| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | @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<>(); |
| | | |
| | | /** |
| | | * 流离开的处理 |
| | |
| | | @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); |
| | | } |
| | |
| | | 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) { |
| | |
| | | })); |
| | | } |
| | | |
| | | 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; |
| | |
| | | */ |
| | | @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)); |
| | | // } |
| | | // } |
| | | // } |
| | | } |
| | | |
| | | /** |
| | |
| | | * @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) { |
| | |
| | | } |
| | | |
| | | // 查看是否有人观看,存在则不做处理,等待后续自然处理,如果无人观看,则关闭该流 |
| | | 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) { |