diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index 63239b78..f2ed5be4 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -411,7 +411,7 @@ public class ZLMHttpHookListener { } // 开启语音对讲通道 try { - playService.audioBroadcastCmd(device, channelId, mediaInfo, param.getApp(), param.getStream(), 60, false, (msg) -> { + playService.audioBroadcastCmd(device, channelId, mediaInfo, param.getApp(), param.getStream(), 60, false, (code, msg) -> { logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); }); } catch (InvalidArgumentException | ParseException | SipException e) { @@ -440,8 +440,12 @@ public class ZLMHttpHookListener { playService.stopAudioBroadcast(deviceId, channelId); } // 开启语音对讲通道 - playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (msg) -> { - logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); + playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (code, msg) -> { + if (code == 0) { + logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); + }else { + logger.info("[语音对讲] 通道建立失败,{}, device: {}, channel: {}", msg, deviceId, channelId); + } }); } else { // 流注销 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java index 77525e88..16346e02 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -47,7 +47,7 @@ public interface IPlayService { AudioBroadcastResult audioBroadcast(Device device, String channelId, Boolean broadcastMode); - boolean audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; + boolean audioBroadcastCmd(Device device, DeviceChannel channel, MediaServerItem mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; boolean audioBroadcastInUse(Device device, String channelId); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java index 26867eed..6b3a0f4b 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -220,7 +220,7 @@ public class PlayServiceImpl implements IPlayService { String playSsrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); if (playSsrc == null) { - audioEvent.call("ssrc已经用尽"); + audioEvent.call(-1,"ssrc已经用尽"); return; } SendRtpItem sendRtpItem = new SendRtpItem(); @@ -246,7 +246,7 @@ public class PlayServiceImpl implements IPlayService { //端口获取失败的ssrcInfo 没有必要发送点播指令 if (port <= 0) { logger.info("[语音对讲] 端口分配异常,deviceId={},channelId={}", device.getDeviceId(), channelId); - audioEvent.call("端口分配异常"); + audioEvent.call(-1,"端口分配异常"); return; } sendRtpItem.setLocalPort(port); @@ -287,7 +287,7 @@ public class PlayServiceImpl implements IPlayService { if (jsonObject == null || jsonObject.getInteger("code") != 0 ) { mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); logger.info("[语音对讲]失败 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); - audioEvent.call("失败, " + jsonObject.getString("msg")); + audioEvent.call(-1,"失败, " + jsonObject.getString("msg")); // 查看是否已经建立了通道,存在则发送bye stopTalk(device, channelId); } @@ -349,8 +349,6 @@ public class PlayServiceImpl implements IPlayService { eventResult.msg = "命令发送失败"; errorEvent.response(eventResult); } -// } - } @@ -1123,7 +1121,7 @@ public class PlayServiceImpl implements IPlayService { DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); if (deviceChannel == null) { logger.warn("开启语音广播的时候未找到通道: {}", channelId); - event.call("开启语音广播的时候未找到通道"); + event.call(-1, "开启语音广播的时候未找到通道"); return false; } // 查询通道使用状态 @@ -1134,25 +1132,13 @@ public class PlayServiceImpl implements IPlayService { Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream()); if (streamReady) { logger.warn("语音广播已经开启: {}", channelId); - event.call("语音广播已经开启"); + event.call(-1,"语音广播已经开启"); return false; } else { stopAudioBroadcast(device.getDeviceId(), channelId); } } } -// SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); -// if (sendRtpItem != null) { -// MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); -// Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); -// if (streamReady) { -// logger.warn("[语音对讲] 进行中: {}", channelId); -// event.call("语音对讲进行中"); -// return false; -// } else { -// stopTalk(device, channelId); -// } -// } // 发送通知 cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> { @@ -1166,12 +1152,13 @@ public class PlayServiceImpl implements IPlayService { } dynamicTask.startDelay(key, ()->{ logger.info("[语音广播]等待invite消息超时:{}/{}", device.getDeviceId(), channelId); + event.call(-1,"等待invite消息超时"); stopAudioBroadcast(device.getDeviceId(), channelId); }, 10*1000); }, eventResultForError -> { // 发送失败 logger.error("语音广播发送失败: {}:{}", channelId, eventResultForError.msg); - event.call("语音广播发送失败"); + event.call(-1,"语音广播发送失败"); stopAudioBroadcast(device.getDeviceId(), channelId); }); return true; @@ -1443,7 +1430,7 @@ public class PlayServiceImpl implements IPlayService { DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); if (deviceChannel == null) { logger.warn("开启语音对讲的时候未找到通道: {}", channelId); - event.call("开启语音对讲的时候未找到通道"); + event.call(-1,"开启语音对讲的时候未找到通道"); return; } // 查询通道使用状态 @@ -1455,7 +1442,7 @@ public class PlayServiceImpl implements IPlayService { Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); if (streamReady) { logger.warn("[语音对讲] 正在语音广播,无法开启语音通话: {}", channelId); - event.call("正在语音广播"); + event.call(-1, "正在语音广播"); return; } else { stopAudioBroadcast(device.getDeviceId(), channelId); @@ -1469,7 +1456,7 @@ public class PlayServiceImpl implements IPlayService { Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, "rtp", sendRtpItem.getReceiveStream()); if (streamReady) { logger.warn("[语音对讲] 进行中: {}", channelId); - event.call("语音对讲进行中"); + event.call(-1,"语音对讲进行中"); return; } else { stopTalk(device, channelId); @@ -1480,14 +1467,14 @@ public class PlayServiceImpl implements IPlayService { logger.info("[语音对讲] 收到设备发来的流"); }, eventResult -> { logger.warn("[语音对讲] 失败,{}/{}, 错误码 {} {}", device.getDeviceId(), channelId, eventResult.statusCode, eventResult.msg); - event.call("失败,错误码 " + eventResult.statusCode + ", " + eventResult.msg); + event.call(-1,"失败,错误码 " + eventResult.statusCode + ", " + eventResult.msg); }, () -> { logger.warn("[语音对讲] 失败,{}/{} 超时", device.getDeviceId(), channelId); - event.call("失败,超时 "); + event.call(-1,"失败,超时 "); stopTalk(device, channelId); - }, errorMsg -> { - logger.warn("[语音对讲] 失败,{}/{} {}", device.getDeviceId(), channelId, errorMsg); - event.call(errorMsg); + }, (code, msg) -> { + logger.warn("[语音对讲] 失败,{}/{} {}", device.getDeviceId(), channelId, msg); + event.call(code, msg); stopTalk(device, channelId); }); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java index 8e1207a1..0623c18a 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; @@ -18,10 +19,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.service.IInviteStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IMediaService; -import com.genersoft.iot.vmp.service.IPlayService; +import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.InviteErrorCode; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; @@ -95,6 +93,12 @@ public class PlayController { @Autowired private UserSetting userSetting; + @Autowired + private IDeviceService deviceService; + + @Autowired + private IDeviceChannelService channelService; + @Operation(summary = "开始点播", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) @@ -236,25 +240,60 @@ public class PlayController { } } - @Operation(summary = "语音广播命令", security = @SecurityRequirement(name = JwtUtils.HEADER)) + @Operation(summary = "开始语音广播", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "通道国标编号", required = true) - @Parameter(name = "timeout", description = "推流超时时间(秒)", required = true) - @GetMapping("/broadcast/{deviceId}/{channelId}") - @PostMapping("/broadcast/{deviceId}/{channelId}") - public AudioBroadcastResult broadcastApi(@PathVariable String deviceId, @PathVariable String channelId, Integer timeout, Boolean broadcastMode) { + @Parameter(name = "mediaServerId", description = "流媒体ID", required = false) + @Parameter(name = "app", description = "用于广播的应用名", required = true) + @Parameter(name = "stream", description = "用于广播的流ID", required = true) + @GetMapping("/broadcast/start") + @PostMapping("/broadcast/start") + public DeferredResult> broadcastApi(String deviceId, String channelId, @RequestParam(required = false) String mediaServerId, String app, String stream) { if (logger.isDebugEnabled()) { logger.debug("语音广播API调用"); } - Device device = storager.queryVideoDevice(deviceId); + Device device = deviceService.getDevice(deviceId); if (device == null) { throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到设备: " + deviceId); } - if (channelId == null) { + DeviceChannel channel = channelService.getOne(deviceId, channelId); + if (channel == null) { throw new ControllerException(ErrorCode.ERROR400.getCode(), "未找到通道: " + channelId); } + MediaServerItem mediaServerItem; + if (ObjectUtils.isEmpty(mediaServerId)) { + mediaServerItem = mediaServerService.getDefaultMediaServer(); + }else { + mediaServerItem = mediaServerService.getOne(mediaServerId); + } + JSONObject jsonObject = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", stream); + if (jsonObject == null || jsonObject.getInteger("code") != 0) { + throw new ControllerException(ErrorCode.ERROR400.getCode(), "推流信息不存在"); + } - return playService.audioBroadcast(device, channelId, broadcastMode); + DeferredResult> result = new DeferredResult<>(); + + result.onTimeout(()->{ + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("请求超时"); + result.setResult(wvpResult); + playService.stopAudioBroadcast(); + }); + try { + playService.audioBroadcastCmd(device, channelId, mediaServerItem, app, stream, 60, false, (code, msg) -> { + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(code); + wvpResult.setMsg(msg); + result.setResult(wvpResult); + }); + } catch (InvalidArgumentException | ParseException | SipException e) { + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("请求失败:" + e.getMessage()); + result.setResult(wvpResult); + } + return result; } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java index 55b710f2..fc53ccc3 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java @@ -5,5 +5,5 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play.bean; * @author lin */ public interface AudioBroadcastEvent { - void call(String msg); + void call(int code, String msg); }