添加语音对讲接口

2.7.1-多对一语音对讲
648540858 2024-06-14 16:22:42 +08:00
parent 4ad711f61a
commit 1e67a8dde0
5 changed files with 75 additions and 45 deletions

View File

@ -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 {
// 流注销

View File

@ -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);

View File

@ -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);
});
}

View File

@ -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<WVPResult<Void>> 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<WVPResult<Void>> result = new DeferredResult<>();
result.onTimeout(()->{
WVPResult<Void> 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<Void> wvpResult = new WVPResult<>();
wvpResult.setCode(code);
wvpResult.setMsg(msg);
result.setResult(wvpResult);
});
} catch (InvalidArgumentException | ParseException | SipException e) {
WVPResult<Void> wvpResult = new WVPResult<>();
wvpResult.setCode(-1);
wvpResult.setMsg("请求失败:" + e.getMessage());
result.setResult(wvpResult);
}
return result;
}

View File

@ -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);
}