648540858
2024-03-20 c7ca9703c196c5ac39de5594049171f3a1bf067c
优化媒体节点服务的代码结构
16个文件已修改
1个文件已添加
387 ■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/bean/Track.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.common;
import com.genersoft.iot.vmp.media.bean.Track;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -70,7 +71,7 @@
    @Schema(description = "流媒体ID")
    private String mediaServerId;
    @Schema(description = "流编码信息")
    private Object tracks;
    private Track track;
    @Schema(description = "开始时间")
    private String startTime;
    @Schema(description = "结束时间")
@@ -473,12 +474,12 @@
        this.mediaServerId = mediaServerId;
    }
    public Object getTracks() {
        return tracks;
    public Track getTrack() {
        return track;
    }
    public void setTracks(Object tracks) {
        this.tracks = tracks;
    public void setTrack(Track track) {
        this.track = track;
    }
    public String getStartTime() {
src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java
@@ -32,9 +32,6 @@
    @Autowired
    private CloudRecordServiceMapper cloudRecordServiceMapper;
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
    /**
     * 定时查询待删除的录像文件
     */
@@ -66,10 +63,10 @@
                // TODO 后续可以删除空了的过期日期文件夹
                for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
                    String date = new File(cloudRecordItem.getFilePath()).getParentFile().getName();
                    JSONObject jsonObject = zlmresTfulUtils.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(),
                    boolean deleteResult = mediaServerService.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(),
                            cloudRecordItem.getStream(), date, cloudRecordItem.getFileName());
                    if (jsonObject.getInteger("code") != 0) {
                        logger.warn("[录像文件定时清理] 删除磁盘文件错误: {}:{}", cloudRecordItem.getFilePath(), jsonObject);
                    if (deleteResult) {
                        logger.warn("[录像文件定时清理] 删除磁盘文件成功: {}", cloudRecordItem.getFilePath());
                    }
                }
                result += cloudRecordServiceMapper.deleteList(cloudRecordItemList);
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
@@ -54,9 +54,6 @@
    private IDeviceService deviceService;
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
    @Autowired
    private IMediaServerService mediaServerService;
    @Autowired
@@ -109,13 +106,8 @@
                redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream());
                if (mediaServerItem != null) {
                    ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
                    Map<String, Object> param = new HashMap<>();
                    param.put("vhost","__defaultVhost__");
                    param.put("app",sendRtpItem.getApp());
                    param.put("stream",sendRtpItem.getStream());
                    param.put("ssrc",sendRtpItem.getSsrc());
                    JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
                    if (jsonObject != null && jsonObject.getInteger("code") == 0) {
                    boolean stopResult = mediaServerService.stopSendRtp(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
                    if (stopResult) {
                        ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
                        if (platform != null) {
                            try {
src/main/java/com/genersoft/iot/vmp/media/bean/Track.java
New file
@@ -0,0 +1,80 @@
package com.genersoft.iot.vmp.media.bean;
import io.swagger.v3.oas.annotations.media.Schema;
/**
 * 视频信息
 */
@Schema(description = "视频信息")
public class Track {
    @Schema(description = "观看人数")
    private Integer readerCount;
    @Schema(description = "视频编码类型")
    private String videoCodec;
    @Schema(description = "视频宽度")
    private Integer width;
    @Schema(description = "视频高度")
    private Integer height;
    @Schema(description = "音频编码类型")
    private String audioCodec;
    @Schema(description = "音频通道数")
    private Integer audioChannels;
    @Schema(description = "音频采样率")
    private Integer audioSampleRate;
    public Integer getReaderCount() {
        return readerCount;
    }
    public void setReaderCount(Integer readerCount) {
        this.readerCount = readerCount;
    }
    public String getVideoCodec() {
        return videoCodec;
    }
    public void setVideoCodec(String videoCodec) {
        this.videoCodec = videoCodec;
    }
    public Integer getWidth() {
        return width;
    }
    public void setWidth(Integer width) {
        this.width = width;
    }
    public Integer getHeight() {
        return height;
    }
    public void setHeight(Integer height) {
        this.height = height;
    }
    public String getAudioCodec() {
        return audioCodec;
    }
    public void setAudioCodec(String audioCodec) {
        this.audioCodec = audioCodec;
    }
    public Integer getAudioChannels() {
        return audioChannels;
    }
    public void setAudioChannels(Integer audioChannels) {
        this.audioChannels = audioChannels;
    }
    public Integer getAudioSampleRate() {
        return audioSampleRate;
    }
    public void setAudioSampleRate(Integer audioSampleRate) {
        this.audioSampleRate = audioSampleRate;
    }
}
src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java
@@ -1,7 +1,10 @@
package com.genersoft.iot.vmp.media.service;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import java.util.List;
public interface IMediaNodeServerService {
    int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode);
@@ -19,4 +22,10 @@
    void online(MediaServerItem mediaServerItem);
    MediaServerItem checkMediaServer(String ip, int port, String secret);
    boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc);
    boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName);
    List<StreamInfo> getMediaList(MediaServerItem mediaServerItem, String app, String stream);
}
src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java
@@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.media.service;
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.service.bean.MediaServerLoad;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -69,4 +70,10 @@
    List<MediaServerItem> getAllWithAssistPort();
    MediaServerItem getOneFromDatabase(String id);
    boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc);
    boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName);
    List<StreamInfo> getMediaList(MediaServerItem mediaInfo, String app, String stream);
}
src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java
@@ -1,7 +1,9 @@
package com.genersoft.iot.vmp.media.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.CommonCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
@@ -533,4 +535,33 @@
    }
    @Override
    public boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaInfo.getType());
        if (mediaNodeServerService == null) {
            logger.info("[stopSendRtp] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaInfo.getType());
            return false;
        }
        return mediaNodeServerService.stopSendRtp(mediaInfo, app, stream, ssrc);
    }
    @Override
    public boolean deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[stopSendRtp] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
            return false;
        }
        return mediaNodeServerService.deleteRecordDirectory(mediaServerItem, app, stream, date, fileName);
    }
    @Override
    public List<StreamInfo> getMediaList(MediaServerItem mediaServerItem, String app, String stream) {
        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType());
        if (mediaNodeServerService == null) {
            logger.info("[getMediaList] 失败, mediaServerItem的类型: {},未找到对应的实现类", mediaServerItem.getType());
            return new ArrayList<>();
        }
        return mediaNodeServerService.getMediaList(mediaServerItem, app, stream);
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -18,6 +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.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.media.zlm.dto.hook.*;
@@ -33,6 +34,7 @@
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;
@@ -368,6 +370,39 @@
            }
            List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
            Track track = new Track();
            track.setReaderCount(param.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());
                }
            }
            // TODO 重构此处逻辑
            if (param.isRegist()) {
                // 处理流注册的鉴权信息, 流注销这里不再删除鉴权信息,下次来了新的鉴权信息会对就的进行覆盖
@@ -471,7 +506,7 @@
                                callId = streamAuthorityInfo.getCallId();
                            }
                            StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo,
                                    param.getApp(), param.getStream(), tracks, callId);
                                    param.getApp(), param.getStream(), track, callId);
                            param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
                            redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param);
                            if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
