liusuyi
2026-05-12 9f327c33730ba10cb2d89aff99b727502232e968
ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/ZlmRecordPlanServiceImpl.java
@@ -1,5 +1,7 @@
package com.ard.zlm.service.impl;
import com.ard.work.api.RemoteChannelService;
import com.ard.work.api.domian.ArdChannel;
import com.google.common.base.Joiner;
import com.ard.common.core.constant.HttpStatus;
import com.ard.common.core.constant.SecurityConstants;
@@ -21,6 +23,7 @@
import com.ard.zlm.service.IDevicePlayService;
import com.ard.zlm.service.IMediaServerService;
import com.ard.zlm.service.IZlmRecordPlanService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
@@ -41,23 +44,24 @@
@Service
@Transactional(rollbackFor = Exception.class)
public class ZlmRecordPlanServiceImpl implements IZlmRecordPlanService {
    @Autowired
    @Resource
    private ZlmRecordPlanMapper zlmRecordPlanMapper;
    @Autowired
    @Resource
    private ZlmRecordPlanItemMapper zlmRecordPlanItemMapper;
    @Autowired
    @Resource
    private RemoteQsDeviceService remoteQsDeviceService;
    @Autowired
    @Resource
    private RemoteChannelService remoteChannelService;
    @Resource
    private IMediaServerService mediaServerService;
    @Autowired
    @Resource
    private IDevicePlayService devicePlayService;
    Map<Long, StreamInfo> recordStreamMap = new HashMap<>();
    Map<String, StreamInfo> recordStreamMap = new HashMap<>();
    /**
     * 流离开的处理
@@ -66,17 +70,18 @@
    @EventListener
    public void onApplicationEvent(MediaDepartureEvent event) {
        // 流断开,检查是否还处于录像状态, 如果是则继续录像
        Long deviceId = recording(event.getApp(), event.getStream());
        String deviceId = recording(event.getApp(), event.getStream());
        if (deviceId == null) {
            return;
        }
        // 重新拉起
        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
        R<ArdChannel> r = remoteChannelService.getInfo(deviceId, SecurityConstants.INNER);
        //  R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
        if (r.getCode() != HttpStatus.SUCCESS) {
            throw new RuntimeException("根据设备id查询设备信息失败");
        }
        QsDevice device = r.getData();
        ArdChannel device = r.getData();
        if (device == null) {
            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备不存在, id: {}", deviceId);
        }
@@ -86,10 +91,10 @@
            return;
        }
        if ("OFFLINE".equals(device.getDeviceStatus())) {
            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备不在线, id: {}", deviceId);
            return;
        }
//        if ("OFFLINE".equals(device.getDeviceStatus())) {
//            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备不在线, id: {}", deviceId);
//            return;
//        }
        // 开启点播,
        devicePlayService.play(device, true, ((code, msg, streamInfo) -> {
            if (code == InviteErrorCode.SUCCESS.getCode() && streamInfo != null) {
@@ -102,8 +107,8 @@
        }));
    }
    public Long recording(String app, String stream) {
        for (Long deviceId : recordStreamMap.keySet()) {
    public String recording(String app, String stream) {
        for (String deviceId : recordStreamMap.keySet()) {
            StreamInfo streamInfo = recordStreamMap.get(deviceId);
            if (streamInfo != null && streamInfo.getApp().equals(app) && streamInfo.getStream().equals(stream)) {
                return deviceId;
@@ -222,59 +227,60 @@
     */
    @Override
    public void task() {
        List<Long> startDeviceIdList = queryCurrentChannelRecord();
        if (startDeviceIdList.isEmpty()) {
            // 当前没有录像任务, 如果存在旧的正在录像的就移除
            if (!recordStreamMap.isEmpty()) {
                Set<Long> recordStreamSet = new HashSet<>(recordStreamMap.keySet());
                stopStreams(recordStreamSet, recordStreamMap);
                recordStreamMap.clear();
            }
        } else {
            // 当前存在录像任务, 获取正在录像中存在但是当前录制列表不存在的内容,进行停止; 获取正在录像中没有但是当前需录制的列表中存在的进行开启.
            Set<Long> recordStreamSet = new HashSet<>(recordStreamMap.keySet());
            startDeviceIdList.forEach(recordStreamSet::remove);
            if (!recordStreamSet.isEmpty()) {
                // 正在录像中存在但是当前录制列表不存在的内容,进行停止;
                stopStreams(recordStreamSet, recordStreamMap);
            }
            // 移除startDeviceIdList中已经在录像的部分, 剩下的都是需要新添加的(正在录像中没有但是当前需录制的列表中存在的进行开启)
            recordStreamMap.keySet().forEach(startDeviceIdList::remove);
            if (!startDeviceIdList.isEmpty()) {
                // 获取所有的关联的设备
                R<List<QsDevice>> r = remoteQsDeviceService.queryByIds(startDeviceIdList, SecurityConstants.INNER);
                if (r.getCode() != HttpStatus.SUCCESS) {
                    throw new RuntimeException("根据设备id集合查询设备信息失败");
                }
                List<QsDevice> deviceList = r.getData();
                if (!deviceList.isEmpty()) {
                    // 查找是否已经开启录像, 如果没有则开启录像
                    for (QsDevice device : deviceList) {
                        if ("OFFLINE".equals(device.getDeviceStatus())) {
                            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备不在线, id: {}", device.getId());
                            return;
                        }
                        if ("DEACTIVATE".equals(device.getStatus())) {
                            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备未启用, id: {}", device.getId());
                            return;
                        }
                        // 开启点播,
                        devicePlayService.play(device, true, ((code, msg, streamInfo) -> {
                            if (code == InviteErrorCode.SUCCESS.getCode() && streamInfo != null) {
                                log.info("[录像] 开启成功, 设备ID: {}", device.getId());
                                recordStreamMap.put(device.getId(), streamInfo);
                            } else {
                                log.info("[录像] 开启失败, 十分钟后重试,  设备ID: {}", device.getId());
                            }
                        }));
                    }
                } else {
                    log.error("[录制计划] 数据异常, 这些关联的设备已经不存在了: {}", Joiner.on(",").join(startDeviceIdList));
                }
            }
        }
//        List<String> startDeviceIdList = queryCurrentChannelRecord();
//        if (startDeviceIdList.isEmpty()) {
//            // 当前没有录像任务, 如果存在旧的正在录像的就移除
//            if (!recordStreamMap.isEmpty()) {
//                Set<String> recordStreamSet = new HashSet<>(recordStreamMap.keySet());
//                stopStreams(recordStreamSet, recordStreamMap);
//                recordStreamMap.clear();
//            }
//        } else {
//            // 当前存在录像任务, 获取正在录像中存在但是当前录制列表不存在的内容,进行停止; 获取正在录像中没有但是当前需录制的列表中存在的进行开启.
//            Set<String> recordStreamSet = new HashSet<>(recordStreamMap.keySet());
//            startDeviceIdList.forEach(recordStreamSet::remove);
//            if (!recordStreamSet.isEmpty()) {
//                // 正在录像中存在但是当前录制列表不存在的内容,进行停止;
//                stopStreams(recordStreamSet, recordStreamMap);
//            }
//
//            // 移除startDeviceIdList中已经在录像的部分, 剩下的都是需要新添加的(正在录像中没有但是当前需录制的列表中存在的进行开启)
//            recordStreamMap.keySet().forEach(startDeviceIdList::remove);
//            if (!startDeviceIdList.isEmpty()) {
//                // 获取所有的关联的设备
//              //  R<List<QsDevice>> r = remoteQsDeviceService.queryByIds(startDeviceIdList, SecurityConstants.INNER);
//                R<List<ArdChannel>> r = remoteChannelService.queryByIds(startDeviceIdList, SecurityConstants.INNER);
//                if (r.getCode() != HttpStatus.SUCCESS) {
//                    throw new RuntimeException("根据设备id集合查询设备信息失败");
//                }
//                List<ArdChannel> deviceList = r.getData();
//                if (!deviceList.isEmpty()) {
//                    // 查找是否已经开启录像, 如果没有则开启录像
//                    for (ArdChannel device : deviceList) {
////                        if ("OFFLINE".equals(device.getDeviceStatus())) {
////                            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备不在线, id: {}", device.getId());
////                            return;
////                        }
////
////                        if ("DEACTIVATE".equals(device.getStatus())) {
////                            log.warn("[录制计划] 流离开时拉起需要录像的流时, 发现设备未启用, id: {}", device.getId());
////                            return;
////                        }
//                        // 开启点播,
//                        devicePlayService.play(device, true, ((code, msg, streamInfo) -> {
//                            if (code == InviteErrorCode.SUCCESS.getCode() && streamInfo != null) {
//                                log.info("[录像] 开启成功, 设备ID: {}", device.getId());
//                                recordStreamMap.put(device.getId(), streamInfo);
//                            } else {
//                                log.info("[录像] 开启失败, 十分钟后重试,  设备ID: {}", device.getId());
//                            }
//                        }));
//                    }
//                } else {
//                    log.error("[录制计划] 数据异常, 这些关联的设备已经不存在了: {}", Joiner.on(",").join(startDeviceIdList));
//                }
//            }
//        }
    }
    /**
@@ -283,8 +289,8 @@
     * @param devices         设备ID列表
     * @param recordStreamMap 正在录制的流信息
     */
    private void stopStreams(Collection<Long> devices, Map<Long, StreamInfo> recordStreamMap) {
        for (Long deviceId : devices) {
    private void stopStreams(Collection<String> devices, Map<String, StreamInfo> recordStreamMap) {
        for (String deviceId : devices) {
            try {
                StreamInfo streamInfo = recordStreamMap.get(deviceId);
                if (streamInfo == null) {
@@ -292,50 +298,52 @@
                }
                // 查看是否有人观看,存在则不做处理,等待后续自然处理,如果无人观看,则关闭该流
                MediaInfo mediaInfo = mediaServerService.getMediaInfo(streamInfo.getMediaServer(), streamInfo.getApp(), streamInfo.getStream());
                MediaInfo mediaInfo = mediaServerService.getMediaInfo(streamInfo.getMediaServer(),
                        streamInfo.getApp(), streamInfo.getStream());
                if (mediaInfo.getReaderCount() == null || mediaInfo.getReaderCount() == 0) {
                    R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
                    R<ArdChannel> r = remoteChannelService.getInfo(deviceId, SecurityConstants.INNER);
                    // R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(deviceId, SecurityConstants.INNER);
                    if (r.getCode() != HttpStatus.SUCCESS) {
                        throw new RuntimeException("根据设备id查询设备信息失败");
                        throw new RuntimeException("根据通道id查询设备信息失败");
                    }
                    QsDevice device = r.getData();
                    if (device == null) {
                        throw new RuntimeException("设备不存在");
                    ArdChannel ardChannel = r.getData();
                    if (ardChannel == null) {
                        throw new RuntimeException("通道不存在");
                    }
                    // 播放海康sdk/播放海康isup/播放大华sdk
                    if (LiveStreamType.HIK_SDK.getCode().equals(device.getType())
                            || LiveStreamType.HIK_ISUP.getCode().equals(device.getType())
                            || LiveStreamType.DAHUA_SDK.getCode().equals(device.getType())
                    ) {
                        RTPServerParam rtpServerParam = new RTPServerParam();
                        rtpServerParam.setType(device.getType());
                        rtpServerParam.setStreamId(device.getDeviceCode());
                        rtpServerParam.setId(device.getId());
                        mediaServerService.stopRtpPlay(rtpServerParam);
                    }
//                    if (LiveStreamType.HIK_SDK.getCode().equals(device.getType())
//                            || LiveStreamType.HIK_ISUP.getCode().equals(device.getType())
//                            || LiveStreamType.DAHUA_SDK.getCode().equals(device.getType())
//                    ) {
//                        RTPServerParam rtpServerParam = new RTPServerParam();
//                        rtpServerParam.setType(device.getType());
//                        rtpServerParam.setStreamId(device.getDeviceCode());
//                        rtpServerParam.setId(device.getId());
//
//                        mediaServerService.stopRtpPlay(rtpServerParam);
//                    }
                    // rtsp/rtmp/flv/hls/onvif
                    if (LiveStreamType.RTSP.getCode().equals(device.getType())
                            || LiveStreamType.RTMP.getCode().equals(device.getType())
                            || LiveStreamType.FLV.getCode().equals(device.getType())
                            || LiveStreamType.HLS.getCode().equals(device.getType())
                            || LiveStreamType.ONVIF.getCode().equals(device.getType())
                    if (LiveStreamType.RTSP.getCode().equals(ardChannel.getType())
                            || LiveStreamType.RTMP.getCode().equals(ardChannel.getType())
                            || LiveStreamType.FLV.getCode().equals(ardChannel.getType())
                            || LiveStreamType.HLS.getCode().equals(ardChannel.getType())
                            || LiveStreamType.ONVIF.getCode().equals(ardChannel.getType())
                    ) {
                        StreamPullPlay streamPullPlay = new StreamPullPlay();
                        streamPullPlay.setDeviceId(device.getId());
                        streamPullPlay.setMediaServerId(device.getMediaServerId());
                        streamPullPlay.setStreamKey(device.getStreamKey());
                        streamPullPlay.setChannelId(ardChannel.getId());
                        streamPullPlay.setMediaServerId(ardChannel.getMediaServerId());
                        streamPullPlay.setStreamKey(ardChannel.getStreamKey());
                        mediaServerService.stopStreamPullPlay(streamPullPlay);
                    }
                    // 视频文件
                    if (LiveStreamType.VIDEO_FILE.getCode().equals(device.getType())) {
                        mediaServerService.closeStreams(device.getId());
                    }
//                    if (LiveStreamType.VIDEO_FILE.getCode().equals(device.getType())) {
//                        mediaServerService.closeStreams(device.getId());
//                    }
                    log.info("[录制计划] 停止, 设备ID: {}", deviceId);
                }
            } catch (Exception e) {