648540858
2024-03-21 b90dc789b429c31674c26bb3ff309b987afaa77a
优化媒体节点服务的代码结构
64个文件已修改
2 文件已重命名
1296 ■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaNodeServerService.java 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/event/MediaServerChangeEvent.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaServerStatusManger.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServer.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerKeepaliveEvent.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerStartEvent.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java 185 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.common;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -71,7 +71,7 @@
    @Schema(description = "流媒体ID")
    private String mediaServerId;
    @Schema(description = "流编码信息")
    private Track track;
    private MediaInfo mediaInfo;
    @Schema(description = "开始时间")
    private String startTime;
    @Schema(description = "结束时间")
@@ -474,12 +474,12 @@
        this.mediaServerId = mediaServerId;
    }
    public Track getTrack() {
        return track;
    public MediaInfo getMediaInfo() {
        return mediaInfo;
    }
    public void setTrack(Track track) {
        this.track = track;
    public void setMediaInfo(MediaInfo mediaInfo) {
        this.mediaInfo = mediaInfo;
    }
    public String getStartTime() {
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -12,7 +12,7 @@
    public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_";
    public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
    public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_INFO_";
    public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_";
src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java
@@ -1,9 +1,7 @@
package com.genersoft.iot.vmp.conf;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
@@ -40,12 +38,12 @@
    public void execute(){
        logger.info("[录像文件定时清理] 开始清理过期录像文件");
        // 获取配置了assist的流媒体节点
        List<MediaServerItem> mediaServerItemList =  mediaServerService.getAllOnline();
        List<MediaServer> mediaServerItemList =  mediaServerService.getAllOnline();
        if (mediaServerItemList.isEmpty()) {
            return;
        }
        long result = 0;
        for (MediaServerItem mediaServerItem : mediaServerItemList) {
        for (MediaServer mediaServerItem : mediaServerItemList) {
            Calendar lastCalendar = Calendar.getInstance();
            if (mediaServerItem.getRecordDay() > 0) {
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -199,8 +199,8 @@
        return sipDomain;
    }
    public MediaServerItem getMediaSerItem(){
        MediaServerItem mediaServerItem = new MediaServerItem();
    public MediaServer getMediaSerItem(){
        MediaServer mediaServerItem = new MediaServer();
        mediaServerItem.setId(id);
        mediaServerItem.setIp(ip);
        mediaServerItem.setDefaultServer(true);
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
@@ -54,7 +54,7 @@
        @Override
        protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
            String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
            MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
            MediaServer mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
            if (mediaInfo != null) {
                if (!ObjectUtils.isEmpty(queryStr)) {
                    queryStr += "&secret=" + mediaInfo.getSecret();
@@ -103,7 +103,7 @@
        @Override
        protected String getTargetUri(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            MediaServer mediaInfo = getMediaInfoByUri(requestURI);
            String uri = null;
            if (mediaInfo != null) {
@@ -121,7 +121,7 @@
        @Override
        protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            MediaServer mediaInfo = getMediaInfoByUri(requestURI);
            HttpHost host;
            if (mediaInfo != null) {
                host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
@@ -135,7 +135,7 @@
        /**
         * 根据uri获取流媒体信息
         */
        MediaServerItem getMediaInfoByUri(String uri){
        MediaServer getMediaInfoByUri(String uri){
            String[] split = uri.split("/");
            String mediaServerId = split[2];
            if ("default".equalsIgnoreCase(mediaServerId)) {
@@ -151,7 +151,7 @@
        @Override
        protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            MediaServer mediaInfo = getMediaInfoByUri(requestURI);
            String url = super.rewriteUrlFromRequest(servletRequest);
            if (mediaInfo == null) {
                logger.error("[ZLM服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
@@ -181,7 +181,7 @@
        @Override
        protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
            String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
            MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
            MediaServer mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
            if (mediaInfo == null) {
                return null;
            }
@@ -238,7 +238,7 @@
        @Override
        protected String getTargetUri(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            MediaServer mediaInfo = getMediaInfoByUri(requestURI);
            String uri = null;
            if (mediaInfo != null) {
@@ -256,7 +256,7 @@
        @Override
        protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            MediaServer mediaInfo = getMediaInfoByUri(requestURI);
            HttpHost host;
            if (mediaInfo != null) {
                host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
@@ -270,7 +270,7 @@
        /**
         * 根据uri获取流媒体信息
         */
        MediaServerItem getMediaInfoByUri(String uri){
        MediaServer getMediaInfoByUri(String uri){
            String[] split = uri.split("/");
            String mediaServerId = split[2];
            if ("default".equalsIgnoreCase(mediaServerId)) {
@@ -287,7 +287,7 @@
        @Override
        protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
            String requestURI = servletRequest.getRequestURI();
            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
            MediaServer mediaInfo = getMediaInfoByUri(requestURI);
            String url = super.rewriteUrlFromRequest(servletRequest);
            if (mediaInfo == null) {
                logger.error("[录像服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java
@@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
import gov.nist.javax.sip.message.SIPResponse;
@@ -15,7 +15,7 @@
    public AudioBroadcastCatch(
            String deviceId,
            String channelId,
            MediaServerItem mediaServerItem,
            MediaServer mediaServerItem,
            String app,
            String stream,
            AudioBroadcastEvent event,
@@ -48,7 +48,7 @@
    /**
     * 流媒体信息
     */
    private MediaServerItem mediaServerItem;
    private MediaServer mediaServerItem;
    /**
     * 关联的流APP
@@ -109,11 +109,11 @@
        return sipTransactionInfo;
    }
    public MediaServerItem getMediaServerItem() {
    public MediaServer getMediaServerItem() {
        return mediaServerItem;
    }
    public void setMediaServerItem(MediaServerItem mediaServerItem) {
    public void setMediaServerItem(MediaServer mediaServerItem) {
        this.mediaServerItem = mediaServerItem;
    }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java
@@ -1,11 +1,11 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
public class InviteStreamInfo {
    public InviteStreamInfo(MediaServerItem mediaServerItem, JSONObject response, String callId, String app, String stream) {
    public InviteStreamInfo(MediaServer mediaServerItem, JSONObject response, String callId, String app, String stream) {
        this.mediaServerItem = mediaServerItem;
        this.response = response;
        this.callId = callId;
@@ -13,17 +13,17 @@
        this.stream = stream;
    }
    private MediaServerItem mediaServerItem;
    private MediaServer mediaServerItem;
    private JSONObject response;
    private String callId;
    private String app;
    private String stream;
    public MediaServerItem getMediaServerItem() {
    public MediaServer getMediaServerItem() {
        return mediaServerItem;
    }
    public void setMediaServerItem(MediaServerItem mediaServerItem) {
    public void setMediaServerItem(MediaServer mediaServerItem) {
        this.mediaServerItem = mediaServerItem;
    }
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
@@ -1,14 +1,12 @@
package com.genersoft.iot.vmp.gb28181.task;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlatformService;
@@ -102,7 +100,7 @@
        List<SendRtpItem> sendRtpItems = redisCatchStorage.queryAllSendRTPServer();
        if (sendRtpItems.size() > 0) {
            for (SendRtpItem sendRtpItem : sendRtpItems) {
                MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                MediaServer mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream());
                if (mediaServerItem != null) {
                    ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -8,7 +8,7 @@
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import gov.nist.javax.sip.message.SIPRequest;
@@ -100,7 +100,7 @@
     * @param device  视频设备
     * @param channel  预览通道
     */
    void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    /**
     * 请求回放视频流
@@ -110,7 +110,7 @@
     * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
     * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
     */
    void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    /**
     * 请求历史媒体下载
@@ -121,9 +121,9 @@
     * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
     * @param downloadSpeed 下载倍速参数
     */ 
    void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
                           String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent,
                           SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
    void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
                           String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent,
                           SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
    /**
@@ -131,7 +131,7 @@
     */
    void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
    void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    void talkStreamCmd(MediaServer mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
    void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
@@ -4,7 +4,7 @@
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -154,7 +154,7 @@
    void streamByeCmd(ParentPlatform platform, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
    void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem,
    void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServer mediaServerItem,
                            SSRCInfo ssrcInfo, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent,
                            SipSubscribe.Event errorEvent) throws ParseException, SipException, InvalidArgumentException;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -23,7 +23,7 @@
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamPush;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -274,7 +274,7 @@
     * @param errorEvent sip错误订阅
     */
    @Override
    public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
    public void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
                              ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
        String stream = ssrcInfo.getStream();
@@ -284,7 +284,7 @@
        logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
        subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
        subscribe.addSubscribe(hookSubscribe, (MediaServer mediaServerItemInUse, HookParam hookParam) -> {
            if (event != null) {
                event.response(mediaServerItemInUse, hookParam);
                subscribe.removeSubscribe(hookSubscribe);
@@ -383,7 +383,7 @@
     * @param endTime   结束时间,格式要求:yyyy-MM-dd HH:mm:ss
     */
    @Override
    public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
    public void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
                                  String startTime, String endTime, ZlmHttpHookSubscribe.Event hookEvent,
                                  SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
@@ -459,7 +459,7 @@
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
        // 添加订阅
        subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
        subscribe.addSubscribe(hookSubscribe, (MediaServer mediaServerItemInUse, HookParam hookParam) -> {
            if (hookEvent != null) {
                hookEvent.response(mediaServerItemInUse, hookParam);
            }
@@ -485,10 +485,10 @@
     * @param downloadSpeed 下载倍速参数
     */
    @Override
    public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
    public void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
                                  String startTime, String endTime, int downloadSpeed,
                                  ZlmHttpHookSubscribe.Event hookEvent,
                                  SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
                                  SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
        logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
        String sdpIp;
@@ -594,7 +594,7 @@
    }
    @Override
    public void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
    public void talkStreamCmd(MediaServer mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
        String stream = sendRtpItem.getStream();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -17,7 +17,7 @@
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
@@ -844,7 +844,7 @@
        }
        logger.info("[向上级发送BYE], {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId());
        String mediaServerId = sendRtpItem.getMediaServerId();
        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
        if (mediaServerItem != null) {
            mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
            zlmServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStream());
@@ -895,7 +895,7 @@
    }
    @Override
    public void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem,
    public void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServer mediaServerItem,
                                   SSRCInfo ssrcInfo, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent,
                                   SipSubscribe.Event errorEvent) throws ParseException, SipException, InvalidArgumentException {
        String stream = ssrcInfo.getStream();
@@ -906,7 +906,7 @@
        logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
        subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
        subscribe.addSubscribe(hookSubscribe, (MediaServer mediaServerItemInUse, HookParam hookParam) -> {
            if (event != null) {
                event.response(mediaServerItemInUse, hookParam);
                subscribe.removeSubscribe(hookSubscribe);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -11,7 +11,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlayService;
@@ -104,7 +104,7 @@
            logger.info("收到ACK,rtp/{} TCP主动方式后续处理", sendRtpItem.getStream());
            return;
        }
        MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
        MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
        logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}, 协议:{}",
                sendRtpItem.getStream(),
                sendRtpItem.getIp(),
@@ -173,7 +173,7 @@
        return param;
    }
    private JSONObject sendRtp(SendRtpItem sendRtpItem, MediaServerItem mediaInfo, Map<String, Object> param){
    private JSONObject sendRtp(SendRtpItem sendRtpItem, MediaServer mediaInfo, Map<String, Object> param){
        JSONObject startSendRtpStreamResult = null;
        if (sendRtpItem.getLocalPort() != 0) {
            if (sendRtpItem.isTcpActive()) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -15,7 +15,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.*;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
@@ -146,7 +146,7 @@
                        redisGbPlayMsgListener.sendMsgForStopSendRtpStream(sendRtpItem.getServerId(), streamMsg);
                    }
                }else {
                    MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                    MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                    redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(),
                            callIdHeader.getCallId(), null);
                    zlmServerFactory.stopSendRtpStream(mediaInfo, param);
@@ -166,7 +166,7 @@
                    }
                }
            }else {
                MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(),
                        callIdHeader.getCallId(), null);
                zlmServerFactory.stopSendRtpStream(mediaInfo, param);
@@ -174,7 +174,7 @@
                    mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc());
                }
            }
            MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
            MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
            if (mediaInfo != null) {
                AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
                if (audioBroadcastCatch != null && audioBroadcastCatch.getSipTransactionInfo().getCallId().equals(callIdHeader.getCallId())) {
@@ -246,7 +246,7 @@
                }
            }
            // 释放ssrc
            MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
            MediaServer mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
            if (mediaServerItem != null) {
                mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc());
            }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -192,7 +192,7 @@
                GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
                PlatformCatalog catalog = storager.getCatalog(requesterId, channelId);
                MediaServerItem mediaServerItem = null;
                MediaServer mediaServerItem = null;
                StreamPushItem streamPushItem = null;
                StreamProxyItem proxyByAppAndStream = null;
                // 不是通道可能是直播流
@@ -398,7 +398,7 @@
                    Long finalStopTime = stopTime;
                    ErrorCallback<Object> hookEvent = (code, msg, data) -> {
                        StreamInfo streamInfo = (StreamInfo)data;
                        MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId());
                        MediaServer mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId());
                        logger.info("[上级Invite]下级已经开始推流。 回复200OK(SDP), {}/{}", streamInfo.getApp(), streamInfo.getStream());
                        //     * 0 等待设备推流上来
                        //     * 1 下级已经推流,等待上级平台回复ack
@@ -452,7 +452,7 @@
                            responseSdpAck(request, content.toString(), platform);
                            // tcp主动模式,回复sdp后开启监听
                            if (sendRtpItem.isTcpActive()) {
                                MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                                MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                                Map<String, Object> param = new HashMap<>(12);
                                param.put("vhost","__defaultVhost__");
                                param.put("app",sendRtpItem.getApp());
@@ -624,7 +624,7 @@
     * 安排推流
     */
    private void pushProxyStream(RequestEvent evt, SIPRequest request, GbStream gbStream, ParentPlatform platform,
                            CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                            CallIdHeader callIdHeader, MediaServer mediaServerItem,
                            int port, Boolean tcpActive, boolean mediaTransmissionTCP,
                            String channelId, String addressStr, String ssrc, String requesterId) {
            Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
@@ -662,7 +662,7 @@
    }
    private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
                            CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                            CallIdHeader callIdHeader, MediaServer mediaServerItem,
                            int port, Boolean tcpActive, boolean mediaTransmissionTCP,
                            String channelId, String addressStr, String ssrc, String requesterId) {
        // 推流
@@ -714,7 +714,7 @@
     * 通知流上线
     */
    private void notifyStreamOnline(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
                                    CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                                    CallIdHeader callIdHeader, MediaServer mediaServerItem,
                                    int port, Boolean tcpActive, boolean mediaTransmissionTCP,
                                    String channelId, String addressStr, String ssrc, String requesterId) {
        if ("proxy".equals(gbStream.getStreamType())) {
@@ -837,7 +837,7 @@
     * 来自其他wvp的推流
     */
    private void otherWvpPushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
                                    CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                                    CallIdHeader callIdHeader, MediaServer mediaServerItem,
                                    int port, Boolean tcpActive, boolean mediaTransmissionTCP,
                                    String channelId, String addressStr, String ssrc, String requesterId) {
        logger.info("[级联点播]直播流来自其他平台,发送redis消息");
@@ -900,7 +900,7 @@
                });
    }
    public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
    public SIPResponse sendStreamAck(MediaServer mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) {
        StringBuffer content = new StringBuffer(200);
        content.append("v=0\r\n");
@@ -1042,7 +1042,7 @@
                logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}, {}", requesterId, addressStr, port, gb28181Sdp.getSsrc(),
                        mediaTransmissionTCP ? (tcpActive ? "TCP主动" : "TCP被动") : "UDP");
                MediaServerItem mediaServerItem = broadcastCatch.getMediaServerItem();
                MediaServer mediaServerItem = broadcastCatch.getMediaServerItem();
                if (mediaServerItem == null) {
                    logger.warn("未找到语音喊话使用的zlm");
                    try {
@@ -1119,7 +1119,7 @@
        }
    }
    SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc) {
    SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServer mediaServerItem, boolean mediaTransmissionTCP, String ssrc) {
        SIPResponse sipResponse = null;
        try {
            sendRtpItem.setStatus(2);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java
@@ -8,7 +8,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
@@ -120,7 +120,7 @@
                return;
            }
            MediaServerItem mediaServerForMinimumLoad = mediaServerService.getMediaServerForMinimumLoad(null);
            MediaServer mediaServerForMinimumLoad = mediaServerService.getMediaServerForMinimumLoad(null);
            commanderForPlatform.broadcastResultCmd(platform, deviceChannel, sn, true,  eventResult->{
                logger.info("[国标级联] 语音喊话 回复失败 platform: {}, 错误:{}/{}", platform.getServerGBId(), eventResult.statusCode, eventResult.msg);
            }, eventResult->{
src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java
@@ -3,7 +3,7 @@
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -37,15 +37,15 @@
    public void run(String... strings) throws Exception {
        // 清理所有在线节点的缓存信息
        mediaServerService.clearMediaServerForOnline();
        MediaServerItem defaultMediaServer = mediaServerService.getDefaultMediaServer();
        MediaServerItem mediaSerItemInConfig = mediaConfig.getMediaSerItem();
        MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer();
        MediaServer mediaSerItemInConfig = mediaConfig.getMediaSerItem();
        if (defaultMediaServer != null && mediaSerItemInConfig.getId().equals(defaultMediaServer.getId())) {
            mediaServerService.update(mediaSerItemInConfig);
        }else {
            if (defaultMediaServer != null) {
                mediaServerService.delete(defaultMediaServer.getId());
            }
            MediaServerItem mediaServerItem = mediaServerService.getOneFromDatabase(mediaSerItemInConfig.getId());
            MediaServer mediaServerItem = mediaServerService.getOneFromDatabase(mediaSerItemInConfig.getId());
            if (mediaServerItem == null) {
                mediaServerService.add(mediaSerItemInConfig);
            }else {
@@ -55,7 +55,7 @@
        // 发送媒体节点变化事件
        mediaServerService.syncCatchFromDatabase();
        // 获取所有的zlm, 并开启主动连接
        List<MediaServerItem> all = mediaServerService.getAllFromDatabase();
        List<MediaServer> all = mediaServerService.getAllFromDatabase();
        logger.info("[媒体节点] 加载节点列表, 共{}个节点", all.size());
        MediaServerChangeEvent event = new MediaServerChangeEvent(this);
        event.setMediaServerItemList(all);
src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaNodeServerService.java
@@ -2,8 +2,9 @@
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.service.IMediaNodeServerService;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -12,57 +13,72 @@
public class ABLMediaNodeServerService implements IMediaNodeServerService {
    @Override
    public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
    public int createRTPServer(MediaServer mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
        return 0;
    }
    @Override
    public void closeRtpServer(MediaServerItem mediaServerItem, String streamId) {
    public void closeRtpServer(MediaServer mediaServerItem, String streamId) {
    }
    @Override
    public void closeRtpServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
    public void closeRtpServer(MediaServer mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
    }
    @Override
    public void closeStreams(MediaServerItem mediaServerItem, String rtp, String streamId) {
    public void closeStreams(MediaServer mediaServerItem, String rtp, String streamId) {
    }
    @Override
    public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) {
    public Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) {
        return null;
    }
    @Override
    public boolean checkNodeId(MediaServerItem mediaServerItem) {
    public boolean checkNodeId(MediaServer mediaServerItem) {
        return false;
    }
    @Override
    public void online(MediaServerItem mediaServerItem) {
    public void online(MediaServer mediaServerItem) {
    }
    @Override
    public MediaServerItem checkMediaServer(String ip, int port, String secret) {
    public MediaServer checkMediaServer(String ip, int port, String secret) {
        return null;
    }
    @Override
    public boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc) {
    public boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) {
        return false;
    }
    @Override
    public boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) {
    public boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName) {
        return false;
    }
    @Override
    public List<StreamInfo> getMediaList(MediaServerItem mediaServerItem, String app, String stream, String callId) {
    public List<StreamInfo> getMediaList(MediaServer mediaServerItem, String app, String stream, String callId) {
        return null;
    }
    @Override
    public Boolean connectRtpServer(MediaServer mediaServerItem, String address, int port, String stream) {
        return null;
    }
    @Override
    public void getSnap(MediaServer mediaServerItem, String streamUrl, int timeoutSec, int expireSec, String path, String fileName) {
    }
    @Override
    public MediaInfo getMediaInfo(MediaServer mediaServerItem, String app, String stream) {
        return null;
    }
}
src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java
File was renamed from src/main/java/com/genersoft/iot/vmp/media/bean/Track.java
@@ -11,7 +11,7 @@
 * 视频信息
 */
@Schema(description = "视频信息")
public class Track {
public class MediaInfo {
    @Schema(description = "观看人数")
    private Integer readerCount;
    @Schema(description = "视频编码类型")
@@ -26,12 +26,14 @@
    private Integer audioChannels;
    @Schema(description = "音频采样率")
    private Integer audioSampleRate;
    @Schema(description = "音频采样率")
    private Long duration;
    public static Track getInstance(JSONObject jsonObject) {
        Track track = new Track();
    public static MediaInfo getInstance(JSONObject jsonObject) {
        MediaInfo mediaInfo = new MediaInfo();
        Integer totalReaderCount = jsonObject.getInteger("totalReaderCount");
        if (totalReaderCount != null) {
            track.setReaderCount(totalReaderCount);
            mediaInfo.setReaderCount(totalReaderCount);
        }
        JSONArray jsonArray = jsonObject.getJSONArray("tracks");
        if (jsonArray.isEmpty()) {
@@ -45,77 +47,81 @@
            Integer sampleRate = trackJson.getInteger("sample_rate");
            Integer height = trackJson.getInteger("height");
            Integer width = trackJson.getInteger("height");
            Long duration = trackJson.getLongValue("duration");
            if (channels != null) {
                track.setAudioChannels(channels);
                mediaInfo.setAudioChannels(channels);
            }
            if (sampleRate != null) {
                track.setAudioSampleRate(sampleRate);
                mediaInfo.setAudioSampleRate(sampleRate);
            }
            if (height != null) {
                track.setHeight(height);
                mediaInfo.setHeight(height);
            }
            if (width != null) {
                track.setWidth(width);
                mediaInfo.setWidth(width);
            }
            if (duration > 0L) {
                mediaInfo.setDuration(duration);
            }
            if (codecId != null) {
                switch (codecId) {
                    case 0:
                        track.setVideoCodec("H264");
                        mediaInfo.setVideoCodec("H264");
                        break;
                    case 1:
                        track.setVideoCodec("H265");
                        mediaInfo.setVideoCodec("H265");
                        break;
                    case 2:
                        track.setAudioCodec("AAC");
                        mediaInfo.setAudioCodec("AAC");
                        break;
                    case 3:
                        track.setAudioCodec("G711A");
                        mediaInfo.setAudioCodec("G711A");
                        break;
                    case 4:
                        track.setAudioCodec("G711U");
                        mediaInfo.setAudioCodec("G711U");
                        break;
                }
            }
        }
        return track;
        return mediaInfo;
    }
    public static Track getInstance(OnStreamChangedHookParam param) {
    public static MediaInfo getInstance(OnStreamChangedHookParam param) {
        List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
        Track track = new Track();
        track.setReaderCount(param.getTotalReaderCount());
        MediaInfo mediaInfo = new MediaInfo();
        mediaInfo.setReaderCount(param.getTotalReaderCount());
        for (OnStreamChangedHookParam.MediaTrack mediaTrack : tracks) {
            switch (mediaTrack.getCodec_id()) {
                case 0:
                    track.setVideoCodec("H264");
                    mediaInfo.setVideoCodec("H264");
                    break;
                case 1:
                    track.setVideoCodec("H265");
                    mediaInfo.setVideoCodec("H265");
                    break;
                case 2:
                    track.setAudioCodec("AAC");
                    mediaInfo.setAudioCodec("AAC");
                    break;
                case 3:
                    track.setAudioCodec("G711A");
                    mediaInfo.setAudioCodec("G711A");
                    break;
                case 4:
                    track.setAudioCodec("G711U");
                    mediaInfo.setAudioCodec("G711U");
                    break;
            }
            if (mediaTrack.getSample_rate() > 0) {
                track.setAudioSampleRate(mediaTrack.getSample_rate());
                mediaInfo.setAudioSampleRate(mediaTrack.getSample_rate());
            }
            if (mediaTrack.getChannels() > 0) {
                track.setAudioChannels(mediaTrack.getChannels());
                mediaInfo.setAudioChannels(mediaTrack.getChannels());
            }
            if (mediaTrack.getHeight() > 0) {
                track.setHeight(mediaTrack.getHeight());
                mediaInfo.setHeight(mediaTrack.getHeight());
            }
            if (mediaTrack.getWidth() > 0) {
                track.setWidth(mediaTrack.getWidth());
                mediaInfo.setWidth(mediaTrack.getWidth());
            }
        }
        return track;
        return mediaInfo;
    }
    public Integer getReaderCount() {
@@ -173,4 +179,12 @@
    public void setAudioSampleRate(Integer audioSampleRate) {
        this.audioSampleRate = audioSampleRate;
    }
    public Long getDuration() {
        return duration;
    }
    public void setDuration(Long duration) {
        this.duration = duration;
    }
}
src/main/java/com/genersoft/iot/vmp/media/event/MediaServerChangeEvent.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.media.event;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import org.springframework.context.ApplicationEvent;
import java.util.ArrayList;
@@ -13,22 +13,22 @@
        super(source);
    }
    private List<MediaServerItem> mediaServerItemList;
    private List<MediaServer> mediaServerItemList;
    public List<MediaServerItem> getMediaServerItemList() {
    public List<MediaServer> getMediaServerItemList() {
        return mediaServerItemList;
    }
    public void setMediaServerItemList(List<MediaServerItem> mediaServerItemList) {
    public void setMediaServerItemList(List<MediaServer> mediaServerItemList) {
        this.mediaServerItemList = mediaServerItemList;
    }
    public void setMediaServerItemList(MediaServerItem... mediaServerItemArray) {
    public void setMediaServerItemList(MediaServer... mediaServerItemArray) {
        this.mediaServerItemList = new ArrayList<>();
        this.mediaServerItemList.addAll(Arrays.asList(mediaServerItemArray));
    }
    public void setMediaServerItem(List<MediaServerItem> mediaServerItemList) {
    public void setMediaServerItem(List<MediaServer> mediaServerItemList) {
        this.mediaServerItemList = mediaServerItemList;
    }
}
src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java
@@ -2,30 +2,41 @@
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import java.util.List;
public interface IMediaNodeServerService {
    int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode);
    int createRTPServer(MediaServer mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode);
    void closeRtpServer(MediaServerItem mediaServerItem, String streamId);
    void closeRtpServer(MediaServer mediaServerItem, String streamId);
    void closeRtpServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback);
    void closeRtpServer(MediaServer mediaServerItem, String streamId, CommonCallback<Boolean> callback);
    void closeStreams(MediaServerItem mediaServerItem, String app, String stream);
    void closeStreams(MediaServer mediaServerItem, String app, String stream);
    Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String stream, String ssrc);
    Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String stream, String ssrc);
    boolean checkNodeId(MediaServerItem mediaServerItem);
    boolean checkNodeId(MediaServer mediaServerItem);
    void online(MediaServerItem mediaServerItem);
    void online(MediaServer mediaServerItem);
    MediaServerItem checkMediaServer(String ip, int port, String secret);
    MediaServer checkMediaServer(String ip, int port, String secret);
    boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc);
    boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc);
    boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName);
    boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName);
    List<StreamInfo> getMediaList(MediaServerItem mediaServerItem, String app, String stream, String callId);
    List<StreamInfo> getMediaList(MediaServer mediaServerItem, String app, String stream, String callId);
    Boolean connectRtpServer(MediaServer mediaServerItem, String address, int port, String stream);
    void getSnap(MediaServer mediaServerItem, String streamUrl, int timeoutSec, int expireSec, String path, String fileName);
    MediaInfo getMediaInfo(MediaServer mediaServerItem, String app, String stream);
    Boolean pauseRtpCheck(MediaServer mediaServerItem, String streamKey);
    Boolean resumeRtpCheck(MediaServer mediaServerItem, String streamKey);
}
src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java
@@ -2,7 +2,8 @@
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.bean.MediaServerLoad;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -13,37 +14,37 @@
 */
public interface IMediaServerService {
    List<MediaServerItem> getAllOnlineList();
    List<MediaServer> getAllOnlineList();
    List<MediaServerItem> getAll();
    List<MediaServer> getAll();
    List<MediaServerItem> getAllFromDatabase();
    List<MediaServer> getAllFromDatabase();
    List<MediaServerItem> getAllOnline();
    List<MediaServer> getAllOnline();
    MediaServerItem getOne(String generalMediaServerId);
    MediaServer getOne(String generalMediaServerId);
    void syncCatchFromDatabase();
    MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist);
    MediaServer getMediaServerForMinimumLoad(Boolean hasAssist);
    void updateVmServer(List<MediaServerItem>  mediaServerItemList);
    void updateVmServer(List<MediaServer>  mediaServerItemList);
    SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck,
    SSRCInfo openRTPServer(MediaServer mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck,
                           boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode);
    SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto);
    SSRCInfo openRTPServer(MediaServer mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto);
    void closeRTPServer(MediaServerItem mediaServerItem, String streamId);
    void closeRTPServer(MediaServer mediaServerItem, String streamId);
    void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback);
    Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc);
    void closeRTPServer(MediaServer mediaServerItem, String streamId, CommonCallback<Boolean> callback);
    Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc);
    void closeRTPServer(String mediaServerId, String streamId);
    void clearRTPServer(MediaServerItem mediaServerItem);
    void clearRTPServer(MediaServer mediaServerItem);
    void update(MediaServerItem mediaSerItem);
    void update(MediaServer mediaSerItem);
    void addCount(String mediaServerId);
@@ -53,27 +54,37 @@
    void clearMediaServerForOnline();
    void add(MediaServerItem mediaSerItem);
    void add(MediaServer mediaSerItem);
    void resetOnlineServerItem(MediaServerItem serverItem);
    void resetOnlineServerItem(MediaServer serverItem);
    MediaServerItem checkMediaServer(String ip, int port, String secret, String type);
    MediaServer checkMediaServer(String ip, int port, String secret, String type);
    boolean checkMediaRecordServer(String ip, int port);
    void delete(String id);
    MediaServerItem getDefaultMediaServer();
    MediaServer getDefaultMediaServer();
    MediaServerLoad getLoad(MediaServerItem mediaServerItem);
    MediaServerLoad getLoad(MediaServer mediaServerItem);
    List<MediaServerItem> getAllWithAssistPort();
    List<MediaServer> getAllWithAssistPort();
    MediaServerItem getOneFromDatabase(String id);
    MediaServer getOneFromDatabase(String id);
    boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc);
    boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc);
    boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName);
    boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName);
    List<StreamInfo> getMediaList(MediaServerItem mediaInfo, String app, String stream, String callId);
    List<StreamInfo> getMediaList(MediaServer mediaInfo, String app, String stream, String callId);
    Boolean connectRtpServer(MediaServer mediaServerItem, String address, int port, String stream);
    void getSnap(MediaServer mediaServerItemInuse, String streamUrl, int timeoutSec, int expireSec, String path, String fileName);
    MediaInfo getMediaInfo(MediaServer mediaServerItem, String app, String stream);
    Boolean pauseRtpCheck(MediaServer mediaServerItem, String streamKey);
    boolean resumeRtpCheck(MediaServer mediaServerItem, String streamKey);
}
src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java
@@ -7,11 +7,12 @@
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent;
import com.genersoft.iot.vmp.media.event.MediaServerDeleteEvent;
import com.genersoft.iot.vmp.media.service.IMediaNodeServerService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.IInviteStreamService;
import com.genersoft.iot.vmp.service.bean.MediaServerLoad;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -73,9 +74,9 @@
     * 初始化
     */
    @Override
    public void updateVmServer(List<MediaServerItem> mediaServerItemList) {
    public void updateVmServer(List<MediaServer> mediaServerItemList) {
        logger.info("[媒体服务节点] 缓存初始化 ");
        for (MediaServerItem mediaServerItem : mediaServerItemList) {
        for (MediaServer mediaServerItem : mediaServerItemList) {
            if (ObjectUtils.isEmpty(mediaServerItem.getId())) {
                continue;
            }
@@ -94,7 +95,7 @@
    @Override
    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck,
    public SSRCInfo openRTPServer(MediaServer mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck,
                                  boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
        if (mediaServerItem == null || mediaServerItem.getId() == null) {
            logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null");
@@ -134,13 +135,13 @@
    }
    @Override
    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto) {
    public SSRCInfo openRTPServer(MediaServer mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto) {
        return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, port, onlyAuto, null, 0);
    }
    @Override
    public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) {
    public void closeRTPServer(MediaServer mediaServerItem, String streamId) {
        if (mediaServerItem == null) {
            return;
        }
@@ -153,7 +154,7 @@
    }
    @Override
    public void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
    public void closeRTPServer(MediaServer mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
        if (mediaServerItem == null) {
            callback.run(false);
            return;
@@ -168,7 +169,7 @@
    @Override
    public void closeRTPServer(String mediaServerId, String streamId) {
        MediaServerItem mediaServerItem = this.getOne(mediaServerId);
        MediaServer mediaServerItem = this.getOne(mediaServerId);
        if (mediaServerItem == null) {
            return;
        }
@@ -184,7 +185,7 @@
    }
    @Override
    public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) {
    public Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) {
        if (mediaServerItem == null) {
            return false;
        }
@@ -198,7 +199,7 @@
    @Override
    public void releaseSsrc(String mediaServerItemId, String ssrc) {
        MediaServerItem mediaServerItem = getOne(mediaServerItemId);
        MediaServer mediaServerItem = getOne(mediaServerItemId);
        if (mediaServerItem == null || ssrc == null) {
            return;
        }
@@ -209,21 +210,21 @@
     * 媒体服务节点 重启后重置他的推流信息, TODO 给正在使用的设备发送停止命令
     */
    @Override
    public void clearRTPServer(MediaServerItem mediaServerItem) {
    public void clearRTPServer(MediaServer mediaServerItem) {
        ssrcFactory.reset(mediaServerItem.getId());
    }
    @Override
    public void update(MediaServerItem mediaSerItem) {
    public void update(MediaServer mediaSerItem) {
        mediaServerMapper.update(mediaSerItem);
        MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
        MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
        MediaServer mediaServerInRedis = getOne(mediaSerItem.getId());
        MediaServer mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
        if (mediaServerItemInDataBase == null) {
            return;
        }
        mediaServerItemInDataBase.setStatus(mediaSerItem.isStatus());
        if (mediaServerItemInRedis == null || !ssrcFactory.hasMediaServerSSRC(mediaServerItemInDataBase.getId())) {
        if (mediaServerInRedis == null || !ssrcFactory.hasMediaServerSSRC(mediaServerItemInDataBase.getId())) {
            ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null);
        }
        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId();
@@ -240,13 +241,13 @@
    @Override
    public List<MediaServerItem> getAllOnlineList() {
        List<MediaServerItem> result = new ArrayList<>();
    public List<MediaServer> getAllOnlineList() {
        List<MediaServer> result = new ArrayList<>();
        List<Object> mediaServerKeys = RedisUtil.scan(redisTemplate, String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX+ userSetting.getServerId() + "_" ));
        String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
        for (Object mediaServerKey : mediaServerKeys) {
            String key = (String) mediaServerKey;
            MediaServerItem mediaServerItem = JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class);
            MediaServer mediaServerItem = JsonUtil.redisJsonToObject(redisTemplate, key, MediaServer.class);
            if (Objects.isNull(mediaServerItem)) {
                continue;
            }
@@ -269,13 +270,13 @@
    }
    @Override
    public List<MediaServerItem> getAll() {
        List<MediaServerItem> mediaServerList = mediaServerMapper.queryAll();
    public List<MediaServer> getAll() {
        List<MediaServer> mediaServerList = mediaServerMapper.queryAll();
        if (mediaServerList.isEmpty()) {
            return new ArrayList<>();
        }
        for (MediaServerItem mediaServerItem : mediaServerList) {
            MediaServerItem mediaServerItemInRedis = getOne(mediaServerItem.getId());
        for (MediaServer mediaServerItem : mediaServerList) {
            MediaServer mediaServerItemInRedis = getOne(mediaServerItem.getId());
            if (mediaServerItemInRedis != null) {
                mediaServerItem.setStatus(mediaServerItemInRedis.isStatus());
            }
@@ -285,21 +286,21 @@
    @Override
    public List<MediaServerItem> getAllFromDatabase() {
    public List<MediaServer> getAllFromDatabase() {
        return mediaServerMapper.queryAll();
    }
    @Override
    public List<MediaServerItem> getAllOnline() {
    public List<MediaServer> getAllOnline() {
        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
        Set<Object> mediaServerIdSet = redisTemplate.opsForZSet().reverseRange(key, 0, -1);
        List<MediaServerItem> result = new ArrayList<>();
        List<MediaServer> result = new ArrayList<>();
        if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) {
            for (Object mediaServerId : mediaServerIdSet) {
                String mediaServerIdStr = (String) mediaServerId;
                String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerIdStr;
                result.add((MediaServerItem) redisTemplate.opsForValue().get(serverKey));
                result.add((MediaServer) redisTemplate.opsForValue().get(serverKey));
            }
        }
        Collections.reverse(result);
@@ -312,17 +313,17 @@
     * @return MediaServerItem
     */
    @Override
    public MediaServerItem getOne(String mediaServerId) {
    public MediaServer getOne(String mediaServerId) {
        if (mediaServerId == null) {
            return null;
        }
        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
        return JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class);
        return JsonUtil.redisJsonToObject(redisTemplate, key, MediaServer.class);
    }
    @Override
    public MediaServerItem getDefaultMediaServer() {
    public MediaServer getDefaultMediaServer() {
        return mediaServerMapper.queryDefault();
    }
@@ -333,7 +334,7 @@
    }
    @Override
    public void add(MediaServerItem mediaServerItem) {
    public void add(MediaServer mediaServerItem) {
        mediaServerItem.setCreateTime(DateUtil.getNow());
        mediaServerItem.setUpdateTime(DateUtil.getNow());
        if (mediaServerItem.getHookAliveInterval() == null || mediaServerItem.getHookAliveInterval() == 0F) {
@@ -364,7 +365,7 @@
    }
    @Override
    public void resetOnlineServerItem(MediaServerItem serverItem) {
    public void resetOnlineServerItem(MediaServer serverItem) {
        // 更新缓存
        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
        // 使用zset的分数作为当前并发量, 默认值设置为0
@@ -378,7 +379,7 @@
        }
    }
    private int getMediaList(MediaServerItem serverItem) {
    private int getMediaList(MediaServer serverItem) {
        return 0;
    }
@@ -405,7 +406,7 @@
     * @return MediaServerItem
     */
    @Override
    public MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist) {
    public MediaServer getMediaServerForMinimumLoad(Boolean hasAssist) {
        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
        Long size = redisTemplate.opsForZSet().zCard(key);
        if (size  == null || size == 0) {
@@ -416,14 +417,14 @@
        // 获取分数最低的,及并发最低的
        Set<Object> objects = redisTemplate.opsForZSet().range(key, 0, -1);
        ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects);
        MediaServerItem mediaServerItem = null;
        MediaServer mediaServerItem = null;
        if (hasAssist == null) {
            String mediaServerId = (String)mediaServerObjectS.get(0);
            mediaServerItem = getOne(mediaServerId);
        }else if (hasAssist) {
            for (Object mediaServerObject : mediaServerObjectS) {
                String mediaServerId = (String)mediaServerObject;
                MediaServerItem serverItem = getOne(mediaServerId);
                MediaServer serverItem = getOne(mediaServerId);
                if (serverItem.getRecordAssistPort() > 0) {
                    mediaServerItem = serverItem;
                    break;
@@ -432,7 +433,7 @@
        }else if (!hasAssist) {
            for (Object mediaServerObject : mediaServerObjectS) {
                String mediaServerId = (String)mediaServerObject;
                MediaServerItem serverItem = getOne(mediaServerId);
                MediaServer serverItem = getOne(mediaServerId);
                if (serverItem.getRecordAssistPort() == 0) {
                    mediaServerItem = serverItem;
                    break;
@@ -444,7 +445,7 @@
    }
    @Override
    public MediaServerItem checkMediaServer(String ip, int port, String secret, String type) {
    public MediaServer checkMediaServer(String ip, int port, String secret, String type) {
        if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "此连接已存在");
        }
@@ -454,7 +455,7 @@
            logger.info("[closeRTPServer] 失败, mediaServerItem的类型: {},未找到对应的实现类", type);
            return null;
        }
        MediaServerItem mediaServerItem = mediaNodeServerService.checkMediaServer(ip, port, secret);
        MediaServer mediaServerItem = mediaNodeServerService.checkMediaServer(ip, port, secret);
        if (mediaServerItem != null) {
            if (mediaServerMapper.queryOne(mediaServerItem.getId()) != null) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "媒体服务ID [" + mediaServerItem.getId() + " ] 已存在,请修改媒体服务器配置");
@@ -495,20 +496,20 @@
    }
    @Override
    public MediaServerItem getOneFromDatabase(String mediaServerId) {
    public MediaServer getOneFromDatabase(String mediaServerId) {
        return mediaServerMapper.queryOne(mediaServerId);
    }
    @Override
    public void syncCatchFromDatabase() {
        List<MediaServerItem> allInCatch = getAllOnlineList();
        List<MediaServerItem> allInDatabase = mediaServerMapper.queryAll();
        Map<String, MediaServerItem> mediaServerItemMap = new HashMap<>();
        List<MediaServer> allInCatch = getAllOnlineList();
        List<MediaServer> allInDatabase = mediaServerMapper.queryAll();
        Map<String, MediaServer> mediaServerItemMap = new HashMap<>();
        for (MediaServerItem mediaServerItem : allInDatabase) {
        for (MediaServer mediaServerItem : allInDatabase) {
            mediaServerItemMap.put(mediaServerItem.getId(), mediaServerItem);
        }
        for (MediaServerItem mediaServerItem : allInCatch) {
        for (MediaServer mediaServerItem : allInCatch) {
            // 清除数据中不存在但redis缓存数据
            if (!mediaServerItemMap.containsKey(mediaServerItem.getId())) {
                delete(mediaServerItem.getId());
@@ -517,7 +518,7 @@
    }
    @Override
    public MediaServerLoad getLoad(MediaServerItem mediaServerItem) {
    public MediaServerLoad getLoad(MediaServer mediaServerItem) {
        MediaServerLoad result = new MediaServerLoad();
        result.setId(mediaServerItem.getId());
        result.setPush(redisCatchStorage.getPushStreamCount(mediaServerItem.getId()));
@@ -529,13 +530,13 @@
    }
    @Override
    public List<MediaServerItem> getAllWithAssistPort() {
    public List<MediaServer> getAllWithAssistPort() {
        return mediaServerMapper.queryAllWithAssistPort();
    }
    @Override
    public boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc) {
    public boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaInfo.getType());
        if (mediaNodeServerService == null) {
            logger.info("[stopSendRtp] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaInfo.getType());
@@ -545,7 +546,7 @@
    }
    @Override
    public boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) {
    public boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[stopSendRtp] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
@@ -555,7 +556,7 @@
    }
    @Override
    public List<StreamInfo> getMediaList(MediaServerItem mediaServerItem, String app, String stream, String callId) {
    public List<StreamInfo> getMediaList(MediaServer mediaServerItem, String app, String stream, String callId) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[getMediaList] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
@@ -563,4 +564,54 @@
        }
        return mediaNodeServerService.getMediaList(mediaServerItem, app, stream, callId);
    }
    @Override
    public Boolean connectRtpServer(MediaServer mediaServerItem, String address, int port, String stream) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[connectRtpServer] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
            return false;
        }
        return mediaNodeServerService.connectRtpServer(mediaServerItem, address, port, stream);
    }
    @Override
    public void getSnap(MediaServer mediaServerItem, String streamUrl, int timeoutSec, int expireSec, String path, String fileName) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[getSnap] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
            return;
        }
        mediaNodeServerService.getSnap(mediaServerItem, streamUrl, timeoutSec, expireSec, path, fileName);
    }
    @Override
    public MediaInfo getMediaInfo(MediaServer mediaServerItem, String app, String stream) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[getMediaInfo] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
            return null;
        }
        return mediaNodeServerService.getMediaInfo(mediaServerItem, app, stream);
    }
    @Override
    public Boolean pauseRtpCheck(MediaServer mediaServerItem, String streamKey) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[pauseRtpCheck] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
            return false;
        }
        return mediaNodeServerService.pauseRtpCheck(mediaServerItem, streamKey);
    }
    @Override
    public boolean resumeRtpCheck(MediaServer mediaServerItem, String streamKey) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[pauseRtpCheck] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
            return false;
        }
        return mediaNodeServerService.resumeRtpCheck(mediaServerItem, streamKey);
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
@@ -2,7 +2,7 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.utils.SSLSocketClientUtil;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
@@ -70,7 +70,7 @@
    }
    public JSONObject sendGet(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
    public JSONObject sendGet(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
        OkHttpClient client = getClient();
        if (mediaServerItem == null) {
@@ -155,7 +155,7 @@
        return responseJSON;
    }
    public JSONObject sendPost(MediaServerItem mediaServerItem, String url,
    public JSONObject sendPost(MediaServer mediaServerItem, String url,
                               JSONObject param, ZLMRESTfulUtils.RequestCallback callback,
                               Integer readTimeOut) {
        OkHttpClient client = getClient(readTimeOut);
@@ -244,12 +244,12 @@
        return responseJSON;
    }
    public JSONObject getInfo(MediaServerItem mediaServerItem, RequestCallback callback){
    public JSONObject getInfo(MediaServer mediaServerItem, RequestCallback callback){
        Map<String, Object> param = new HashMap<>();
        return sendGet(mediaServerItem, "api/record/info",param, callback);
    }
    public JSONObject addTask(MediaServerItem mediaServerItem, String app, String stream, String startTime,
    public JSONObject addTask(MediaServer mediaServerItem, String app, String stream, String startTime,
                              String endTime, String callId, List<String> filePathList, String remoteHost) {
        JSONObject videoTaskInfoJSON = new JSONObject();
@@ -266,7 +266,7 @@
        return sendPost(mediaServerItem, urlStr, videoTaskInfoJSON, null, 30);
    }
    public JSONObject queryTaskList(MediaServerItem mediaServerItem, String app, String stream, String callId,
    public JSONObject queryTaskList(MediaServer mediaServerItem, String app, String stream, String callId,
                                    String taskId, Boolean isEnd, String scheme) {
        Map<String, Object> param = new HashMap<>();
        if (!ObjectUtils.isEmpty(app)) {
src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java
@@ -3,7 +3,7 @@
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
@@ -30,7 +30,7 @@
    private final String KEY = "VM_MEDIA_SEND_RTP_PORT_";
    public synchronized int getNextPort(MediaServerItem mediaServer) {
    public synchronized int getNextPort(MediaServer mediaServer) {
        if (mediaServer == null) {
            logger.warn("[发送端口管理] 参数错误,mediaServer为NULL");
            return -1;
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -18,7 +18,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.media.zlm.dto.hook.*;
@@ -34,7 +34,6 @@
import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo;
import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -153,7 +152,7 @@
        });
        try {
            HookZlmServerKeepaliveEvent event = new HookZlmServerKeepaliveEvent(this);
            MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
            MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
            if (mediaServerItem != null) {
                event.setMediaServerItem(mediaServerItem);
                applicationEventPublisher.publishEvent(event);
@@ -179,7 +178,7 @@
            JSONObject json = (JSONObject) JSON.toJSON(param);
            ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json);
            if (subscribe != null) {
                MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
                MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
                if (mediaInfo != null) {
                    subscribe.response(mediaInfo, param);
                }
@@ -209,7 +208,7 @@
        // TODO 加快处理速度
        String mediaServerId = json.getString("mediaServerId");
        MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
        MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
        if (mediaInfo == null) {
            return new HookResultForOnPublish(200, "success");
        }
@@ -360,7 +359,7 @@
        JSONObject json = (JSONObject) JSON.toJSON(param);
        taskExecutor.execute(() -> {
            ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json);
            MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId());
            MediaServer mediaInfo = mediaServerService.getOne(param.getMediaServerId());
            if (mediaInfo == null) {
                logger.info("[ZLM HOOK] 流变化未找到ZLM, {}", param.getMediaServerId());
                return;
@@ -472,7 +471,7 @@
                                callId = streamAuthorityInfo.getCallId();
                            }
                            StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo,
                                    param.getApp(), param.getStream(), Track.getInstance(param), callId);
                                    param.getApp(), param.getStream(), MediaInfo.getInstance(param), callId);
                            param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
                            redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param);
                            if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
@@ -680,7 +679,7 @@
        DeferredResult<HookResult> defaultResult = new DeferredResult<>();
        MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId());
        MediaServer mediaInfo = mediaServerService.getOne(param.getMediaServerId());
        if (!userSetting.isAutoApplyPlay() || mediaInfo == null) {
            defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg()));
            return defaultResult;
@@ -811,7 +810,7 @@
        });
        try {
            HookZlmServerStartEvent event = new HookZlmServerStartEvent(this);
            MediaServerItem mediaServerItem = mediaServerService.getOne(zlmServerConfig.getMediaServerId());
            MediaServer mediaServerItem = mediaServerService.getOne(zlmServerConfig.getMediaServerId());
            if (mediaServerItem != null) {
                event.setMediaServerItem(mediaServerItem);
                applicationEventPublisher.publishEvent(event);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
@@ -88,7 +88,7 @@
    }
    public void sendStreamEvent(String app, String stream, String mediaServerId) {
        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
        // 查看推流状态
        Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream);
        if (streamReady != null && streamReady) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java
@@ -6,11 +6,10 @@
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.service.IMediaNodeServerService;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig;
import com.genersoft.iot.vmp.service.impl.DeviceServiceImpl;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,32 +38,32 @@
    private String sipIp;
    @Override
    public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
    public int createRTPServer(MediaServer mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
        return zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrc, port, onlyAuto, reUsePort, tcpMode);
    }
    @Override
    public void closeRtpServer(MediaServerItem mediaServerItem, String streamId) {
    public void closeRtpServer(MediaServer mediaServerItem, String streamId) {
        zlmresTfulUtils.closeStreams(mediaServerItem, "rtp", streamId);
    }
    @Override
    public void closeRtpServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
    public void closeRtpServer(MediaServer mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
        zlmServerFactory.closeRtpServer(mediaServerItem, streamId, callback);
    }
    @Override
    public void closeStreams(MediaServerItem mediaServerItem, String app, String stream) {
    public void closeStreams(MediaServer mediaServerItem, String app, String stream) {
        zlmresTfulUtils.closeStreams(mediaServerItem, app, stream);
    }
    @Override
    public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) {
    public Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) {
        return zlmServerFactory.updateRtpServerSSRC(mediaServerItem, streamId, ssrc);
    }
    @Override
    public boolean checkNodeId(MediaServerItem mediaServerItem) {
    public boolean checkNodeId(MediaServer mediaServerItem) {
        if (mediaServerItem == null) {
            return false;
        }
@@ -84,13 +83,13 @@
    }
    @Override
    public void online(MediaServerItem mediaServerItem) {
    public void online(MediaServer mediaServerItem) {
    }
    @Override
    public MediaServerItem checkMediaServer(String ip, int port, String secret) {
        MediaServerItem mediaServerItem = new MediaServerItem();
    public MediaServer checkMediaServer(String ip, int port, String secret) {
        MediaServer mediaServerItem = new MediaServer();
        mediaServerItem.setIp(ip);
        mediaServerItem.setHttpPort(port);
        mediaServerItem.setSecret(secret);
@@ -121,7 +120,7 @@
    }
    @Override
    public boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc) {
    public boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) {
        Map<String, Object> param = new HashMap<>();
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
@@ -135,7 +134,7 @@
    }
    @Override
    public boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) {
    public boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName) {
        logger.info("[zlm-deleteRecordDirectory] 删除磁盘文件, server: {} {}:{}->{}/{}", mediaServerItem.getId(), app, stream, date, fileName);
        JSONObject jsonObject = zlmresTfulUtils.deleteRecordDirectory(mediaServerItem, app,
                stream, date, fileName);
@@ -148,7 +147,7 @@
    }
    @Override
    public List<StreamInfo> getMediaList(MediaServerItem mediaServerItem, String app, String stream, String callId) {
    public List<StreamInfo> getMediaList(MediaServer mediaServerItem, String app, String stream, String callId) {
        List<StreamInfo> streamInfoList = new ArrayList<>();
        JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServerItem, app, stream);
        if (mediaList != null) {
@@ -158,8 +157,8 @@
                    return null;
                }
                JSONObject mediaJSON = data.getJSONObject(0);
                Track track = Track.getInstance(mediaJSON);
                StreamInfo streamInfo = getStreamInfoByAppAndStream(mediaServerItem, app, stream, track, callId, true);
                MediaInfo mediaInfo = MediaInfo.getInstance(mediaJSON);
                StreamInfo streamInfo = getStreamInfoByAppAndStream(mediaServerItem, app, stream, mediaInfo, callId, true);
                if (streamInfo != null) {
                    streamInfoList.add(streamInfo);
                }
@@ -168,23 +167,56 @@
        return streamInfoList;
    }
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String callId, boolean isPlay) {
    public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String callId, boolean isPlay) {
        StreamInfo streamInfoResult = new StreamInfo();
        streamInfoResult.setStream(stream);
        streamInfoResult.setApp(app);
        String addr = mediaInfo.getStreamIp();
        String addr = mediaServerItem.getStreamIp();
        streamInfoResult.setIp(addr);
        streamInfoResult.setMediaServerId(mediaInfo.getId());
        streamInfoResult.setMediaServerId(mediaServerItem.getId());
        String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId;
        streamInfoResult.setRtmp(addr, mediaInfo.getRtmpPort(),mediaInfo.getRtmpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtsp(addr, mediaInfo.getRtspPort(),mediaInfo.getRtspSSLPort(), app,  stream, callIdParam);
        streamInfoResult.setFlv(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setFmp4(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setHls(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setTs(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtc(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam, isPlay);
        streamInfoResult.setRtmp(addr, mediaServerItem.getRtmpPort(),mediaServerItem.getRtmpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtsp(addr, mediaServerItem.getRtspPort(),mediaServerItem.getRtspSSLPort(), app,  stream, callIdParam);
        streamInfoResult.setFlv(addr, mediaServerItem.getHttpPort(),mediaServerItem.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setFmp4(addr, mediaServerItem.getHttpPort(),mediaServerItem.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setHls(addr, mediaServerItem.getHttpPort(),mediaServerItem.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setTs(addr, mediaServerItem.getHttpPort(),mediaServerItem.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtc(addr, mediaServerItem.getHttpPort(),mediaServerItem.getHttpSSlPort(), app,  stream, callIdParam, isPlay);
        streamInfoResult.setTrack(track);
        streamInfoResult.setMediaInfo(mediaInfo);
        return streamInfoResult;
    }
    @Override
    public Boolean connectRtpServer(MediaServer mediaServerItem, String address, int port, String stream) {
        JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, address, port, stream);
        logger.info("[TCP主动连接对方] 结果: {}", jsonObject);
        return jsonObject.getInteger("code") == 0;
    }
    @Override
    public void getSnap(MediaServer mediaServerItem, String streamUrl, int timeoutSec, int expireSec, String path, String fileName) {
        zlmresTfulUtils.getSnap(mediaServerItem, streamUrl, timeoutSec, expireSec, path, fileName);
    }
    @Override
    public MediaInfo getMediaInfo(MediaServer mediaServerItem, String app, String stream) {
        JSONObject jsonObject = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", stream);
        if (jsonObject.getInteger("code") != 0) {
            return null;
        }
        return MediaInfo.getInstance(jsonObject);
    }
    @Override
    public Boolean pauseRtpCheck(MediaServer mediaServerItem, String streamKey) {
        JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamKey);
        return jsonObject.getInteger("code") == 0;
    }
    @Override
    public Boolean resumeRtpCheck(MediaServer mediaServerItem, String streamKey) {
        JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamKey);
        return jsonObject.getInteger("code") == 0;
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaServerStatusManger.java
@@ -8,7 +8,7 @@
import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent;
import com.genersoft.iot.vmp.media.event.MediaServerDeleteEvent;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig;
import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerKeepaliveEvent;
import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerStartEvent;
@@ -36,8 +36,8 @@
    private final static Logger logger = LoggerFactory.getLogger(ZLMMediaServerStatusManger.class);
    private final Map<Object, MediaServerItem> offlineZlmPrimaryMap = new ConcurrentHashMap<>();
    private final Map<Object, MediaServerItem> offlineZlmsecondaryMap = new ConcurrentHashMap<>();
    private final Map<Object, MediaServer> offlineZlmPrimaryMap = new ConcurrentHashMap<>();
    private final Map<Object, MediaServer> offlineZlmsecondaryMap = new ConcurrentHashMap<>();
    private final Map<Object, Long> offlineZlmTimeMap = new ConcurrentHashMap<>();
    @Autowired
@@ -67,7 +67,7 @@
                || event.getMediaServerItemList().isEmpty()) {
            return;
        }
        for (MediaServerItem mediaServerItem : event.getMediaServerItemList()) {
        for (MediaServer mediaServerItem : event.getMediaServerItemList()) {
            if (!type.equals(mediaServerItem.getType())) {
                continue;
            }
@@ -85,7 +85,7 @@
                || event.getMediaServerItem().isStatus()) {
            return;
        }
        MediaServerItem serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
        MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
        if (serverItem == null) {
            return;
        }
@@ -99,7 +99,7 @@
        if (event.getMediaServerItem() == null) {
            return;
        }
        MediaServerItem serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
        MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
        if (serverItem == null) {
            return;
        }
@@ -126,7 +126,7 @@
            return;
        }
        if (!offlineZlmPrimaryMap.isEmpty()) {
            for (MediaServerItem mediaServerItem : offlineZlmPrimaryMap.values()) {
            for (MediaServer mediaServerItem : offlineZlmPrimaryMap.values()) {
                if (offlineZlmTimeMap.get(mediaServerItem.getId()) <  System.currentTimeMillis() - 30*60*1000) {
                    offlineZlmsecondaryMap.put(mediaServerItem.getId(), mediaServerItem);
                    offlineZlmPrimaryMap.remove(mediaServerItem.getId());
@@ -150,7 +150,7 @@
            }
        }
        if (!offlineZlmsecondaryMap.isEmpty()) {
            for (MediaServerItem mediaServerItem : offlineZlmsecondaryMap.values()) {
            for (MediaServer mediaServerItem : offlineZlmsecondaryMap.values()) {
                if (offlineZlmTimeMap.get(mediaServerItem.getId()) <  System.currentTimeMillis() - 30*60*1000) {
                    continue;
                }
@@ -175,7 +175,7 @@
        }
    }
    private void online(MediaServerItem mediaServerItem, ZLMServerConfig config) {
    private void online(MediaServer mediaServerItem, ZLMServerConfig config) {
        offlineZlmPrimaryMap.remove(mediaServerItem.getId());
        offlineZlmsecondaryMap.remove(mediaServerItem.getId());
        offlineZlmTimeMap.remove(mediaServerItem.getId());
@@ -209,7 +209,7 @@
            mediaServerService.update(mediaServerItem);
        }, (int)(mediaServerItem.getHookAliveInterval() * 2 * 1000));
    }
    private void initPort(MediaServerItem mediaServerItem, ZLMServerConfig zlmServerConfig) {
    private void initPort(MediaServer mediaServerItem, ZLMServerConfig zlmServerConfig) {
        if (mediaServerItem.getHttpSSlPort() == 0) {
            mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
        }
@@ -231,7 +231,7 @@
        mediaServerItem.setHookAliveInterval(10F);
    }
    public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) {
    public void setZLMConfig(MediaServer mediaServerItem, boolean restart) {
        logger.info("[媒体服务节点] 正在设置 :{} -> {}:{}",
                mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
        String protocol = sslEnabled ? "https" : "http";
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -2,7 +2,7 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import org.jetbrains.annotations.NotNull;
@@ -60,12 +60,12 @@
    }
    public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
    public JSONObject sendPost(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
        return sendPost(mediaServerItem, api, param, callback, null);
    }
    public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback, Integer readTimeOut) {
    public JSONObject sendPost(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback, Integer readTimeOut) {
        OkHttpClient client = getClient(readTimeOut);
        if (mediaServerItem == null) {
@@ -164,7 +164,7 @@
        return responseJSON;
    }
    public void sendGetForImg(MediaServerItem mediaServerItem, String api, Map<String, Object> params, String targetPath, String fileName) {
    public void sendGetForImg(MediaServer mediaServerItem, String api, Map<String, Object> params, String targetPath, String fileName) {
        String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
        HttpUrl parseUrl = HttpUrl.parse(url);
        if (parseUrl == null) {
@@ -216,7 +216,7 @@
        }
    }
    public JSONObject isMediaOnline(MediaServerItem mediaServerItem, String app, String stream, String schema){
    public JSONObject isMediaOnline(MediaServer mediaServerItem, String app, String stream, String schema){
        Map<String, Object> param = new HashMap<>();
        if (app != null) {
            param.put("app",app);
@@ -231,7 +231,7 @@
        return sendPost(mediaServerItem, "isMediaOnline", param, null);
    }
    public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream, String schema, RequestCallback callback){
    public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream, String schema, RequestCallback callback){
        Map<String, Object> param = new HashMap<>();
        if (app != null) {
            param.put("app",app);
@@ -246,15 +246,15 @@
        return sendPost(mediaServerItem, "getMediaList",param, callback);
    }
    public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream){
    public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream){
        return getMediaList(mediaServerItem, app, stream,null,  null);
    }
    public JSONObject getMediaList(MediaServerItem mediaServerItem, RequestCallback callback){
    public JSONObject getMediaList(MediaServer mediaServerItem, RequestCallback callback){
        return sendPost(mediaServerItem, "getMediaList",null, callback);
    }
    public JSONObject getMediaInfo(MediaServerItem mediaServerItem, String app, String schema, String stream){
    public JSONObject getMediaInfo(MediaServer mediaServerItem, String app, String schema, String stream){
        Map<String, Object> param = new HashMap<>();
        param.put("app",app);
        param.put("schema",schema);
@@ -263,13 +263,13 @@
        return sendPost(mediaServerItem, "getMediaInfo",param, null);
    }
    public JSONObject getRtpInfo(MediaServerItem mediaServerItem, String stream_id){
    public JSONObject getRtpInfo(MediaServer mediaServerItem, String stream_id){
        Map<String, Object> param = new HashMap<>();
        param.put("stream_id",stream_id);
        return sendPost(mediaServerItem, "getRtpInfo",param, null);
    }
    public JSONObject addFFmpegSource(MediaServerItem mediaServerItem, String src_url, String dst_url, String timeout_ms,
    public JSONObject addFFmpegSource(MediaServer mediaServerItem, String src_url, String dst_url, String timeout_ms,
                                      boolean enable_audio, boolean enable_mp4, String ffmpeg_cmd_key){
        logger.info(src_url);
        logger.info(dst_url);
@@ -282,63 +282,63 @@
        return sendPost(mediaServerItem, "addFFmpegSource",param, null);
    }
    public JSONObject delFFmpegSource(MediaServerItem mediaServerItem, String key){
    public JSONObject delFFmpegSource(MediaServer mediaServerItem, String key){
        Map<String, Object> param = new HashMap<>();
        param.put("key", key);
        return sendPost(mediaServerItem, "delFFmpegSource",param, null);
    }
    public JSONObject delStreamProxy(MediaServerItem mediaServerItem, String key){
    public JSONObject delStreamProxy(MediaServer mediaServerItem, String key){
        Map<String, Object> param = new HashMap<>();
        param.put("key", key);
        return sendPost(mediaServerItem, "delStreamProxy",param, null);
    }
    public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){
    public JSONObject getMediaServerConfig(MediaServer mediaServerItem){
        return sendPost(mediaServerItem, "getServerConfig",null, null);
    }
    public JSONObject setServerConfig(MediaServerItem mediaServerItem, Map<String, Object> param){
    public JSONObject setServerConfig(MediaServer mediaServerItem, Map<String, Object> param){
        return sendPost(mediaServerItem,"setServerConfig",param, null);
    }
    public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){
    public JSONObject openRtpServer(MediaServer mediaServerItem, Map<String, Object> param){
        return sendPost(mediaServerItem, "openRtpServer",param, null);
    }
    public JSONObject closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param) {
    public JSONObject closeRtpServer(MediaServer mediaServerItem, Map<String, Object> param) {
        return sendPost(mediaServerItem, "closeRtpServer",param, null);
    }
    public void closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param, RequestCallback callback) {
    public void closeRtpServer(MediaServer mediaServerItem, Map<String, Object> param, RequestCallback callback) {
        sendPost(mediaServerItem, "closeRtpServer",param, callback);
    }
    public JSONObject listRtpServer(MediaServerItem mediaServerItem) {
    public JSONObject listRtpServer(MediaServer mediaServerItem) {
        return sendPost(mediaServerItem, "listRtpServer",null, null);
    }
    public JSONObject startSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
    public JSONObject startSendRtp(MediaServer mediaServerItem, Map<String, Object> param) {
        return sendPost(mediaServerItem, "startSendRtp",param, null);
    }
    public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object> param) {
    public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object> param) {
        return sendPost(mediaServerItem, "startSendRtpPassive",param, null);
    }
    public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object> param, RequestCallback callback) {
    public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object> param, RequestCallback callback) {
        return sendPost(mediaServerItem, "startSendRtpPassive",param, callback);
    }
    public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
    public JSONObject stopSendRtp(MediaServer mediaServerItem, Map<String, Object> param) {
        return sendPost(mediaServerItem, "stopSendRtp",param, null);
    }
    public JSONObject restartServer(MediaServerItem mediaServerItem) {
    public JSONObject restartServer(MediaServer mediaServerItem) {
        return sendPost(mediaServerItem, "restartServer",null, null);
    }
    public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) {
    public JSONObject addStreamProxy(MediaServer mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) {
        Map<String, Object> param = new HashMap<>();
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
@@ -350,7 +350,7 @@
        return sendPost(mediaServerItem, "addStreamProxy",param, null, 20);
    }
    public JSONObject closeStreams(MediaServerItem mediaServerItem, String app, String stream) {
    public JSONObject closeStreams(MediaServer mediaServerItem, String app, String stream) {
        Map<String, Object> param = new HashMap<>();
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
@@ -359,17 +359,17 @@
        return sendPost(mediaServerItem, "close_streams",param, null);
    }
    public JSONObject getAllSession(MediaServerItem mediaServerItem) {
    public JSONObject getAllSession(MediaServer mediaServerItem) {
        return sendPost(mediaServerItem, "getAllSession",null, null);
    }
    public void kickSessions(MediaServerItem mediaServerItem, String localPortSStr) {
    public void kickSessions(MediaServer mediaServerItem, String localPortSStr) {
        Map<String, Object> param = new HashMap<>();
        param.put("local_port", localPortSStr);
        sendPost(mediaServerItem, "kick_sessions",param, null);
    }
    public void getSnap(MediaServerItem mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
    public void getSnap(MediaServer mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
        Map<String, Object> param = new HashMap<>(3);
        param.put("url", streamUrl);
        param.put("timeout_sec", timeout_sec);
@@ -377,19 +377,19 @@
        sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName);
    }
    public JSONObject pauseRtpCheck(MediaServerItem mediaServerItem, String streamId) {
    public JSONObject pauseRtpCheck(MediaServer mediaServerItem, String streamId) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("stream_id", streamId);
        return sendPost(mediaServerItem, "pauseRtpCheck",param, null);
    }
    public JSONObject resumeRtpCheck(MediaServerItem mediaServerItem, String streamId) {
    public JSONObject resumeRtpCheck(MediaServer mediaServerItem, String streamId) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("stream_id", streamId);
        return sendPost(mediaServerItem, "resumeRtpCheck",param, null);
    }
    public JSONObject connectRtpServer(MediaServerItem mediaServerItem, String dst_url, int dst_port, String stream_id) {
    public JSONObject connectRtpServer(MediaServer mediaServerItem, String dst_url, int dst_port, String stream_id) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("dst_url", dst_url);
        param.put("dst_port", dst_port);
@@ -397,14 +397,14 @@
        return sendPost(mediaServerItem, "connectRtpServer",param, null);
    }
    public JSONObject updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) {
    public JSONObject updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("ssrc", ssrc);
        param.put("stream_id", streamId);
        return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null);
    }
    public JSONObject deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) {
    public JSONObject deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java
@@ -5,7 +5,7 @@
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -42,7 +42,7 @@
     * @param tcpMode 0/null udp 模式,1 tcp 被动模式, 2 tcp 主动模式。
     * @return
     */
    public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
    public int createRTPServer(MediaServer mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
        int result = -1;
        // 查询此rtp server 是否已经存在
        JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
@@ -108,7 +108,7 @@
        return result;
    }
    public boolean closeRtpServer(MediaServerItem serverItem, String streamId) {
    public boolean closeRtpServer(MediaServer serverItem, String streamId) {
        boolean result = false;
        if (serverItem !=null){
            Map<String, Object> param = new HashMap<>();
@@ -129,7 +129,7 @@
        return result;
    }
    public void closeRtpServer(MediaServerItem serverItem, String streamId, CommonCallback<Boolean> callback) {
    public void closeRtpServer(MediaServer serverItem, String streamId, CommonCallback<Boolean> callback) {
        if (serverItem == null) {
            callback.run(false);
            return;
@@ -165,7 +165,7 @@
     * @param tcp 是否为tcp
     * @return SendRtpItem
     */
    public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId,
    public SendRtpItem createSendRtpItem(MediaServer serverItem, String ip, int port, String ssrc, String platformId,
                                         String deviceId, String channelId, boolean tcp, boolean rtcp){
        int localPort = sendRtpPortManager.getNextPort(serverItem);
@@ -198,7 +198,7 @@
     * @param tcp 是否为tcp
     * @return SendRtpItem
     */
    public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId,
    public SendRtpItem createSendRtpItem(MediaServer serverItem, String ip, int port, String ssrc, String platformId,
                                         String app, String stream, String channelId, boolean tcp, boolean rtcp){
        int localPort = sendRtpPortManager.getNextPort(serverItem);
@@ -224,25 +224,25 @@
    /**
     * 调用zlm RESTFUL API —— startSendRtp
     */
    public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
    public JSONObject startSendRtpStream(MediaServer mediaServerItem, Map<String, Object>param) {
        return zlmresTfulUtils.startSendRtp(mediaServerItem, param);
    }
    /**
     * 调用zlm RESTFUL API —— startSendRtpPassive
     */
    public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param) {
    public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object>param) {
        return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param);
    }
    public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param, ZLMRESTfulUtils.RequestCallback callback) {
    public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object>param, ZLMRESTfulUtils.RequestCallback callback) {
        return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param, callback);
    }
    /**
     * 查询待转推的流是否就绪
     */
    public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) {
    public Boolean isRtpReady(MediaServer mediaServerItem, String streamId) {
        JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtsp", streamId);
        if (mediaInfo.getInteger("code") == -2) {
            return null;
@@ -253,7 +253,7 @@
    /**
     * 查询待转推的流是否就绪
     */
    public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) {
    public Boolean isStreamReady(MediaServer mediaServerItem, String app, String streamId) {
        JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId);
        if (mediaInfo == null || (mediaInfo.getInteger("code") == -2)) {
            return null;
@@ -268,7 +268,7 @@
     * @param streamId
     * @return
     */
    public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) {
    public int totalReaderCount(MediaServer mediaServerItem, String app, String streamId) {
        JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId);
        if (mediaInfo == null) {
            return 0;
@@ -288,7 +288,7 @@
    /**
     * 调用zlm RESTful API —— stopSendRtp
     */
    public Boolean stopSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
    public Boolean stopSendRtpStream(MediaServer mediaServerItem, Map<String, Object>param) {
        if (mediaServerItem == null) {
            logger.error("[停止RTP推流] 失败: 媒体节点为NULL");
            return false;
@@ -306,7 +306,7 @@
        return result;
    }
    public JSONObject startSendRtp(MediaServerItem mediaInfo, SendRtpItem sendRtpItem) {
    public JSONObject startSendRtp(MediaServer mediaInfo, SendRtpItem sendRtpItem) {
        String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
        logger.info("rtp/{}开始推流, 目标={}:{},SSRC={}", sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
        Map<String, Object> param = new HashMap<>(12);
@@ -351,7 +351,7 @@
        return startSendRtpStreamResult;
    }
    public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) {
    public Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) {
        boolean result = false;
        JSONObject jsonObject = zlmresTfulUtils.updateRtpServerSSRC(mediaServerItem, streamId, ssrc);
        if (jsonObject == null) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java
@@ -3,7 +3,7 @@
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.HookType;
import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,7 +27,7 @@
    @FunctionalInterface
    public interface Event{
        void response(MediaServerItem mediaServerItem, HookParam hookParam);
        void response(MediaServer mediaServerItem, HookParam hookParam);
    }
    private Map<HookType, Map<IHookSubscribe, ZlmHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServer.java
File was renamed from src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
@@ -5,7 +5,7 @@
import org.springframework.util.ObjectUtils;
@Schema(description = "流媒体服务信息")
public class MediaServerItem{
public class MediaServer {
    @Schema(description = "ID")
    private String id;
@@ -87,10 +87,10 @@
    @Schema(description = "类型: zlm/abl")
    private String type;
    public MediaServerItem() {
    public MediaServer() {
    }
    public MediaServerItem(ZLMServerConfig zlmServerConfig, String sipIp) {
    public MediaServer(ZLMServerConfig zlmServerConfig, String sipIp) {
        id = zlmServerConfig.getGeneralMediaServerId();
        ip = zlmServerConfig.getIp();
        hookIp = ObjectUtils.isEmpty(zlmServerConfig.getHookIp())? sipIp: zlmServerConfig.getHookIp();
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java
@@ -36,7 +36,7 @@
    public MediaServerItemLite(MediaServerItem mediaServerItem) {
    public MediaServerItemLite(MediaServer mediaServerItem) {
        this.id = mediaServerItem.getId();
        this.ip = mediaServerItem.getIp();
        this.hookIp = mediaServerItem.getHookIp();
src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerKeepaliveEvent.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.media.zlm.event;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import org.springframework.context.ApplicationEvent;
/**
@@ -12,13 +12,13 @@
        super(source);
    }
    private MediaServerItem mediaServerItem;
    private MediaServer mediaServerItem;
    public MediaServerItem getMediaServerItem() {
    public MediaServer getMediaServerItem() {
        return mediaServerItem;
    }
    public void setMediaServerItem(MediaServerItem mediaServerItem) {
    public void setMediaServerItem(MediaServer mediaServerItem) {
        this.mediaServerItem = mediaServerItem;
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerStartEvent.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.media.zlm.event;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import org.springframework.context.ApplicationEvent;
/**
@@ -12,13 +12,13 @@
        super(source);
    }
    private MediaServerItem mediaServerItem;
    private MediaServer mediaServerItem;
    public MediaServerItem getMediaServerItem() {
    public MediaServer getMediaServerItem() {
        return mediaServerItem;
    }
    public void setMediaServerItem(MediaServerItem mediaServerItem) {
    public void setMediaServerItem(MediaServer mediaServerItem) {
        this.mediaServerItem = mediaServerItem;
    }
}
src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java
@@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.service;
import com.alibaba.fastjson2.JSONArray;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
@@ -18,7 +18,7 @@
    /**
     * 分页回去云端录像列表
     */
    PageInfo<CloudRecordItem> getList(int page, int count, String query,  String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems);
    PageInfo<CloudRecordItem> getList(int page, int count, String query,  String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems);
    /**
     * 根据hook消息增加一条记录
@@ -28,12 +28,12 @@
    /**
     * 获取所有的日期
     */
    List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems);
    List<String> getDateList(String app, String stream, int year, int month, List<MediaServer> mediaServerItems);
    /**
     * 添加合并任务
     */
    String addTask(String app, String stream, MediaServerItem mediaServerItem, String startTime,
    String addTask(String app, String stream, MediaServer mediaServerItem, String startTime,
                   String endTime, String callId, String remoteHost, boolean filterMediaServer);
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
@@ -1,9 +1,8 @@
package com.genersoft.iot.vmp.service;
import com.alibaba.fastjson2.JSONArray;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
/**
 * 媒体信息业务
@@ -33,7 +32,7 @@
     * @param stream
     * @return
     */
    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Track track, String callId);
    StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String callId);
    /**
     * 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
@@ -41,5 +40,5 @@
     * @param stream
     * @return
     */
    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String addr, String callId, boolean isPlay);
    StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay);
}
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
@@ -4,7 +4,7 @@
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback;
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
import com.github.pagehelper.PageInfo;
@@ -73,13 +73,13 @@
     * @param errorEvent 信令错误事件
     * @param timeoutCallback 超时事件
     */
    void broadcastInvite(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem,  ZlmHttpHookSubscribe.Event hookEvent,
    void broadcastInvite(ParentPlatform platform, String channelId, MediaServer mediaServerItem, ZlmHttpHookSubscribe.Event hookEvent,
                         SipSubscribe.Event errorEvent, InviteTimeOutCallback timeoutCallback) throws InvalidArgumentException, ParseException, SipException;
    /**
     * 语音喊话回复BYE
     */
    void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream,boolean sendBye, MediaServerItem mediaServerItem);
    void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream,boolean sendBye, MediaServer mediaServerItem);
    void addSimulatedSubscribeInfo(ParentPlatform parentPlatform);
}
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -7,7 +7,7 @@
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -26,20 +26,20 @@
 */
public interface IPlayService {
    void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId,
    void play(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId,
              ErrorCallback<Object> callback);
    SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback);
    SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback);
    StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId);
    StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, HookParam hookParam, String deviceId, String channelId);
    MediaServerItem getNewMediaServerItem(Device device);
    MediaServer getNewMediaServerItem(Device device);
    void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
    void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
    void playBack(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
    void zlmServerOffline(String mediaServerId);
    void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
    void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId,  String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
    void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
    StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
@@ -47,7 +47,7 @@
    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, String channelId, MediaServer mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException;
    boolean audioBroadcastInUse(Device device, String channelId);
@@ -62,7 +62,7 @@
    void startSendRtpStreamHand(SendRtpItem sendRtpItem, Object correlationInfo,
                                JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader);
    void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event);
    void talkCmd(Device device, String channelId, MediaServer mediaServerItem, String stream, AudioBroadcastEvent event);
    void stopTalk(Device device, String channelId, Boolean streamIsReady);
src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
@@ -3,7 +3,7 @@
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.GeneralCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import com.github.pagehelper.PageInfo;
@@ -75,7 +75,7 @@
     * 获取ffmpeg.cmd模板
     * @return
     */
    JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem);
    JSONObject getFFmpegCMDs(MediaServer mediaServerItem);
    /**
     * 根据app与stream获取streamProxy
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
@@ -2,7 +2,7 @@
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
@@ -16,7 +16,7 @@
 */
public interface IStreamPushService {
    List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem);
    List<StreamPushItem> handleJSON(String json, MediaServer mediaServerItem);
    /**
     * 将应用名和流ID加入国标关联
src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java
@@ -2,7 +2,7 @@
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import java.util.EventObject;
@@ -15,7 +15,7 @@
    private String msg;
    private T data;
    private MediaServerItem mediaServerItem;
    private MediaServer mediaServerItem;
    private JSONObject response;
    private SipSubscribe.EventResult<EventObject> event;
@@ -35,11 +35,11 @@
        this.data = data;
    }
    public MediaServerItem getMediaServerItem() {
    public MediaServer getMediaServerItem() {
        return mediaServerItem;
    }
    public void setMediaServerItem(MediaServerItem mediaServerItem) {
    public void setMediaServerItem(MediaServer mediaServerItem) {
        this.mediaServerItem = mediaServerItem;
    }
src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java
@@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.service.bean;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
/**
 * redis消息:下级回复推送信息
@@ -11,7 +11,7 @@
    private SendRtpItem sendRtpItem;
    private MediaServerItem mediaServerItem;
    private MediaServer mediaServerItem;
    public SendRtpItem getSendRtpItem() {
        return sendRtpItem;
@@ -21,11 +21,11 @@
        this.sendRtpItem = sendRtpItem;
    }
    public MediaServerItem getMediaServerItem() {
    public MediaServer getMediaServerItem() {
        return mediaServerItem;
    }
    public void setMediaServerItem(MediaServerItem mediaServerItem) {
    public void setMediaServerItem(MediaServer mediaServerItem) {
        this.mediaServerItem = mediaServerItem;
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java
@@ -6,7 +6,7 @@
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
import com.genersoft.iot.vmp.service.ICloudRecordService;
@@ -51,7 +51,7 @@
    private VideoStreamSessionManager streamSession;
    @Override
    public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems) {
    public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems) {
        // 开始时间和结束时间在数据库中都是以秒为单位的
        Long startTimeStamp = null;
        Long endTimeStamp = null;
@@ -76,7 +76,7 @@
    }
    @Override
    public List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems) {
    public List<String> getDateList(String app, String stream, int year, int month, List<MediaServer> mediaServerItems) {
        LocalDate startDate = LocalDate.of(year, month, 1);
        LocalDate endDate;
        if (month == 12) {
@@ -111,7 +111,7 @@
    }
    @Override
    public String addTask(String app, String stream, MediaServerItem mediaServerItem, String startTime, String endTime,
    public String addTask(String app, String stream, MediaServer mediaServerItem, String startTime, String endTime,
                          String callId, String remoteHost, boolean filterMediaServer) {
        // 参数校验
        assert app != null;
@@ -128,7 +128,7 @@
            endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
        }
        List<MediaServerItem> mediaServers = new ArrayList<>();
        List<MediaServer> mediaServers = new ArrayList<>();
        mediaServers.add(mediaServerItem);
        // 检索相关的录像文件
        List<String> filePathList = cloudRecordServiceMapper.queryRecordFilePathList(app, stream, startTimeStamp,
@@ -146,7 +146,7 @@
    @Override
    public JSONArray queryTask(String app, String stream, String callId, String taskId, String mediaServerId,
                               Boolean isEnd, String scheme) {
        MediaServerItem mediaServerItem = null;
        MediaServer mediaServerItem = null;
        if (mediaServerId == null) {
            mediaServerItem = mediaServerService.getDefaultMediaServer();
        }else {
@@ -183,10 +183,10 @@
        }
        List<MediaServerItem> mediaServerItems;
        List<MediaServer> mediaServerItems;
        if (!ObjectUtils.isEmpty(mediaServerId)) {
            mediaServerItems = new ArrayList<>();
            MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
            MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
            if (mediaServerItem == null) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
            }
@@ -229,7 +229,7 @@
            throw new ControllerException(ErrorCode.ERROR400.getCode(), "资源不存在");
        }
        String filePath = recordItem.getFilePath();
        MediaServerItem mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
        MediaServer mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
        return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -14,7 +14,7 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IInviteStreamService;
@@ -241,7 +241,7 @@
                SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null);
                if (sendRtpItem != null) {
                    redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null);
                    MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                    MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                    mediaServerService.stopSendRtp(mediaInfo, sendRtpItem.getApp(), sendRtpItem.getStream(), null);
                }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -2,10 +2,9 @@
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -27,13 +26,10 @@
    @Autowired
    private MediaConfig mediaConfig;
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
    @Override
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String callId) {
        return getStreamInfoByAppAndStream(mediaInfo, app, stream, track, null, callId, true);
    public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String callId) {
        return getStreamInfoByAppAndStream(mediaServerItem, app, stream, mediaInfo, null, callId, true);
    }
    @Override
@@ -42,7 +38,7 @@
        if (mediaServerId == null) {
            mediaServerId = mediaConfig.getId();
        }
        MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
        MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
        if (mediaInfo == null) {
            return null;
        }
@@ -67,26 +63,26 @@
    }
    @Override
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String addr, String callId, boolean isPlay) {
    public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServer, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay) {
        StreamInfo streamInfoResult = new StreamInfo();
        streamInfoResult.setStream(stream);
        streamInfoResult.setApp(app);
        if (addr == null) {
            addr = mediaInfo.getStreamIp();
            addr = mediaServer.getStreamIp();
        }
        streamInfoResult.setIp(addr);
        streamInfoResult.setMediaServerId(mediaInfo.getId());
        streamInfoResult.setMediaServerId(mediaServer.getId());
        String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId;
        streamInfoResult.setRtmp(addr, mediaInfo.getRtmpPort(),mediaInfo.getRtmpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtsp(addr, mediaInfo.getRtspPort(),mediaInfo.getRtspSSLPort(), app,  stream, callIdParam);
        streamInfoResult.setFlv(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setFmp4(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setHls(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setTs(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtc(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam, isPlay);
        streamInfoResult.setRtmp(addr, mediaServer.getRtmpPort(),mediaServer.getRtmpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtsp(addr, mediaServer.getRtspPort(),mediaServer.getRtspSSLPort(), app,  stream, callIdParam);
        streamInfoResult.setFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setFmp4(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setHls(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setTs(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtc(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app,  stream, callIdParam, isPlay);
        streamInfoResult.setTrack(track);
        streamInfoResult.setMediaInfo(mediaInfo);
        return streamInfoResult;
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
@@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.InviteSessionStatus;
import com.genersoft.iot.vmp.common.InviteSessionType;
@@ -13,11 +12,10 @@
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.service.IInviteStreamService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
@@ -96,15 +94,11 @@
    @Autowired
    private VideoStreamSessionManager streamSession;
    @Autowired
    private IPlayService playService;
    @Autowired
    private IInviteStreamService inviteStreamService;
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
    @Override
@@ -392,7 +386,7 @@
            for (SendRtpItem sendRtpItem : sendRtpItems) {
                ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
                redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), null, null);
                MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                Map<String, Object> param = new HashMap<>(3);
                param.put("vhost", "__defaultVhost__");
                param.put("app", sendRtpItem.getApp());
@@ -455,7 +449,7 @@
    }
    @Override
    public void broadcastInvite(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, ZlmHttpHookSubscribe.Event hookEvent,
    public void broadcastInvite(ParentPlatform platform, String channelId, MediaServer mediaServerItem, ZlmHttpHookSubscribe.Event hookEvent,
                                SipSubscribe.Event errorEvent, InviteTimeOutCallback timeoutCallback) throws InvalidArgumentException, ParseException, SipException {
        if (mediaServerItem == null) {
@@ -466,7 +460,7 @@
        if (inviteInfoForOld != null && inviteInfoForOld.getStreamInfo() != null) {
            // 如果zlm不存在这个流,则删除数据即可
            MediaServerItem mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfoForOld.getStreamInfo().getMediaServerId());
            MediaServer mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfoForOld.getStreamInfo().getMediaServerId());
            if (mediaServerItemForStreamInfo != null) {
                Boolean ready = zlmServerFactory.isStreamReady(mediaServerItemForStreamInfo, inviteInfoForOld.getStreamInfo().getApp(), inviteInfoForOld.getStreamInfo().getStream());
                if (!ready) {
@@ -596,7 +590,7 @@
        });
    }
    private void inviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, int tcpMode, boolean ssrcCheck, MediaServerItem mediaServerItem,
    private void inviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, int tcpMode, boolean ssrcCheck, MediaServer mediaServerItem,
                                 ParentPlatform platform, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback,
                                 InviteInfo inviteInfo, InviteSessionType inviteSessionType){
        inviteInfo.setStatus(InviteSessionStatus.ok);
@@ -701,7 +695,7 @@
    private void tcpActiveHandler(ParentPlatform platform, String channelId, String contentString,
                                  MediaServerItem mediaServerItem, int tcpMode, boolean ssrcCheck,
                                  MediaServer mediaServerItem, int tcpMode, boolean ssrcCheck,
                                  String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<Object> callback){
        if (tcpMode != 2) {
            return;
@@ -729,8 +723,8 @@
            }
            logger.info("[TCP主动连接对方] serverGbId: {}, channelId: {}, 连接对方的地址:{}:{}, SSRC: {}, SSRC校验:{}",
                    platform.getServerGBId(), channelId, sdp.getConnection().getAddress(), port, ssrcInfo.getSsrc(), ssrcCheck);
            JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream());
            logger.info("[TCP主动连接对方] 结果: {}", jsonObject);
            Boolean result = mediaServerService.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream());
            logger.info("[TCP主动连接对方] 结果: {}", result);
        } catch (SdpException e) {
            logger.error("[TCP主动连接对方] serverGbId: {}, channelId: {}, 解析200OK的SDP信息失败", platform.getServerGBId(), channelId, e);
            dynamicTask.stop(timeOutTaskKey);
@@ -749,7 +743,7 @@
    }
    @Override
    public void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream, boolean sendBye, MediaServerItem mediaServerItem) {
    public void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream, boolean sendBye, MediaServer mediaServerItem) {
        try {
            if (sendBye) {
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -1,11 +1,9 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.*;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.ServiceException;
@@ -18,16 +16,15 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRecordMp4;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
@@ -36,7 +33,6 @@
import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
import com.genersoft.iot.vmp.utils.CloudRecordUtils;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
@@ -47,9 +43,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
@@ -102,9 +95,6 @@
    private SendRtpPortManager sendRtpPortManager;
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
    @Autowired
    private IMediaService mediaService;
    @Autowired
@@ -120,37 +110,20 @@
    private IDeviceChannelService channelService;
    @Autowired
    private SipConfig sipConfig;
    @Autowired
    private DynamicTask dynamicTask;
    @Autowired
    private CloudRecordServiceMapper cloudRecordServiceMapper;
    @Autowired
    private ISIPCommanderForPlatform commanderForPlatform;
    @Qualifier("taskExecutor")
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private RedisGbPlayMsgListener redisGbPlayMsgListener;
    @Autowired
    private ZlmHttpHookSubscribe hookSubscribe;
    @Autowired
    private SSRCFactory ssrcFactory;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Override
    public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) {
    public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) {
        if (mediaServerItem == null) {
            logger.warn("[点播] 未找到可用的zlm deviceId: {},channelId:{}", deviceId, channelId);
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm");
@@ -185,7 +158,7 @@
                    return inviteInfo.getSsrcInfo();
                }
                String mediaServerId = streamInfo.getMediaServerId();
                MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
                MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
                Boolean ready = zlmServerFactory.isStreamReady(mediaInfo, "rtp", streamId);
                if (ready != null && ready) {
@@ -204,7 +177,7 @@
                }
            }
        }
        String streamId = String.format("%s_%s", device.getDeviceId(), channelId);;
        String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
        SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(),  false, 0, false, false, device.getStreamModeForParam());
        if (ssrcInfo == null) {
            callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
@@ -218,7 +191,7 @@
        return ssrcInfo;
    }
    private void talk(MediaServerItem mediaServerItem, Device device, String channelId, String stream,
    private void talk(MediaServer mediaServerItem, Device device, String channelId, String stream,
                      ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
                      Runnable timeoutCallback, AudioBroadcastEvent audioEvent) {
@@ -361,7 +334,7 @@
    @Override
    public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
    public void play(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
                     ErrorCallback<Object> callback) {
        if (mediaServerItem == null || ssrcInfo == null) {
@@ -495,7 +468,7 @@
    }
    private void tcpActiveHandler(Device device, String channelId, String contentString,
                                  MediaServerItem mediaServerItem,
                                  MediaServer mediaServerItem,
                                  String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<Object> callback){
        if (!device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
            return;
@@ -522,9 +495,9 @@
                }
            }
            logger.info("[TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
            JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream());
            logger.info("[TCP主动连接对方] 结果: {}" , jsonObject);
            if (jsonObject.getInteger("code") != 0) {
            Boolean result = mediaServerService.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream());
            logger.info("[TCP主动连接对方] 结果: {}" , result);
            if (!result) {
                // 主动连接失败,结束流程, 清理数据
                dynamicTask.stop(timeOutTaskKey);
                mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
@@ -564,7 +537,7 @@
     * @param channelId            通道 ID
     * @param stream               ssrc
     */
    private void snapOnPlay(MediaServerItem mediaServerItemInuse, String deviceId, String channelId, String stream) {
    private void snapOnPlay(MediaServer mediaServerItemInuse, String deviceId, String channelId, String stream) {
        String streamUrl;
        if (mediaServerItemInuse.getRtspPort() != 0) {
            streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", stream);
@@ -575,10 +548,10 @@
        String fileName = deviceId + "_" + channelId + ".jpg";
        // 请求截图
        logger.info("[请求截图]: " + fileName);
        zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
        mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
    }
    public StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId) {
    public StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, HookParam hookParam, String deviceId, String channelId) {
        StreamInfo streamInfo = null;
        Device device = redisCatchStorage.getDevice(deviceId);
        OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam;
@@ -600,7 +573,7 @@
    }
    private StreamInfo onPublishHandlerForPlayback(MediaServerItem mediaServerItem, HookParam param, String deviceId, String channelId, String startTime, String endTime) {
    private StreamInfo onPublishHandlerForPlayback(MediaServer mediaServerItem, HookParam param, String deviceId, String channelId, String startTime, String endTime) {
        OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam) param;
        StreamInfo streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, deviceId, channelId);
        if (streamInfo != null) {
@@ -624,11 +597,11 @@
    }
    @Override
    public MediaServerItem getNewMediaServerItem(Device device) {
    public MediaServer getNewMediaServerItem(Device device) {
        if (device == null) {
            return null;
        }
        MediaServerItem mediaServerItem;
        MediaServer mediaServerItem;
        if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) {
            mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
        } else {
@@ -649,7 +622,7 @@
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到设备:" + deviceId);
        }
        MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
        MediaServer newMediaServerItem = getNewMediaServerItem(device);
        if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && ! newMediaServerItem.isRtpEnable()) {
            logger.warn("[录像回放] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流");
@@ -666,7 +639,7 @@
    }
    @Override
    public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
    public void playBack(MediaServer mediaServerItem, SSRCInfo ssrcInfo,
                         String deviceId, String channelId, String startTime,
                         String endTime, ErrorCallback<Object> callback) {
        if (mediaServerItem == null || ssrcInfo == null) {
@@ -750,7 +723,7 @@
    }
    private void InviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, MediaServerItem mediaServerItem,
    private void InviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, MediaServer mediaServerItem,
                                 Device device, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback,
                                 InviteInfo inviteInfo, InviteSessionType inviteSessionType){
        inviteInfo.setStatus(InviteSessionStatus.ok);
@@ -846,7 +819,7 @@
        if (device == null) {
            return;
        }
        MediaServerItem newMediaServerItem = this.getNewMediaServerItem(device);
        MediaServer newMediaServerItem = this.getNewMediaServerItem(device);
        if (newMediaServerItem == null) {
            callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(),
                    InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(),
@@ -860,7 +833,7 @@
    @Override
    public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) {
    public void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) {
        if (mediaServerItem == null || ssrcInfo == null) {
            callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
                    InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
@@ -973,7 +946,7 @@
        // 获取当前已下载时长
        String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId();
        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
        if (mediaServerItem == null) {
            logger.warn("[获取下载进度] 查询录像信息时发现节点不存在");
            return null;
@@ -984,30 +957,13 @@
            logger.warn("[获取下载进度] 下载已结束");
            return null;
        }
        JSONObject mediaListJson= zlmresTfulUtils.getMediaList(mediaServerItem, "rtp", stream);
        if (mediaListJson == null) {
            logger.warn("[获取下载进度] 从zlm查询进度失败");
        String app = "rtp";
        MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServerItem, app, stream);
        if (mediaInfo == null) {
            logger.warn("[获取下载进度] 查询进度失败, 节点Id: {}, {}/{}", mediaServerId, app, stream);
            return null;
        }
        if (mediaListJson.getInteger("code") != 0) {
            logger.warn("[获取下载进度] 从zlm查询进度出现错误: {}", mediaListJson.getString("msg"));
            return null;
        }
        JSONArray data = mediaListJson.getJSONArray("data");
        if (data == null) {
            logger.warn("[获取下载进度] 从zlm查询进度时未返回数据");
            return null;
        }
        JSONObject mediaJSON = data.getJSONObject(0);
        JSONArray tracks = mediaJSON.getJSONArray("tracks");
        if (tracks.isEmpty()) {
            logger.warn("[获取下载进度] 从zlm查询进度时未返回数据");
            return null;
        }
        JSONObject jsonObject = tracks.getJSONObject(0);
        long duration = jsonObject.getLongValue("duration");
        if (duration == 0) {
        if (mediaInfo.getDuration() == 0) {
            inviteInfo.getStreamInfo().setProgress(0);
        } else {
            String startTime = inviteInfo.getStreamInfo().getStartTime();
@@ -1016,7 +972,7 @@
            long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
            long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
            BigDecimal currentCount = new BigDecimal(duration);
            BigDecimal currentCount = new BigDecimal(mediaInfo.getDuration());
            BigDecimal totalCount = new BigDecimal((end - start) * 1000);
            BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP);
            double process = divide.doubleValue();
@@ -1029,7 +985,7 @@
        return inviteInfo.getStreamInfo();
    }
    private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, HookParam hookParam, String deviceId, String channelId, String startTime, String endTime) {
    private StreamInfo onPublishHandlerForDownload(MediaServer mediaServerItemInuse, HookParam hookParam, String deviceId, String channelId, String startTime, String endTime) {
        OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam) hookParam;
        StreamInfo streamInfo = onPublishHandler(mediaServerItemInuse, streamChangedHookParam, deviceId, channelId);
        if (streamInfo != null) {
@@ -1048,42 +1004,9 @@
    }
    public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, OnStreamChangedHookParam hookParam, String deviceId, String channelId) {
        List<OnStreamChangedHookParam.MediaTrack> tracks = hookParam.getTracks();
        Track track = new Track();
        track.setReaderCount(hookParam.getTotalReaderCount());
        for (OnStreamChangedHookParam.MediaTrack mediaTrack : tracks) {
            switch (mediaTrack.getCodec_id()) {
                case 0:
                    track.setVideoCodec("H264");
                    break;
                case 1:
                    track.setVideoCodec("H265");
                    break;
                case 2:
                    track.setAudioCodec("AAC");
                    break;
                case 3:
                    track.setAudioCodec("G711A");
                    break;
                case 4:
                    track.setAudioCodec("G711U");
                    break;
            }
            if (mediaTrack.getSample_rate() > 0) {
                track.setAudioSampleRate(mediaTrack.getSample_rate());
            }
            if (mediaTrack.getChannels() > 0) {
                track.setAudioChannels(mediaTrack.getChannels());
            }
            if (mediaTrack.getHeight() > 0) {
                track.setHeight(mediaTrack.getHeight());
            }
            if (mediaTrack.getWidth() > 0) {
                track.setWidth(mediaTrack.getWidth());
            }
        }
        StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", hookParam.getStream(), track, null);
    public StreamInfo onPublishHandler(MediaServer mediaServerItem, OnStreamChangedHookParam hookParam, String deviceId, String channelId) {
        MediaInfo mediaInfo = MediaInfo.getInstance(hookParam);
        StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", hookParam.getStream(), mediaInfo, null);
        streamInfo.setDeviceID(deviceId);
        streamInfo.setChannelId(channelId);
        return streamInfo;
@@ -1139,7 +1062,7 @@
            logger.warn("开启语音广播的时候未找到通道: {}", channelId);
            return null;
        }
        MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
        MediaServer mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
        if (broadcastMode == null) {
            broadcastMode = true;
        }
@@ -1154,7 +1077,7 @@
    }
    @Override
    public boolean audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException {
    public boolean audioBroadcastCmd(Device device, String channelId, MediaServer mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException {
        if (device == null || channelId == null) {
            return false;
        }
@@ -1222,7 +1145,7 @@
            SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null);
            if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) {
                // 查询流是否存在,不存在则认为是异常状态
                MediaServerItem mediaServerServiceOne = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                MediaServer mediaServerServiceOne = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerServiceOne, sendRtpItem.getApp(), sendRtpItem.getStream());
                if (streamReady) {
                    logger.warn("语音广播通道使用中: {}", channelId);
@@ -1252,12 +1175,8 @@
                SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null);
                if (sendRtpItem != null) {
                    redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null);
                    MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                    Map<String, Object> param = new HashMap<>();
                    param.put("vhost", "__defaultVhost__");
                    param.put("app", sendRtpItem.getApp());
                    param.put("stream", sendRtpItem.getStream());
                    zlmresTfulUtils.stopSendRtp(mediaInfo, param);
                    MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                    mediaServerService.stopSendRtp(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream(), null);
                    try {
                        cmder.streamByeCmdForDeviceInvite(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null);
                    } catch (InvalidArgumentException | ParseException | SipException |
@@ -1333,7 +1252,7 @@
        }
        inviteInfo.getStreamInfo().setPause(true);
        inviteStreamService.updateInviteInfo(inviteInfo);
        MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
        MediaServer mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
        if (null == mediaServerItem) {
            logger.warn("mediaServer 不存在!");
            throw new ServiceException("mediaServer不存在");
@@ -1344,8 +1263,8 @@
        if (!mediaServerItem.isRtpEnable()) {
            streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase();
        }
        JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamKey);
        if (jsonObject == null || jsonObject.getInteger("code") != 0) {
        Boolean result = mediaServerService.pauseRtpCheck(mediaServerItem, streamKey);
        if (!result) {
            throw new ServiceException("暂停RTP接收失败");
        }
        Device device = storager.queryVideoDevice(inviteInfo.getDeviceId());
@@ -1361,7 +1280,7 @@
        }
        inviteInfo.getStreamInfo().setPause(false);
        inviteStreamService.updateInviteInfo(inviteInfo);
        MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
        MediaServer mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
        if (null == mediaServerItem) {
            logger.warn("mediaServer 不存在!");
            throw new ServiceException("mediaServer不存在");
@@ -1372,8 +1291,8 @@
        if (!mediaServerItem.isRtpEnable()) {
            streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase();
        }
        JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamKey);
        if (jsonObject == null || jsonObject.getInteger("code") != 0) {
        boolean result = mediaServerService.resumeRtpCheck(mediaServerItem, streamKey);
        if (!result) {
            throw new ServiceException("继续RTP接收失败");
        }
        Device device = storager.queryVideoDevice(inviteInfo.getDeviceId());
@@ -1384,7 +1303,7 @@
    public void startPushStream(SendRtpItem sendRtpItem, SIPResponse sipResponse, ParentPlatform platform, CallIdHeader callIdHeader) {
        // 开始发流
        String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
        MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
        MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
        logger.info("[开始推流] rtp/{}, 目标={}:{},SSRC={}, RTCP={}", sendRtpItem.getStream(),
                sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp());
        Map<String, Object> param = new HashMap<>(12);
@@ -1481,7 +1400,7 @@
    }
    @Override
    public void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event) {
    public void talkCmd(Device device, String channelId, MediaServer mediaServerItem, String stream, AudioBroadcastEvent event) {
        if (device == null || channelId == null) {
            return;
        }
@@ -1498,7 +1417,7 @@
            SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null);
            if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) {
                // 查询流是否存在,不存在则认为是异常状态
                MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream());
                if (streamReady) {
                    logger.warn("[语音对讲] 正在语音广播,无法开启语音通话: {}", channelId);
@@ -1512,7 +1431,7 @@
        SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, stream, null);
        if (sendRtpItem != null) {
            MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
            MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
            Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, "rtp", sendRtpItem.getReceiveStream());
            if (streamReady) {
                logger.warn("[语音对讲] 进行中: {}", channelId);
@@ -1557,7 +1476,7 @@
            return;
        }
        MediaServerItem mediaServer = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
        if (streamIsReady == null || streamIsReady) {
            Map<String, Object> param = new HashMap<>();
@@ -1592,7 +1511,7 @@
        if (inviteInfo != null) {
            if (inviteInfo.getStreamInfo() != null) {
                // 已存在线直接截图
                MediaServerItem mediaServerItemInuse = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
                MediaServer mediaServerItemInuse = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
                String streamUrl;
                if (mediaServerItemInuse.getRtspPort() != 0) {
                    streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp",  inviteInfo.getStreamInfo().getStream());
@@ -1602,7 +1521,7 @@
                String path = "snap";
                // 请求截图
                logger.info("[请求截图]: " + fileName);
                zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
                mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
                File snapFile = new File(path + File.separator + fileName);
                if (snapFile.exists()) {
                    errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), snapFile.getAbsoluteFile());
@@ -1613,7 +1532,7 @@
            }
        }
        MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
        MediaServer newMediaServerItem = getNewMediaServerItem(device);
        play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{
            if (code == InviteErrorCode.SUCCESS.getCode()) {
                InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -14,7 +14,7 @@
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.service.IGbStreamService;
@@ -108,7 +108,7 @@
    @Override
    public void save(StreamProxyItem param, GeneralCallback<StreamInfo> callback) {
        MediaServerItem mediaInfo;
        MediaServer mediaInfo;
        if (ObjectUtils.isEmpty(param.getMediaServerId()) || "auto".equals(param.getMediaServerId())){
            mediaInfo = mediaServerService.getMediaServerForMinimumLoad(null);
        }else {
@@ -310,7 +310,7 @@
    @Override
    public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
        JSONObject result = null;
        MediaServerItem mediaServerItem = null;
        MediaServer mediaServerItem = null;
        if (param.getMediaServerId() == null) {
            logger.warn("添加代理时MediaServerId 为null");
            return null;
@@ -355,7 +355,7 @@
        if (param ==null) {
            return null;
        }
        MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
        MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
        JSONObject result = null;
        if ("ffmpeg".equalsIgnoreCase(param.getType())){
            result = zlmresTfulUtils.delFFmpegSource(mediaServerItem, param.getStreamKey());
@@ -428,7 +428,7 @@
    }
    @Override
    public JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem) {
    public JSONObject getFFmpegCMDs(MediaServer mediaServerItem) {
        JSONObject result = new JSONObject();
        JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
        if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0
@@ -518,7 +518,7 @@
    }
    private void syncPullStream(String mediaServerId){
        MediaServerItem mediaServer = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
        if (mediaServer != null) {
            List<OnStreamChangedHookParam> allPullStream = redisCatchStorage.getStreams(mediaServerId, "PULL");
            if (allPullStream.size() > 0) {
@@ -571,13 +571,13 @@
    @Scheduled(cron = "* 0/10 * * * ?")
    public void asyncCheckStreamProxyStatus() {
        List<MediaServerItem> all = mediaServerService.getAllOnline();
        List<MediaServer> all = mediaServerService.getAllOnline();
        if (CollectionUtils.isEmpty(all)){
            return;
        }
        Map<String, MediaServerItem> serverItemMap = all.stream().collect(Collectors.toMap(MediaServerItem::getId, Function.identity(), (m1, m2) -> m1));
        Map<String, MediaServer> serverItemMap = all.stream().collect(Collectors.toMap(MediaServer::getId, Function.identity(), (m1, m2) -> m1));
        List<StreamProxyItem> list = videoManagerStorager.getStreamProxyListForEnable(true);
@@ -587,7 +587,7 @@
        for (StreamProxyItem streamProxyItem : list) {
            MediaServerItem mediaServerItem = serverItemMap.get(streamProxyItem.getMediaServerId());
            MediaServer mediaServerItem = serverItemMap.get(streamProxyItem.getMediaServerId());
            // TODO 支持其他 schema
            JSONObject mediaInfo = zlmresTfulUtils.isMediaOnline(mediaServerItem, streamProxyItem.getApp(), streamProxyItem.getStream(), "rtsp");
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
@@ -89,7 +89,7 @@
    @Override
    public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
    public List<StreamPushItem> handleJSON(String jsonData, MediaServer mediaServerItem) {
        if (jsonData == null) {
            return null;
        }
@@ -164,7 +164,7 @@
        gbStreamService.sendCatalogMsg(stream, CatalogEvent.DEL);
        platformGbStreamMapper.delByAppAndStream(stream.getApp(), stream.getStream());
        int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
        MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
        MediaServer mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
        JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
        if (mediaList != null) {
            if (mediaList.getInteger("code") == 0) {
@@ -195,7 +195,7 @@
        gbStreamMapper.del(app, streamId);
        int delStream = streamPushMapper.del(app, streamId);
        if (delStream > 0) {
            MediaServerItem mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId());
            MediaServer mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId());
            zlmresTfulUtils.closeStreams(mediaServerItem,app, streamId);
        }
        return true;
@@ -204,7 +204,7 @@
    @Override
    public void zlmServerOnline(String mediaServerId) {
        // 同步zlm推流信息
        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
        if (mediaServerItem == null) {
            return;
        }
@@ -470,7 +470,7 @@
        int delStream = streamPushMapper.delAllForGbStream(gbStreams);
        if (delStream > 0) {
            for (GbStream gbStream : gbStreams) {
                MediaServerItem mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId());
                MediaServer mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId());
                zlmresTfulUtils.closeStreams(mediaServerItem, gbStream.getApp(), gbStream.getStream());
            }
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
@@ -10,7 +10,7 @@
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.*;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -219,7 +219,7 @@
     * 处理收到的请求推流的请求
     */
    private void requestPushStreamMsgHand(RequestPushStreamMsg requestPushStreamMsg, String fromId, String serial) {
        MediaServerItem mediaInfo = mediaServerService.getOne(requestPushStreamMsg.getMediaServerId());
        MediaServer mediaInfo = mediaServerService.getOne(requestPushStreamMsg.getMediaServerId());
        if (mediaInfo == null) {
            // TODO 回复错误
            return;
@@ -258,7 +258,7 @@
     * 处理收到的请求sendItem的请求
     */
    private void requestSendItemMsgHand(RequestSendItemMsg content, String toId, String serial) {
        MediaServerItem mediaServerItem = mediaServerService.getOne(content.getMediaServerId());
        MediaServer mediaServerItem = mediaServerService.getOne(content.getMediaServerId());
        if (mediaServerItem == null) {
            logger.info("[回复推流信息] 流媒体{}不存在 ", content.getMediaServerId());
@@ -317,7 +317,7 @@
    /**
     * 将获取到的sendItem发送出去
     */
    private void responseSendItem(MediaServerItem mediaServerItem, RequestSendItemMsg content, String toId, String serial) {
    private void responseSendItem(MediaServer mediaServerItem, RequestSendItemMsg content, String toId, String serial) {
        SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, content.getIp(),
                content.getPort(), content.getSsrc(), content.getPlatformId(),
                content.getApp(), content.getStream(), content.getChannelId(),
@@ -449,7 +449,7 @@
            logger.info("[REDIS 执行其他平台的请求停止推流] 失败: sendRtpItem为NULL");
            return;
        }
        MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
        MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
        if (mediaInfo == null) {
            // TODO 回复错误
            return;
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java
@@ -7,7 +7,7 @@
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IStreamPushService;
@@ -95,7 +95,7 @@
                        param.put("stream",streamId);
                        param.put("ssrc",sendRtpItem.getSsrc());
                        logger.info("[REDIS消息-推流结束] 停止向上级推流:{}", streamId);
                        MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                        MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                        redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStream());
                        zlmServerFactory.stopSendRtpStream(mediaInfo, param);
                        if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) {
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -6,7 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
@@ -89,7 +89,7 @@
     * @param app
     * @param streamId
     */
    void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam item);
    void addStream(MediaServer mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam item);
    /**
     * 移除流信息从redis
src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
import org.apache.ibatis.annotations.*;
@@ -55,7 +55,7 @@
            " </script>")
    List<CloudRecordItem> getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream,
                                  @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,
                                  @Param("callId")String callId, List<MediaServerItem> mediaServerItemList);
                                  @Param("callId")String callId, List<MediaServer> mediaServerItemList);
    @Select(" <script>" +
@@ -73,7 +73,7 @@
            " </script>")
    List<String> queryRecordFilePathList(@Param("app") String app, @Param("stream") String stream,
                                  @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,
                                  @Param("callId")String callId, List<MediaServerItem> mediaServerItemList);
                                  @Param("callId")String callId, List<MediaServer> mediaServerItemList);
    @Update(" <script>" +
            "update wvp_cloud_record set collect = #{collect} where file_path in " +
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
@@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@@ -65,7 +65,7 @@
            "#{createTime}, " +
            "#{updateTime}, " +
            "#{hookAliveInterval})")
    int add(MediaServerItem mediaServerItem);
    int add(MediaServer mediaServerItem);
    @Update(value = {" <script>" +
            "UPDATE wvp_media_server " +
@@ -93,7 +93,7 @@
            "<if test=\"type != null\">, type=#{type}</if>" +
            "WHERE id=#{id}"+
            " </script>"})
    int update(MediaServerItem mediaServerItem);
    int update(MediaServer mediaServerItem);
    @Update(value = {" <script>" +
            "UPDATE wvp_media_server " +
@@ -120,13 +120,13 @@
            "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
            "WHERE ip=#{ip} and http_port=#{httpPort}"+
            " </script>"})
    int updateByHostAndPort(MediaServerItem mediaServerItem);
    int updateByHostAndPort(MediaServer mediaServerItem);
    @Select("SELECT * FROM wvp_media_server WHERE id=#{id}")
    MediaServerItem queryOne(String id);
    MediaServer queryOne(String id);
    @Select("SELECT * FROM wvp_media_server")
    List<MediaServerItem> queryAll();
    List<MediaServer> queryAll();
    @Delete("DELETE FROM wvp_media_server WHERE id=#{id}")
    void delOne(String id);
@@ -138,12 +138,12 @@
    int delDefault();
    @Select("SELECT * FROM wvp_media_server WHERE ip=#{host} and http_port=#{port}")
    MediaServerItem queryOneByHostAndPort(@Param("host") String host, @Param("port") int port);
    MediaServer queryOneByHostAndPort(@Param("host") String host, @Param("port") int port);
    @Select("SELECT * FROM wvp_media_server WHERE default_server=true")
    MediaServerItem queryDefault();
    MediaServer queryDefault();
    @Select("SELECT * FROM wvp_media_server WHERE record_assist_port > 0")
    List<MediaServerItem> queryAllWithAssistPort();
    List<MediaServer> queryAllWithAssistPort();
}
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -9,7 +9,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
@@ -313,7 +313,7 @@
    }
    @Override
    public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam onStreamChangedHookParam) {
    public void addStream(MediaServer mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam onStreamChangedHookParam) {
        // 查找是否使用了callID
        StreamAuthorityInfo streamAuthorityInfo = getStreamAuthorityInfo(app, streamId);
        String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + userSetting.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId();
src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java
@@ -1,11 +1,11 @@
package com.genersoft.iot.vmp.utils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
public class CloudRecordUtils {
    public static DownloadFileInfo getDownloadFilePath(MediaServerItem mediaServerItem, String filePath) {
    public static DownloadFileInfo getDownloadFilePath(MediaServer mediaServerItem, String filePath) {
        DownloadFileInfo downloadFileInfo = new DownloadFileInfo();
        String pathTemplate = "%s://%s:%s/index/api/downloadFile?file_path=" + filePath;
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java
@@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.vmanager.bean;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -87,7 +87,7 @@
    private String mediaServerId;
    @Schema(description = "流编码信息")
    private Track track;
    private MediaInfo mediaInfo;
    @Schema(description = "开始时间")
    private String startTime;
@@ -171,7 +171,7 @@
        }
        this.mediaServerId = streamInfo.getMediaServerId();
        this.track = streamInfo.getTrack();
        this.mediaInfo = streamInfo.getMediaInfo();
        this.startTime = streamInfo.getStartTime();
        this.endTime = streamInfo.getEndTime();
        this.progress = streamInfo.getProgress();
@@ -389,12 +389,12 @@
        this.mediaServerId = mediaServerId;
    }
    public Track getTrack() {
        return track;
    public MediaInfo getMediaInfo() {
        return mediaInfo;
    }
    public void setTrack(Track track) {
        this.track = track;
    public void setMediaInfo(MediaInfo mediaInfo) {
        this.mediaInfo = mediaInfo;
    }
    public String getStartTime() {
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java
@@ -3,7 +3,7 @@
import com.alibaba.fastjson2.JSONArray;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.ICloudRecordService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
@@ -67,10 +67,10 @@
        if (ObjectUtils.isEmpty(month)) {
            month = calendar.get(Calendar.MONTH) + 1;
        }
        List<MediaServerItem> mediaServerItems;
        List<MediaServer> mediaServerItems;
        if (!ObjectUtils.isEmpty(mediaServerId)) {
            mediaServerItems = new ArrayList<>();
            MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
            MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
            if (mediaServerItem == null) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
            }
@@ -110,10 +110,10 @@
        logger.info("[云端录像] 查询 app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}",
                app, stream, mediaServerId, page, count, startTime, endTime);
        List<MediaServerItem> mediaServerItems;
        List<MediaServer> mediaServerItems;
        if (!ObjectUtils.isEmpty(mediaServerId)) {
            mediaServerItems = new ArrayList<>();
            MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
            MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
            if (mediaServerItem == null) {
                throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
            }
@@ -162,7 +162,7 @@
            @RequestParam(required = false) String callId,
            @RequestParam(required = false) String remoteHost
    ){
        MediaServerItem mediaServerItem;
        MediaServer mediaServerItem;
        if (mediaServerId == null) {
            mediaServerItem = mediaServerService.getDefaultMediaServer();
        }else {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -17,7 +17,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.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.IInviteStreamService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IMediaService;
@@ -104,7 +104,7 @@
        logger.info("[开始点播] deviceId:{}, channelId:{}, ", deviceId, channelId);
        // 获取可用的zlm
        Device device = storager.queryVideoDevice(deviceId);
        MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
        MediaServer newMediaServerItem = playService.getNewMediaServerItem(device);
        RequestMessage requestMessage = new RequestMessage();
        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
@@ -218,7 +218,7 @@
            logger.warn("视频转码API调用失败!, 视频流已经停止!");
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到视频流信息, 视频流可能已经停止");
        }
        MediaServerItem mediaInfo = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
        MediaServer mediaInfo = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
        JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
        if (!rtpInfo.getBoolean("exist")) {
            logger.warn("视频转码API调用失败!, 视频流已停止推流!");
@@ -257,7 +257,7 @@
        if (mediaServerId == null) {
            throw new ControllerException(ErrorCode.ERROR400.getCode(), "流媒体:" + mediaServerId + "不存在" );
        }
        MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
        MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
        if (mediaInfo == null) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "使用的流媒体已经停止运行" );
        }else {
src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java
@@ -12,7 +12,7 @@
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRtpServerTimeoutHookParam;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
@@ -83,7 +83,7 @@
        logger.info("[第三方PS服务对接->开启收流和获取发流信息] isSend->{}, ssrc->{}, callId->{}, stream->{}, tcpMode->{}, callBack->{}",
                isSend, ssrc, callId, stream, tcpMode==0?"UDP":"TCP被动", callBack);
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        if (mediaServerItem == null) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(),"没有可用的MediaServer");
        }
@@ -158,7 +158,7 @@
    @Parameter(name = "stream", description = "流的ID", required = true)
    public void closeRtpServer(String stream) {
        logger.info("[第三方PS服务对接->关闭收流] stream->{}", stream);
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        zlmServerFactory.closeRtpServer(mediaServerItem,stream);
        String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_*_"  + stream;
        List<Object> scan = RedisUtil.scan(redisTemplate, receiveKey);
@@ -201,7 +201,7 @@
                        app,
                        stream,
                        callId);
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        String key = VideoManagerConstants.WVP_OTHER_SEND_PS_INFO + userSetting.getServerId() + "_"  + callId;
        OtherPsSendInfo sendInfo = (OtherPsSendInfo)redisTemplate.opsForValue().get(key);
        if (sendInfo == null) {
@@ -290,7 +290,7 @@
        param.put("app",sendInfo.getPushApp());
        param.put("stream",sendInfo.getPushStream());
        param.put("ssrc",sendInfo.getPushSSRC());
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        Boolean result = zlmServerFactory.stopSendRtpStream(mediaServerItem, param);
        if (!result) {
            logger.info("[第三方PS服务对接->关闭发送流] 失败 callId->{}", callId);
@@ -305,7 +305,7 @@
    @GetMapping(value = "/getTestPort")
    @ResponseBody
    public int getTestPort() {
        MediaServerItem defaultMediaServer = mediaServerService.getDefaultMediaServer();
        MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer();
//        for (int i = 0; i <300; i++) {
//            new Thread(() -> {
src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java
@@ -12,7 +12,7 @@
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRtpServerTimeoutHookParam;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
@@ -83,7 +83,7 @@
        logger.info("[第三方服务对接->开启收流和获取发流信息] isSend->{}, ssrc->{}, callId->{}, stream->{}, tcpMode->{}, callBack->{}",
                isSend, ssrc, callId, stream, tcpMode==0?"UDP":"TCP被动", callBack);
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        if (mediaServerItem == null) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(),"没有可用的MediaServer");
        }
@@ -162,7 +162,7 @@
    @Parameter(name = "stream", description = "流的ID", required = true)
    public void closeRtpServer(String stream) {
        logger.info("[第三方服务对接->关闭收流] stream->{}", stream);
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        zlmServerFactory.closeRtpServer(mediaServerItem,stream);
        zlmServerFactory.closeRtpServer(mediaServerItem,stream + "_a");
        String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_*_"  + stream;
@@ -225,7 +225,7 @@
        if (!((dstPortForAudio > 0 && !ObjectUtils.isEmpty(dstPortForAudio) || (dstPortForVideo > 0 && !ObjectUtils.isEmpty(dstIpForVideo))))) {
            throw new ControllerException(ErrorCode.ERROR400.getCode(), "至少应该存在一组音频或视频发送参数");
        }
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_"  + callId;
        OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key);
        if (sendInfo == null) {
@@ -367,7 +367,7 @@
        param.put("app",sendInfo.getPushApp());
        param.put("stream",sendInfo.getPushStream());
        param.put("ssrc",sendInfo.getPushSSRC());
        MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
        MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer();
        Boolean result = zlmServerFactory.stopSendRtpStream(mediaServerItem, param);
        if (!result) {
            logger.info("[第三方服务对接->关闭发送流] 失败 callId->{}", callId);
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -13,7 +13,7 @@
import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.*;
import com.genersoft.iot.vmp.service.bean.MediaServerLoad;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -83,14 +83,14 @@
    @GetMapping(value = "/media_server/list")
    @ResponseBody
    @Operation(summary = "流媒体服务列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
    public List<MediaServerItem> getMediaServerList() {
    public List<MediaServer> getMediaServerList() {
        return mediaServerService.getAll();
    }
    @GetMapping(value = "/media_server/online/list")
    @ResponseBody
    @Operation(summary = "在线流媒体服务列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
    public List<MediaServerItem> getOnlineMediaServerList() {
    public List<MediaServer> getOnlineMediaServerList() {
        return mediaServerService.getAllOnline();
    }
@@ -98,7 +98,7 @@
    @ResponseBody
    @Operation(summary = "停止视频回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "id", description = "流媒体服务ID", required = true)
    public MediaServerItem getMediaServer(@PathVariable String id) {
    public MediaServer getMediaServer(@PathVariable String id) {
        return mediaServerService.getOne(id);
    }
@@ -108,7 +108,7 @@
    @Parameter(name = "secret", description = "流媒体服务secret", required = true)
    @GetMapping(value = "/media_server/check")
    @ResponseBody
    public MediaServerItem checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret, @RequestParam String type) {
    public MediaServer checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret, @RequestParam String type) {
        return mediaServerService.checkMediaServer(ip, port, secret, type);
    }
@@ -128,8 +128,8 @@
    @Parameter(name = "mediaServerItem", description = "流媒体信息", required = true)
    @PostMapping(value = "/media_server/save")
    @ResponseBody
    public void saveMediaServer(@RequestBody MediaServerItem mediaServerItem) {
        MediaServerItem mediaServerItemInDatabase = mediaServerService.getOneFromDatabase(mediaServerItem.getId());
    public void saveMediaServer(@RequestBody MediaServer mediaServerItem) {
        MediaServer mediaServerItemInDatabase = mediaServerService.getOneFromDatabase(mediaServerItem.getId());
        if (mediaServerItemInDatabase != null) {
            mediaServerService.update(mediaServerItem);
@@ -238,11 +238,11 @@
    @Operation(summary = "获取负载信息")
    public List<MediaServerLoad> getMediaLoad() {
        List<MediaServerLoad> result = new ArrayList<>();
        List<MediaServerItem> allOnline = mediaServerService.getAllOnline();
        List<MediaServer> allOnline = mediaServerService.getAllOnline();
        if (allOnline.size() == 0) {
            return result;
        }else {
            for (MediaServerItem mediaServerItem : allOnline) {
            for (MediaServer mediaServerItem : allOnline) {
                result.add(mediaServerService.getLoad(mediaServerItem));
            }
        }
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
@@ -7,7 +7,7 @@
import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IStreamProxyService;
@@ -138,7 +138,7 @@
    public JSONObject getFFmpegCMDs(@RequestParam String mediaServerId){
        logger.debug("获取节点[ {} ]ffmpeg.cmd模板", mediaServerId );
        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
        MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
        if (mediaServerItem == null) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "流媒体: " + mediaServerId + "未找到");
        }
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
@@ -9,7 +9,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IInviteStreamService;
import com.genersoft.iot.vmp.service.IPlayService;
@@ -114,7 +114,7 @@
            result.setResult(resultJSON);
            return result;
        }
        MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
        MediaServer newMediaServerItem = playService.getNewMediaServerItem(device);
        playService.play(newMediaServerItem, serial, code, null, (errorCode, msg, data) -> {
            if (errorCode == InviteErrorCode.SUCCESS.getCode()) {