@@ -7,7 +7,6 @@
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
@@ -29,12 +28,6 @@
public class ZLMMediaListManager {
    private Logger logger = LoggerFactory.getLogger("ZLMMediaListManager");
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
    @Autowired
    private IRedisCatchStorage redisCatchStorage;
    @Autowired
    private IVideoManagerStorage storager;
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java
@@ -4,17 +4,30 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
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.service.IMediaNodeServerService;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service("zlm")
public class ZLMMediaNodeServerService implements IMediaNodeServerService {
    private final static Logger logger = LoggerFactory.getLogger(ZLMMediaNodeServerService.class);
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
@@ -106,4 +119,77 @@
        mediaServerItem.setType("zlm");
        return mediaServerItem;
    }
    @Override
    public boolean stopSendRtp(MediaServerItem mediaInfo, String app, String stream, String ssrc) {
        Map<String, Object> param = new HashMap<>();
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
        param.put("stream", stream);
        if (!ObjectUtils.isEmpty(ssrc)) {
            param.put("ssrc", ssrc);
        }
        JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaInfo, param);
        return (jsonObject != null && jsonObject.getInteger("code") == 0);
    }
    @Override
    public boolean deleteRecordDirectory(MediaServerItem 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);
        if (jsonObject.getInteger("code") == 0) {
            return true;
        }else {
            logger.info("[zlm-deleteRecordDirectory] 删除磁盘文件错误, server: {} {}:{}->{}/{}, 结果: {}", mediaServerItem.getId(), app, stream, date, fileName, jsonObject);
            return false;
        }
    }
    @Override
    public List<StreamInfo> getMediaList(MediaServerItem mediaServerItem, String app, String stream) {
        List<StreamInfo> streamInfoList = new ArrayList<>();
        JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServerItem, app, stream);
        if (mediaList != null) {
            if (mediaList.getInteger("code") == 0) {
                JSONArray data = mediaList.getJSONArray("data");
                if (data == null) {
                    return null;
                }
                JSONObject mediaJSON = data.getJSONObject(0);
                JSONArray tracks = mediaJSON.getJSONArray("tracks");
                if (authority) {
                    streamInfo = getStreamInfoByAppAndStream(mediaServerItem, app, stream, tracks, null, calld, true);
                }else {
                    streamInfo = getStreamInfoByAppAndStream(mediaServerItem, app, stream, tracks, null,null, true);
                }
            }
        }
        return streamInfoList;
    }
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String addr, String callId, boolean isPlay) {
        StreamInfo streamInfoResult = new StreamInfo();
        streamInfoResult.setStream(stream);
        streamInfoResult.setApp(app);
        if (addr == null) {
            addr = mediaInfo.getStreamIp();
        }
        streamInfoResult.setIp(addr);
        streamInfoResult.setMediaServerId(mediaInfo.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.setTrack(track);
        return streamInfoResult;
    }
}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java
@@ -17,7 +17,7 @@
@Component
public class ZLMServerFactory {
    private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
    private Logger logger = LoggerFactory.getLogger("ZLMServerFactory");
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java
@@ -32,7 +32,7 @@
    /**
     * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
     */
    private String totalReaderCount;
    private int totalReaderCount;
    /**
     * 协议 包括hls/rtsp/rtmp/http-flv/ws-flv
@@ -374,11 +374,11 @@
        this.stream = stream;
    }
    public String getTotalReaderCount() {
    public int getTotalReaderCount() {
        return totalReaderCount;
    }
    public void setTotalReaderCount(String totalReaderCount) {
    public void setTotalReaderCount(int totalReaderCount) {
        this.totalReaderCount = totalReaderCount;
    }
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
@@ -2,6 +2,7 @@
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;
/**
@@ -32,7 +33,7 @@
     * @param stream
     * @return
     */
    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Object tracks, String callId);
    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Track track, String callId);
    /**
     * 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
@@ -40,5 +41,5 @@
     * @param stream
     * @return
     */
    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId, boolean isPlay);
    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String addr, String callId, boolean isPlay);
}
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -14,7 +14,6 @@
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.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.service.IDeviceService;
@@ -54,6 +53,7 @@
    @Autowired
    private SIPCommander cmder;
    @Autowired
    private DynamicTask dynamicTask;
