|  |  | 
 |  |  |  | 
 |  |  | import com.alibaba.fastjson2.JSONObject; | 
 |  |  | import com.dtflys.forest.exceptions.ForestNetworkException; | 
 |  |  | import com.dtflys.forest.exceptions.ForestRuntimeException; | 
 |  |  | import com.ruoyi.common.utils.StringUtils; | 
 |  |  | import com.ruoyi.media.domain.*; | 
 |  |  | import com.ruoyi.media.service.IMediaService; | 
 |  |  | 
 |  |  | 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; | 
 |  |  |  | 
 |  |  | 
 |  |  |  * @Version: 1.0 | 
 |  |  |  **/ | 
 |  |  | @Service | 
 |  |  | @Slf4j(topic = "cmd") | 
 |  |  | @Slf4j(topic = "vtdu") | 
 |  |  | @Order(2) | 
 |  |  | public class MediaServiceImpl implements IMediaService { | 
 |  |  |  | 
 |  |  | 
 |  |  |  | 
 |  |  |     @Value("${mediamtx.host}") | 
 |  |  |     String mediamtxHost; | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 添加流媒体 | 
 |  |  | 
 |  |  |      */ | 
 |  |  |     @Override | 
 |  |  |     public Map<String, String> addPath(String name, String sourceUrl, String mode, String isCode) { | 
 |  |  |  | 
 |  |  |         String rtspUrl = "rtsp://" + mediamtxHost + ":8554/" + name; | 
 |  |  |         String rtmpUrl = "rtmp://" + mediamtxHost + ":1935/" + name; | 
 |  |  |         String webrtcUrl = "http://" + mediamtxHost + ":8889/" + name; | 
 |  |  |  | 
 |  |  |         Conf conf = new Conf(); | 
 |  |  |         String rootPath = System.getProperty("user.dir").replaceAll("\\\\", "/") + "/lib/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"; | 
 |  |  |             } | 
 |  |  |             conf.setRunOnDemand(cmd); | 
 |  |  |             conf.setRunOnDemandRestart(true); | 
 |  |  |             conf.setRunOnDemandCloseAfter("5s"); | 
 |  |  |         } else { | 
 |  |  |             conf.setSource(sourceUrl); | 
 |  |  |             conf.setSourceOnDemand(true); | 
 |  |  |         } | 
 |  |  |         conf.setMaxReaders(100); | 
 |  |  |         conf.setSourceProtocol("tcp"); | 
 |  |  |  | 
 |  |  |         if (!checkNameExist(name)) { | 
 |  |  |             mediaClient.addPath(name, conf); | 
 |  |  |         } | 
 |  |  |         Map<String, String> map = new HashMap<>(); | 
 |  |  |         map.put("rtspUrl", rtspUrl); | 
 |  |  |         map.put("rtmpUrl", rtmpUrl); | 
 |  |  |         map.put("webrtcUrl", webrtcUrl); | 
 |  |  |         try { | 
 |  |  |             String rtspUrl = "rtsp://" + mediamtxHost + ":8554/" + name; | 
 |  |  |             String rtmpUrl = "rtmp://" + mediamtxHost + ":1935/" + name; | 
 |  |  |             String webrtcUrl = "http://" + mediamtxHost + ":8889/" + name; | 
 |  |  |  | 
 |  |  |             Conf conf = new Conf(); | 
 |  |  |             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 = 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); | 
 |  |  |                 conf.setRunOnDemandCloseAfter("5s"); | 
 |  |  |             } else { | 
 |  |  |                 conf.setSource(sourceUrl); | 
 |  |  |                 conf.setSourceOnDemand(true); | 
 |  |  |             } | 
 |  |  |             conf.setMaxReaders(100); | 
 |  |  |             conf.setSourceProtocol("tcp"); | 
 |  |  |  | 
 |  |  |             if (!checkNameExist(name)) { | 
 |  |  |                 mediaClient.addPath(name, conf); | 
 |  |  |             } else { | 
 |  |  |                 mediaClient.editPath(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()); | 
 |  |  |         } | 
 |  |  |         return map; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |             } else { | 
 |  |  |                 conf.setSource(sourceUrl); | 
 |  |  |                 conf.setSourceOnDemand(true); | 
 |  |  |                 conf.setRunOnDemand(""); | 
 |  |  |                 conf.setRunOnDemandRestart(false); | 
 |  |  |                 conf.setRunOnDemandCloseAfter("5s"); | 
 |  |  |             } | 
 |  |  |             conf.setMaxReaders(100); | 
 |  |  |             conf.setSourceProtocol("tcp"); | 
 |  |  | 
 |  |  |             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()); | 
 |  |  |         } | 
 |  |  |         return map; | 
 |  |  |     } | 
 |  |  | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public void removePath(String[] names) { | 
 |  |  |         for (String name : names) { | 
 |  |  |             if (checkNameExist(name)) { | 
 |  |  |                 mediaClient.removePath(name); | 
 |  |  |         try { | 
 |  |  |             for (String name : names) { | 
 |  |  |                 if (checkNameExist(name)) { | 
 |  |  |                     mediaClient.removePath(name); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } catch (Exception ex) { | 
 |  |  |             log.error("批量移除流媒体异常:" + ex.getMessage()); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public void removePath(String name) { | 
 |  |  |         if (checkNameExist(name)) { | 
 |  |  |             mediaClient.removePath(name); | 
 |  |  |         try { | 
 |  |  |             if (checkNameExist(name)) { | 
 |  |  |                 mediaClient.removePath(name); | 
 |  |  |             } | 
 |  |  |         } catch (ForestRuntimeException ex) { | 
 |  |  |             log.error("移除流媒体异常:" + ex.getMessage()); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public List<StreamInfo> paths() { | 
 |  |  |         String list = mediaClient.paths(); | 
 |  |  |         JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class); | 
 |  |  |         List<Items> items = jsonsRoot.getItems(); | 
 |  |  |         Paths paths = mediaClient.paths(); | 
 |  |  |         List<Items> items = paths.getItems(); | 
 |  |  |         List<StreamInfo> pathInfoList = new ArrayList<>(); | 
 |  |  |         for (Items item : items) { | 
 |  |  |             StreamInfo info = new StreamInfo(); | 
 |  |  | 
 |  |  |     @Override | 
 |  |  |     public List<StreamInfo> getPushStreamList() { | 
 |  |  |         List<StreamInfo> PushStreamInfoList = new ArrayList<>(); | 
 |  |  |         String list = mediaClient.paths(); | 
 |  |  |         JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class); | 
 |  |  |         List<Items> items = jsonsRoot.getItems(); | 
 |  |  |         Paths paths = mediaClient.paths(); | 
 |  |  |         List<Items> items = paths.getItems(); | 
 |  |  |         for (Items item : items) { | 
 |  |  |             StreamInfo info = new StreamInfo(); | 
 |  |  |             //ID | 
 |  |  | 
 |  |  |                 long bytesReceived = item.getBytesReceived(); | 
 |  |  |                 String formatReceivedSize = ArdTool.formatFileSize(bytesReceived); | 
 |  |  |                 info.setUpTraffic(formatReceivedSize); | 
 |  |  |                 info.setBeginTime(item.getReadyTime()); | 
 |  |  |             } else { | 
 |  |  |                 RtspSession rtspSession = getRtspSessionById(source.getId()); | 
 |  |  |                 //会话ID | 
 |  |  | 
 |  |  |     @Override | 
 |  |  |     public List<StreamInfo> getPullStreamList() { | 
 |  |  |         List<StreamInfo> PullStreamInfoList = new ArrayList<>(); | 
 |  |  |         String list = mediaClient.paths(); | 
 |  |  |         JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class); | 
 |  |  |         List<Items> items = jsonsRoot.getItems(); | 
 |  |  |         Paths paths = mediaClient.paths(); | 
 |  |  |         List<Items> items = paths.getItems(); | 
 |  |  |         for (Items item : items) { | 
 |  |  |             List<Readers> readers = item.getReaders(); | 
 |  |  |             for (Readers reader : readers) { | 
 |  |  | 
 |  |  |                         PullStreamInfoList.add(info); | 
 |  |  |                         break; | 
 |  |  |                     case "webRTCSession": | 
 |  |  |                     case "webrtcSession": | 
 |  |  |                         info.setSessionType("webrtc"); | 
 |  |  |                         //webrtc播放地址 | 
 |  |  |                         url = "http://" + mediamtxHost + ":8889/" + name; | 
 |  |  | 
 |  |  |     @Override | 
 |  |  |     public List<String> getNameList() { | 
 |  |  |         List<String> nameList = new ArrayList<>(); | 
 |  |  |         String paths = mediaClient.paths(); | 
 |  |  |         JsonsRoot jsonsRoot = JSONObject.parseObject(paths, JsonsRoot.class); | 
 |  |  |         List<Items> items = jsonsRoot.getItems(); | 
 |  |  |         for (Items item : items) { | 
 |  |  |             nameList.add(item.getName()); | 
 |  |  |         try { | 
 |  |  |             Paths paths = mediaClient.paths(); | 
 |  |  |             List<Items> items = paths.getItems(); | 
 |  |  |             for (Items item : items) { | 
 |  |  |                 nameList.add(item.getName()); | 
 |  |  |             } | 
 |  |  |         } catch (Exception ex) { | 
 |  |  |             log.error("获取流媒体name列表异常:" + ex.getMessage()); | 
 |  |  |         } | 
 |  |  |         return nameList; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 检查名称是否存在 | 
 |  |  |      * 检查name是否存在 | 
 |  |  |      * 刘苏义 | 
 |  |  |      * 2023/10/19 15:18:45 | 
 |  |  |      */ | 
 |  |  | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 配置流媒体参数 | 
 |  |  |      */ | 
 |  |  |     @Override | 
 |  |  |     public String setConfig(Config config) { | 
 |  |  |         return mediaClient.setConfig(config); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } |