‘liusuyi’
2023-10-24 3ed3f6c299eabbda1c161408732d71ecb60b8959
暂时取消异步登录
初始化清空流媒体重新加载
已修改13个文件
355 ■■■■ 文件已修改
ard-work/src/main/java/com/ruoyi/cmd/startup.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/service/ICameraSdkService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/ArdCamerasServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/AsyncLogin.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/CameraSdkServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/dhsdk/service/impl/DhClientServiceImpl.java 96 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/hiksdk/service/impl/HikClientServiceImpl.java 137 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/inspect/service/impl/ArdVideoInspectRecordServiceImpl.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/inspect/service/impl/ArdVideoInspectTaskServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/media/service/impl/MediaServiceImpl.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/media/service/impl/VtduServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/utils/forest/MediaClient.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/mediamtx/mediamtx.yml 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/cmd/startup.java
@@ -6,6 +6,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@@ -77,6 +78,7 @@
    }
    @PostConstruct
    @Order(1)
    public void init() {
        if (minioEnabled) {
            log.info("初始化启动minio");
ard-work/src/main/java/com/ruoyi/device/camera/service/ICameraSdkService.java
@@ -6,8 +6,6 @@
import java.util.Map;
public interface ICameraSdkService {
    //初始化登录
    void loginAll();
    //登录
    Boolean login(ArdCameras ardCamera);
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/ArdCamerasServiceImpl.java
@@ -14,6 +14,7 @@
import com.ruoyi.device.channel.mapper.ArdChannelMapper;
import com.ruoyi.device.hiksdk.service.IHikClientService;
import com.ruoyi.media.domain.Vtdu;
import com.ruoyi.media.service.IMediaService;
import com.ruoyi.media.service.IVtduService;
import com.ruoyi.scheduling.domian.SchedulingParam;
import com.ruoyi.utils.gis.GisUtil;
@@ -50,9 +51,13 @@
    private ArdChannelMapper ardChannelMapper;
    @Resource
    private IVtduService vtduService;
    @Resource
    private IMediaService mediaService;
    @PostConstruct
    public void loadCameras() {
        //清空相机缓存
        Collection<String> cacheKeys = redisCache.keys(getCacheKey("*"));
        redisCache.deleteObject(cacheKeys);
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/AsyncLogin.java
@@ -1,24 +1,19 @@
package com.ruoyi.device.camera.service.impl;
import com.ruoyi.common.utils.Threads;
import com.ruoyi.device.camera.domain.ArdCameras;
import com.ruoyi.device.dhsdk.service.IDhClientService;
import com.ruoyi.device.hiksdk.service.IHikClientService;
import org.hibernate.validator.internal.util.stereotypes.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
 * @ClassName 异步登录
 * @Description:
 * @Description: 由于流媒体多线程有问题,暂时不使用异步
 * @Author 刘苏义
 * @Date 2023/10/23 21:39
 * @Version 1.0
 */
@Service
public class AsyncLogin {
    @Resource
    IHikClientService hikClientService;
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/CameraSdkServiceImpl.java
@@ -12,6 +12,8 @@
import com.ruoyi.device.hiksdk.service.IHikClientService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@@ -30,7 +32,7 @@
 **/
@Service
@Slf4j(topic = "SDK")
public class CameraSdkServiceImpl implements ICameraSdkService {
public class CameraSdkServiceImpl implements ICameraSdkService, ApplicationRunner {
    @Resource
    private IArdCamerasService ardCamerasService;
    @Resource
@@ -39,22 +41,16 @@
    IDhClientService dhClientService;
    @Resource
    RedisCache redisCache;
    @Resource
    AsyncLogin asyncLogin;
    //初始化SDK
    @PostConstruct
    @Override
    public void loginAll() {
    public void run(ApplicationArguments args) throws Exception {
        try {
            List<ArdCameras> ardCameras = ardCamerasService.selectArdCamerasListNoDataScope(new ArdCameras());
            for (ArdCameras camera : ardCameras) {
                if ("1".equals(camera.getFactory())) {
                    asyncLogin.hikLogin(camera);
                    hikClientService.login(camera);
                } else if ("2".equals(camera.getFactory())) {
                    asyncLogin.dhLogin(camera);
                    dhClientService.login(camera);
                }
            }
        } catch (Exception ex) {
@@ -70,10 +66,10 @@
            if (ardCamera != null) {
                String factory = ardCamera.getFactory();
                if (factory.equals("1")) {
                    asyncLogin.hikLogin(ardCamera);
                    hikClientService.login(ardCamera);
                    result = true;
                } else if (factory.equals("2")) {
                    asyncLogin.dhLogin(ardCamera);
                    dhClientService.login(ardCamera);
                    result = true;
                }
            }
ard-work/src/main/java/com/ruoyi/device/dhsdk/service/impl/DhClientServiceImpl.java
@@ -84,62 +84,64 @@
            ardCamerasService.updateArdCameras(camera);
            return false;
        }
        synchronized (lock) {
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            camera.setState("1");
            camera.setChanNum(m_stDeviceInfo.byChanNum);
            camera.setStartDChan(1);
            camera.setLoginId((int) loginId.longValue());
            ardCamerasService.updateArdCameras(camera);
            GlobalVariable.loginMap.put(camera.getId(), loginId);
        if (GlobalVariable.loginMap.containsKey(camera.getId())) {
            GlobalVariable.loginMap.remove(camera.getId());
        }
        //删除管理通道
        ardChannelService.deleteArdChannelByDeviceId(camera.getId());
        camera.setState("1");
        camera.setChanNum(m_stDeviceInfo.byChanNum);
        camera.setStartDChan(1);
        camera.setLoginId((int) loginId.longValue());
        ardCamerasService.updateArdCameras(camera);
        GlobalVariable.loginMap.put(camera.getId(), loginId);
            //获取最新通道
            for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
                ArdChannel channel = new ArdChannel();
                AV_CFG_ChannelName av_cfg_channelName = new AV_CFG_ChannelName();
                boolean b = ConfigModule.GetNewDevConfig(loginId, i - 1, CFG_CMD_CHANNELTITLE, av_cfg_channelName);
                if (b) {
                    String chanName = null;
                    try {
                        chanName = new String(av_cfg_channelName.szName, "GBK").trim();
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    channel.setName(chanName);
                } else {
                    channel.setName("通道" + i);
        //获取最新通道
        for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
            ArdChannel channel = new ArdChannel();
            AV_CFG_ChannelName av_cfg_channelName = new AV_CFG_ChannelName();
            boolean b = ConfigModule.GetNewDevConfig(loginId, i - 1, CFG_CMD_CHANNELTITLE, av_cfg_channelName);
            if (b) {
                String chanName = null;
                try {
                    chanName = new String(av_cfg_channelName.szName, "GBK").trim();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                channel.setDeviceId(camera.getId());
                channel.setChanNo(i);
                ardChannelService.insertArdChannel(channel);
                channel.setName(chanName);
            } else {
                channel.setName("通道" + i);
            }
            //配置到流媒体
            for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
                String name = camera.getId() + "_" + i;
                String rtspSource = "rtsp://" + camera.getUsername() + ":" + camera.getPassword() + "@" + camera.getIp() + ":" + camera.getRtspPort() + "/cam/realmonitor?channel=" + i + "&subtype=0";
                Vtdu vtdu = vtduService.selectVtduByName(name);
                if (vtdu != null) {
                    vtduService.deleteVtduByName(name);
                }
                //添加到流媒体
                CameraCmd cmd = new CameraCmd(camera.getId(), i);
                Map<String, Object> videoCompressionCfg = getVideoCompressionCfg(cmd);
                vtdu = new Vtdu();
            channel.setDeviceId(camera.getId());
            channel.setChanNo(i);
            ardChannelService.insertArdChannel(channel);
        }
        //配置到流媒体
        for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
            String name = camera.getId() + "_" + i;
            String rtspSource = "rtsp://" + camera.getUsername() + ":" + camera.getPassword() + "@" + camera.getIp() + ":" + camera.getRtspPort() + "/cam/realmonitor?channel=" + i + "&subtype=0";
            Vtdu vtdu = vtduService.selectVtduByName(name);
            if (vtdu != null) {
                vtduService.deleteVtduByName(name);
            }
            //添加到流媒体
            CameraCmd cmd = new CameraCmd(camera.getId(), i);
            Map<String, Object> videoCompressionCfg = getVideoCompressionCfg(cmd);
            vtdu = new Vtdu();
            if (videoCompressionCfg.get("videoEncType") != null) {
                if (videoCompressionCfg.get("videoEncType").equals("标准h264")) {
                    vtdu.setIsCode("0");//默认不转码
                } else {
                    vtdu.setIsCode("1");//默认转码
                }
                vtdu.setRtspSource(rtspSource);
                vtdu.setName(camera.getId() + "_" + i);
                vtdu.setMode("1");//默认CPU软解码
                vtdu.setCameraId(camera.getId());
                vtduService.insertVtdu(vtdu);
            } else {
                vtdu.setIsCode("0");//默认不转码
            }
            vtdu.setRtspSource(rtspSource);
            vtdu.setName(camera.getId() + "_" + i);
            vtdu.setMode("1");//默认CPU软解码
            vtdu.setCameraId(camera.getId());
            vtduService.insertVtdu(vtdu);
        }
        return true;
    }
ard-work/src/main/java/com/ruoyi/device/hiksdk/service/impl/HikClientServiceImpl.java
@@ -117,71 +117,72 @@
                camera.setState("0");
                return;
            }
            synchronized (lock) {
                log.debug("Login Success [ " + camera.getIp() + ":" + camera.getPort() + " ]");
                if (fExceptionCallBack == null) {
                    fExceptionCallBack = new ExceptionCallBack();//异常回调
                    //设置异常回调函数(可在回调函数中获取设备上下线状态等)
                    if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, null)) {
                        log.debug("Set fExceptionCallBack function fail");
                        return;
                    } else {
                        log.debug("Set fExceptionCallBack function successfully!");
                    }
            log.debug("Login Success [ " + camera.getIp() + ":" + camera.getPort() + " ]");
            if (fExceptionCallBack == null) {
                fExceptionCallBack = new ExceptionCallBack();//异常回调
                //设置异常回调函数(可在回调函数中获取设备上下线状态等)
                if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, null)) {
                    log.debug("Set fExceptionCallBack function fail");
                    return;
                } else {
                    log.debug("Set fExceptionCallBack function successfully!");
                }
            }
                if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                    GlobalVariable.loginMap.remove(camera.getId());
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            GlobalVariable.loginMap.put(camera.getId(), lUserID);
            GlobalVariable.loginCameraMap.put(lUserID, camera);
            camera.setLoginId(lUserID);
            camera.setState("1");
            camera.setChanNum((int) m_strDeviceInfo.struDeviceV30.byChanNum);
            camera.setStartDChan((int) m_strDeviceInfo.struDeviceV30.byStartDChan);
            //获取最新通道
            List<ArdChannel> cameraChannelList = getCameraChannelList(camera);
            if (cameraChannelList.size() > 0) {
                for (ArdChannel channel : cameraChannelList) {
                    channel.setId(IdUtils.simpleUUID());
                    ardChannelService.insertArdChannel(channel);
                }
                //删除管理通道
                ardChannelService.deleteArdChannelByDeviceId(camera.getId());
                GlobalVariable.loginMap.put(camera.getId(), lUserID);
                GlobalVariable.loginCameraMap.put(lUserID, camera);
                camera.setLoginId(lUserID);
                camera.setState("1");
                camera.setChanNum((int) m_strDeviceInfo.struDeviceV30.byChanNum);
                camera.setStartDChan((int) m_strDeviceInfo.struDeviceV30.byStartDChan);
                //获取最新通道
                List<ArdChannel> cameraChannelList = getCameraChannelList(camera);
                if (cameraChannelList.size() > 0) {
                    for (ArdChannel channel : cameraChannelList) {
                        channel.setId(IdUtils.simpleUUID());
                        ardChannelService.insertArdChannel(channel);
                //添加到流媒体
                for (ArdChannel channel : cameraChannelList) {
                    String name = camera.getId() + "_" + channel.getChanNo();
                    String rtspSource = "rtsp://" + camera.getUsername() + ":" + camera.getPassword() + "@" + camera.getIp() + ":" + camera.getRtspPort() + "/h264/ch" + channel.getChanNo() + "/main/av_stream";
                    Vtdu vtdu = vtduService.selectVtduByName(name);
                    if (vtdu != null) {
                        vtduService.deleteVtduByName(name);
                    }
                    //添加到流媒体
                    for (ArdChannel channel : cameraChannelList) {
                        String name = camera.getId() + "_" + channel.getChanNo();
                        String rtspSource = "rtsp://" + camera.getUsername() + ":" + camera.getPassword() + "@" + camera.getIp() + ":" + camera.getRtspPort() + "/h264/ch" + channel.getChanNo() + "/main/av_stream";
                        Vtdu vtdu = vtduService.selectVtduByName(name);
                        if (vtdu != null) {
                            vtduService.deleteVtduByName(name);
                        }
                        //添加到流媒体
                        vtdu = new Vtdu();
                        vtdu.setRtspSource(rtspSource);
                        vtdu.setName(camera.getId() + "_" + channel.getChanNo());
                        CameraCmd cmd = new CameraCmd(camera.getId(), channel.getChanNo());
                        Map<String, Object> videoCompressionCfg = getVideoCompressionCfg(cmd);
                        if (videoCompressionCfg.get("videoEncType").equals("标准h264")) {
                            vtdu.setIsCode("0");//默认不转码
                        } else {
                            vtdu.setIsCode("1");//默认转码
                        }
                        vtdu.setMode("1");//默认CPU软解码
                        vtdu.setCameraId(camera.getId());
                        vtduService.insertVtdu(vtdu);
                    vtdu = new Vtdu();
                    vtdu.setRtspSource(rtspSource);
                    vtdu.setName(camera.getId() + "_" + channel.getChanNo());
                    CameraCmd cmd = new CameraCmd(camera.getId(), channel.getChanNo());
                    Map<String, Object> videoCompressionCfg = getVideoCompressionCfg(cmd);
                    if (videoCompressionCfg.get("videoEncType").equals("标准h264")) {
                        vtdu.setIsCode("0");//默认不转码
                    } else {
                        vtdu.setIsCode("1");//默认转码
                    }
                    vtdu.setMode("1");//默认CPU软解码
                    vtdu.setCameraId(camera.getId());
                    vtduService.insertVtdu(vtdu);
                }
                //创建引导队列
                if (!GuidePriorityQueue.cameraQueueMap.containsKey(camera.getId())) {
                    Comparator<GuideTask> comparator = GuidePriorityQueue.getComparator();
                    PriorityBlockingQueue<GuideTask> priorityQueue = new PriorityBlockingQueue<>(1000, comparator);
                    GuidePriorityQueue.cameraQueueMap.put(camera.getId(), priorityQueue);
                }
                ardCamerasService.updateArdCameras(camera);
            }
            //创建引导队列
            if (!GuidePriorityQueue.cameraQueueMap.containsKey(camera.getId())) {
                Comparator<GuideTask> comparator = GuidePriorityQueue.getComparator();
                PriorityBlockingQueue<GuideTask> priorityQueue = new PriorityBlockingQueue<>(1000, comparator);
                GuidePriorityQueue.cameraQueueMap.put(camera.getId(), priorityQueue);
            }
            ardCamerasService.updateArdCameras(camera);
        } catch (Exception ex) {
            log.error("注册设备异常", ex);
@@ -502,19 +503,21 @@
     */
    @Override
    public Map<String, Object> getVideoCompressionCfg(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return null;
        }
        Integer userId = (Integer) GlobalVariable.loginMap.get(cameraId);
        Map<String, Object> map = new HashMap<>();
        NET_DVR_COMPRESSIONCFG_V30 compressioncfg = new NET_DVR_COMPRESSIONCFG_V30();
        compressioncfg.write();
        Pointer pioint = compressioncfg.getPointer();
        IntByReference ibrBytesReturned = new IntByReference(0);
        try {
            String cameraId = cmd.getCameraId();
            Integer chanNo = cmd.getChanNo();
            if (!GlobalVariable.loginMap.containsKey(cameraId)) {
                return null;
            }
            Integer userId = (Integer) GlobalVariable.loginMap.get(cameraId);
            NET_DVR_COMPRESSIONCFG_V30 compressioncfg = new NET_DVR_COMPRESSIONCFG_V30();
            compressioncfg.write();
            Pointer pioint = compressioncfg.getPointer();
            IntByReference ibrBytesReturned = new IntByReference(0);
            boolean bool = hCNetSDK.NET_DVR_GetDVRConfig(userId, HCNetSDK.NET_DVR_GET_COMPRESSCFG_V30, chanNo, pioint, compressioncfg.size(), ibrBytesReturned);
            if (bool) {
                compressioncfg.read();
ard-work/src/main/java/com/ruoyi/inspect/service/impl/ArdVideoInspectRecordServiceImpl.java
@@ -2,10 +2,13 @@
import java.util.HashMap;
import java.util.List;
import com.ruoyi.common.utils.uuid.IdUtils;
import org.springframework.stereotype.Service;
import com.ruoyi.inspect.mapper.ArdVideoInspectRecordMapper;
import com.ruoyi.inspect.domain.ArdVideoInspectRecord;
import com.ruoyi.inspect.service.IArdVideoInspectRecordService;
import javax.annotation.Resource;
/**
@@ -42,12 +45,13 @@
    }
    @Override
    public List<HashMap>  selectArdVideoInspectRecordListByStartTime(ArdVideoInspectRecord ardVideoInspectRecord) {
    public List<HashMap> selectArdVideoInspectRecordListByStartTime(ArdVideoInspectRecord ardVideoInspectRecord) {
        return ardVideoInspectRecordMapper.selectArdVideoInspectRecordListByStartTime(ardVideoInspectRecord);
    }
    /**
     * 按月份获取每日记录文件数量
     *
     * @param startMonth
     * @return
     */
@@ -63,8 +67,9 @@
     */
    @Override
    public int insertArdVideoInspectRecord(ArdVideoInspectRecord ardVideoInspectRecord) {
              //  ardVideoInspectRecord.setUserId(SecurityUtils.getUserId());
            return ardVideoInspectRecordMapper.insertArdVideoInspectRecord(ardVideoInspectRecord);
        //  ardVideoInspectRecord.setUserId(SecurityUtils.getUserId());
        ardVideoInspectRecord.setId(IdUtils.simpleUUID());
        return ardVideoInspectRecordMapper.insertArdVideoInspectRecord(ardVideoInspectRecord);
    }
    /**
ard-work/src/main/java/com/ruoyi/inspect/service/impl/ArdVideoInspectTaskServiceImpl.java
@@ -557,6 +557,7 @@
                String url = cameraSdkService.recordStopToMinio(cmd);
                /*插入巡检记录*/
                ArdVideoInspectRecord ardVideoInspectRecord = new ArdVideoInspectRecord();
                ardVideoInspectRecord.setId(IdUtils.simpleUUID());
                ardVideoInspectRecord.setStepId(step.getId());
                ArdAlarmpointsWell ardAlarmpointsWell = ardAlarmpointsWellMapper.selectArdAlarmpointsWellById(step.getWellId());
                if (StringUtils.isNotNull(ardAlarmpointsWell)) {
ard-work/src/main/java/com/ruoyi/media/service/impl/MediaServiceImpl.java
@@ -1,8 +1,10 @@
package com.ruoyi.media.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.dtflys.forest.Forest;
import com.dtflys.forest.exceptions.ForestNetworkException;
import com.dtflys.forest.exceptions.ForestRuntimeException;
import com.dtflys.forest.http.ForestRequest;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.media.domain.*;
import com.ruoyi.media.service.IMediaService;
@@ -10,10 +12,14 @@
import com.ruoyi.utils.tools.ArdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.xml.soap.SOAPEnvelope;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -28,13 +34,22 @@
@Service
@Slf4j(topic = "vtdu")
@Order(2)
public class MediaServiceImpl implements IMediaService {
public class MediaServiceImpl implements IMediaService, ApplicationRunner {
    private static List<String> mediaNameList = new ArrayList<>();
    @Resource
    MediaClient mediaClient;
    @Value("${mediamtx.host}")
    String mediamtxHost;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        mediaNameList = getNameList();
        if(mediaNameList.size()>0)
        {
            removePath(mediaNameList.toArray(new String[0]));
            mediaNameList.clear();
        }
    }
    /**
     * 添加流媒体
@@ -55,13 +70,13 @@
            String webrtcUrl = "http://" + mediamtxHost + ":8889/" + name;
            Conf conf = new Conf();
            String rootPath = System.getProperty("user.dir").replaceAll("\\\\", "/") + "/lib/mediamtx/";
            String rootPath = System.getProperty("user.dir").replaceAll("\\\\", "/") + "/server/mediamtx/";
            if (isCode.equals("1")) {
                conf.setSource("publisher");
                //默认软解码
                String cmd = "ffmpeg -rtsp_transport tcp -i " + sourceUrl + " -vcodec libx264 -preset:v ultrafast -r 25 -keyint_min 25 -g 60 -sc_threshold 0 -threads 6  -b:v 2048k -acodec opus  -strict -2 -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH";
                if (mode.equals("0")) {//硬解码
                    cmd = "ffmpeg -hwaccel cuvid -c:v hevc_cuvid  -rtsp_transport tcp  -i " + sourceUrl + " -c:v h264_nvenc  -r 25 -g 60 -sc_threshold 0 -threads 6  -b:v 2048k -bf 0 -acodec opus  -strict -2 -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH";
                    cmd = rootPath+"ffmpeg -hwaccel cuvid -c:v hevc_cuvid  -rtsp_transport tcp  -i " + sourceUrl + " -c:v h264_nvenc  -r 25 -g 60 -sc_threshold 0 -threads 6  -b:v 2048k -bf 0 -acodec opus  -strict -2 -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH";
                }
                conf.setRunOnDemand(cmd);
                conf.setRunOnDemandRestart(true);
@@ -74,14 +89,16 @@
            conf.setSourceProtocol("tcp");
            if (!checkNameExist(name)) {
                mediaClient.addPath(name, conf);
                 mediaClient.addPath(name, conf);
            }
            map.put("rtspUrl", rtspUrl);
            map.put("rtmpUrl", rtmpUrl);
            map.put("webrtcUrl", webrtcUrl);
        } catch (ForestNetworkException ex) {
            log.error("添加流媒体异常:" + ex.getMessage());
        } catch (ForestRuntimeException ex) {
           log.error("添加流媒体异常:"+ex.getMessage());
            log.error("添加流媒体异常:" + ex.getMessage());
        }
        return map;
    }
@@ -124,7 +141,7 @@
            map.put("rtmpUrl", rtmpUrl);
            map.put("webrtcUrl", webrtcUrl);
        } catch (ForestRuntimeException ex) {
            log.error("修改流媒体异常:"+ex.getMessage());
            log.error("修改流媒体异常:" + ex.getMessage());
        }
        return map;
    }
@@ -157,6 +174,7 @@
        for (String name : names) {
            if (checkNameExist(name)) {
                mediaClient.removePath(name);
                log.info("删除成功");
            }
        }
    }
@@ -168,7 +186,7 @@
                mediaClient.removePath(name);
            }
        } catch (ForestRuntimeException ex) {
            log.error("移除流媒体异常:"+ex.getMessage());
            log.error("移除流媒体异常:" + ex.getMessage());
        }
    }
@@ -463,11 +481,10 @@
            for (Items item : items) {
                nameList.add(item.getName());
            }
        }catch (ForestNetworkException ex) {
            log.error("获取流媒体name列表异常:"+ex.getMessage());
        }
        catch (ForestRuntimeException ex) {
            log.error("获取流媒体name列表异常:"+ex.getMessage());
        } catch (ForestNetworkException ex) {
            log.error("获取流媒体name列表异常:" + ex.getMessage());
        } catch (ForestRuntimeException ex) {
            log.error("获取流媒体name列表异常:" + ex.getMessage());
        }
        return nameList;
    }
@@ -480,8 +497,7 @@
    @Override
    public boolean checkNameExist(String name) {
        boolean result = false;
        List<String> nameList = getNameList();
        if (nameList.contains(name)) {
        if (mediaNameList.contains(name)) {
            result = true;
        }
        return result;
@@ -494,4 +510,6 @@
    public String setConfig(Config config) {
        return mediaClient.setConfig(config);
    }
}
ard-work/src/main/java/com/ruoyi/media/service/impl/VtduServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.media.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -11,6 +12,7 @@
import com.ruoyi.media.domain.Vtdu;
import com.ruoyi.media.service.IVtduService;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
ard-work/src/main/java/com/ruoyi/utils/forest/MediaClient.java
@@ -17,13 +17,13 @@
    /**
     * 增加路径
     */
    @Post(url = "/config/paths/add/{name}",async = true)
    @Post("/config/paths/add/{name}")
    public String addPath(@Var("name") String name, @JSONBody Conf body);
    /**
     * 修改路径
     */
    @Patch(url = "/config/paths/patch/{name}")
    @Patch("/config/paths/patch/{name}")
    public String editPath(@Var("name") String name, @JSONBody Conf body);
    /**
@@ -35,7 +35,7 @@
    /**
     * 获取路径详情
     */
    @Get("/config/paths/get/{name}")
    @Get(url ="/config/paths/get/{name}")
    public Conf getPathInfo(@Var("name") String name);
    /**
server/mediamtx/mediamtx.yml
@@ -44,17 +44,17 @@
# Enable the HTTP API.
api: yes
# Address of the API listener.
apiAddress: 127.0.0.1:9997
apiAddress: 192.168.1.227:9997
# Enable Prometheus-compatible metrics.
metrics: no
# Address of the metrics listener.
metricsAddress: 127.0.0.1:9998
metricsAddress: 192.168.1.227:9998
# Enable pprof-compatible endpoint to monitor performances.
pprof: no
# Address of the pprof listener.
pprofAddress: 127.0.0.1:9999
pprofAddress: 192.168.1.227:9999
# Command to run when a client connects to the server.
# This is terminated with SIGINT when a client disconnects from the server.
@@ -215,17 +215,17 @@
  # needed when server and clients are on different LANs.
  # TURN/TURNS servers are needed when a direct connection between server and
  # clients is not possible. All traffic is routed through them.
- url: stun:127.0.0.1:3478
- url: stun:stun.l.google.com:19302
  # if user is "AUTH_SECRET", then authentication is secret based.
  # the secret must be inserted into the password field.
  username: 'admin'
  password: '123456'
  username: ''
  password: ''
# List of interfaces that will be used to gather IPs to send
# to the counterpart to establish a connection.
webrtcICEInterfaces: []
# List of public IP addresses that are to be used as a host.
# This is used typically for servers that are behind 1:1 D-NAT.
webrtcICEHostNAT1To1IPs: [127.0.0.1]
webrtcICEHostNAT1To1IPs: [192.168.1.227]
# Address of a ICE UDP listener in format host:port.
# If filled, ICE traffic will pass through a single UDP port,
# allowing the deployment of the server inside a container or behind a NAT.
@@ -235,7 +235,7 @@
# allowing the deployment of the server inside a container or behind a NAT.
# Using this setting forces usage of the TCP protocol, which is not
# optimal for WebRTC.
webrtcICETCPMuxAddress: 127.0.0.1:1234
webrtcICETCPMuxAddress: 192.168.1.227:1234
###############################################
# Global settings -> SRT