@@ -101,9 +101,6 @@
    @Autowired
    private AudioBroadcastManager audioBroadcastManager;
    @Autowired
    private ZLMRESTfulUtils zlmresTfulUtils;
    @Override
    public void online(Device device, SipTransactionInfo sipTransactionInfo) {
@@ -245,11 +242,7 @@
                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);
                    mediaServerService.stopSendRtp(mediaInfo, sendRtpItem.getApp(), sendRtpItem.getStream());
                }
                audioBroadcastManager.del(deviceId, audioBroadcastCatch.getChannelId());
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -4,6 +4,7 @@
import com.alibaba.fastjson2.JSONObject;
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.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
@@ -13,6 +14,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.List;
@Service
public class MediaServiceImpl implements IMediaService {
@@ -31,8 +34,8 @@
    @Override
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String callId) {
        return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, callId, true);
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String callId) {
        return getStreamInfoByAppAndStream(mediaInfo, app, stream, track, null, callId, true);
    }
    @Override
@@ -50,23 +53,12 @@
        if (streamAuthorityInfo != null) {
            calld = streamAuthorityInfo.getCallId();
        }
        JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream);
        if (mediaList != null) {
            if (mediaList.getInteger("code") == 0) {
                JSONArray data = mediaList.getJSONArray("data");
                if (data == null) {
                    return null;
                }
                JSONObject mediaJSON = data.getJSONObject(0);
                JSONArray tracks = mediaJSON.getJSONArray("tracks");
                if (authority) {
                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld, true);
                }else {
                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null, true);
                }
            }
        List<StreamInfo> streamInfoList = mediaServerService.getMediaList(mediaInfo, app, stream);
        if (streamInfoList.isEmpty()) {
            return null;
        }else {
            return streamInfoList.get(0);
        }
        return streamInfo;
    }
@@ -77,7 +69,7 @@
    }
    @Override
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId, boolean isPlay) {
    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Track track, String addr, String callId, boolean isPlay) {
        StreamInfo streamInfoResult = new StreamInfo();
        streamInfoResult.setStream(stream);
        streamInfoResult.setApp(app);
@@ -96,7 +88,7 @@
        streamInfoResult.setTs(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam);
        streamInfoResult.setRtc(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app,  stream, callIdParam, isPlay);
        streamInfoResult.setTracks(tracks);
        streamInfoResult.setTrack(track);
        return streamInfoResult;
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -18,6 +18,7 @@
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.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
@@ -1048,7 +1049,41 @@
    public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, OnStreamChangedHookParam hookParam, String deviceId, String channelId) {
        StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", hookParam.getStream(), hookParam.getTracks(), null);
        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);
        streamInfo.setDeviceID(deviceId);
        streamInfo.setChannelId(channelId);
        return streamInfo;
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java
@@ -1,6 +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.service.bean.DownloadFileInfo;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -86,7 +87,7 @@
    private String mediaServerId;
    @Schema(description = "流编码信息")
    private Object tracks;
    private Track track;
    @Schema(description = "开始时间")
    private String startTime;
@@ -170,7 +171,7 @@
        }
        this.mediaServerId = streamInfo.getMediaServerId();
        this.tracks = streamInfo.getTracks();
        this.track = streamInfo.getTracks();
        this.startTime = streamInfo.getStartTime();
        this.endTime = streamInfo.getEndTime();
        this.progress = streamInfo.getProgress();