ard-work/src/main/java/com/ruoyi/alarmpoints/elecwall/controller/ArdWallController.java
@@ -2,6 +2,9 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -27,6 +30,7 @@ * @author ard * @date 2023-07-20 */ @Api(tags = "çµåå´æ 管ç") @RestController @RequestMapping("/alarmpoints/wall") public class ArdWallController extends BaseController @@ -37,6 +41,7 @@ /** * æ¥è¯¢çµåå´æ 管çå表 */ @ApiOperation("æ¥è¯¢çµåå´æ 管çå表") @PreAuthorize("@ss.hasPermi('alarmpoints:wall:list')") @GetMapping("/list") public TableDataInfo list(ArdWall ardWall) @@ -62,6 +67,7 @@ /** * è·åçµåå´æ 管ç详ç»ä¿¡æ¯ */ @ApiOperation("è·åçµåå´æ 管ç详ç»ä¿¡æ¯") @PreAuthorize("@ss.hasPermi('alarmpoints:wall:query')") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") String id) @@ -72,6 +78,7 @@ /** * æ°å¢çµåå´æ 管ç */ @ApiOperation("æ°å¢çµåå´æ 管ç") @PreAuthorize("@ss.hasPermi('alarmpoints:wall:add')") @Log(title = "çµåå´æ 管ç", businessType = BusinessType.INSERT) @PostMapping @@ -83,6 +90,7 @@ /** * ä¿®æ¹çµåå´æ 管ç */ @ApiOperation("ä¿®æ¹çµåå´æ 管ç") @PreAuthorize("@ss.hasPermi('alarmpoints:wall:edit')") @Log(title = "çµåå´æ 管ç", businessType = BusinessType.UPDATE) @PutMapping @@ -94,6 +102,7 @@ /** * å é¤çµåå´æ 管ç */ @ApiOperation("å é¤çµåå´æ 管ç") @PreAuthorize("@ss.hasPermi('alarmpoints:wall:remove')") @Log(title = "çµåå´æ 管ç", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") ard-work/src/main/java/com/ruoyi/media/controller/MediaController.java
@@ -2,15 +2,15 @@ import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.device.camera.domain.ArdCameras; import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.media.domain.StreamInfo; import com.ruoyi.media.domain.Vtdu; import com.ruoyi.media.service.IMediaService; import com.ruoyi.media.service.IVtduService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; @@ -19,7 +19,6 @@ import javax.annotation.Resource; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @Description: @@ -35,11 +34,16 @@ public class MediaController extends BaseController { @Resource private IMediaService mediaService; @Resource private IVtduService vtduService; /** * å¢å éé */ @PostMapping() @ApiOperation("å¢å 转ç ") @ApiOperation("å¢å éé") @PreAuthorize("@ss.hasPermi('media:stream:add')") @ApiOperationSupport(includeParameters = {"streamInfo.name", "streamInfo.rtspSource", "streamInfo.mode"}) @ApiOperationSupport(includeParameters = {"streamInfo.name", "streamInfo.rtspSource", "streamInfo.mode", "streamInfo.isCode"}, order = 1) public AjaxResult addPath(@RequestBody StreamInfo streamInfo) { if (StringUtils.isEmpty(streamInfo.getName())) { return AjaxResult.error("ééåç§°ä¸è½ä¸ºç©º"); @@ -48,107 +52,135 @@ return AjaxResult.error("rtspå°åä¸è½ä¸ºç©º"); } String rtsp = mediaService.addPath(streamInfo.getName(), streamInfo.getRtspSource(), streamInfo.getMode(), streamInfo.getIsCode()); Vtdu vtdu = new Vtdu(); vtdu.setName(streamInfo.getName()); vtdu.setRtspUrl(streamInfo.getRtspSource()); vtdu.setIsCode(streamInfo.getIsCode()); vtdu.setCodeType(streamInfo.getMode()); vtduService.insertVtdu(vtdu); return AjaxResult.success(rtsp); } /** * ä¿®æ¹éé */ @ApiOperation("ä¿®æ¹éé") @ApiOperationSupport(includeParameters = {"streamInfo.name", "streamInfo.rtspSource", "streamInfo.mode", "streamInfo.isCode"}, order = 2) @PreAuthorize("@ss.hasPermi('media:stream:edit')") @PutMapping public AjaxResult edit(@RequestBody StreamInfo streamInfo) { mediaService.removePath(new String[]{streamInfo.getName()}); vtduService.deleteVtduByName(streamInfo.getName()); String rtsp = mediaService.addPath(streamInfo.getName(), streamInfo.getRtspSource(), streamInfo.getMode(), streamInfo.getIsCode()); Vtdu vtdu = new Vtdu(); vtdu.setName(streamInfo.getName()); vtdu.setRtspUrl(streamInfo.getRtspSource()); vtdu.setIsCode(streamInfo.getIsCode()); vtdu.setCodeType(streamInfo.getMode()); vtduService.insertVtdu(vtdu); return AjaxResult.success(rtsp); } /** * è·å转ç 详ç»ä¿¡æ¯ * ç§»é¤éé */ @ApiOperation("è·å转ç 详ç»ä¿¡æ¯") @DeleteMapping("/path/{names}") @PreAuthorize("@ss.hasPermi('media:stream:remove')") @ApiOperation("ç§»é¤éé") @ApiOperationSupport(order = 3) public AjaxResult removePath(@PathVariable String[] names) { mediaService.removePath(names); vtduService.deleteVtduByNames(names); return AjaxResult.success(); } /** * ç§»é¤ææµ */ @ApiOperation("ç§»é¤ææµ") @ApiOperationSupport(order =4 ) @PreAuthorize("@ss.hasPermi('media:stream:remove')") @DeleteMapping("/{id}") public AjaxResult removePullStreamSession(@PathVariable String sessionId) { List<StreamInfo> pullStreamList = mediaService.getPullStreamList(); StreamInfo streamInfo = pullStreamList.stream() .filter(object -> object.getId().equals(sessionId)) .collect(Collectors.toList()).get(0); switch (streamInfo.getSessionType()) { case "rtsp": return AjaxResult.success(mediaService.kickRtspSession(sessionId)); case "webrtc": return AjaxResult.success(mediaService.kickWebrtcSession(sessionId)); case "rtmp": return AjaxResult.success(mediaService.kickRtmpSession(sessionId)); } return AjaxResult.error(); } /** * è·åéé详ç»ä¿¡æ¯ */ @ApiOperation("è·åéé详ç»ä¿¡æ¯") @ApiOperationSupport(order =4 ) @GetMapping(value = "/{name}") public AjaxResult getInfo(@PathVariable("name") String name) { return success(mediaService.getPathInfo(name)); } /** * ä¿®æ¹è½¬ç * è·åå½åééå表 */ @ApiOperation("ä¿®æ¹è½¬ç ") @PreAuthorize("@ss.hasPermi('media:stream:edit')") @PutMapping public AjaxResult edit(@RequestBody StreamInfo streamInfo) { mediaService.removePath(new String[]{streamInfo.getName()}); String rtsp = mediaService.addPath(streamInfo.getName(), streamInfo.getRtspSource(), streamInfo.getMode(), streamInfo.getIsCode()); return AjaxResult.success(rtsp); } @DeleteMapping("/path/{names}") @PreAuthorize("@ss.hasPermi('media:stream:remove')") @ApiOperation("ç§»é¤è½¬ç ") public AjaxResult removePath(@PathVariable String[] names) { mediaService.removePath(names); return AjaxResult.success(); } @GetMapping("/path/list") @ApiOperation("è·åå½å转ç å表") @ApiOperation("è·åå½åééå表") @ApiOperationSupport(order = 5) public TableDataInfo getPaths() { startPage(); return getDataTable(mediaService.paths()); } @GetMapping("/getRtspSessions") @ApiOperation("è·årtspä¼è¯å表") public AjaxResult getRtspSessions() { return AjaxResult.success(mediaService.rtspsessions()); } @GetMapping("/getRtspConns") @ApiOperation("è·årtspè¿æ¥å表") public AjaxResult getRtspConns() { return AjaxResult.success(mediaService.rtspconns()); } /** * æIDæ¥è¯¢ææµè¯¦æ */ @GetMapping("/getRtspSessionById") @ApiOperation("æIDæ¥è¯¢ä¼è¯") @ApiOperation("æIDæ¥è¯¢ææµè¯¦æ ") public AjaxResult getRtspSessionById(String sessionId) { return AjaxResult.success(mediaService.getRtspSessionById(sessionId)); List<StreamInfo> pullStreamList = mediaService.getPullStreamList(); StreamInfo streamInfo = pullStreamList.stream() .filter(object -> object.getId().equals(sessionId)) .collect(Collectors.toList()).get(0); switch (streamInfo.getSessionType()) { case "rtsp": return AjaxResult.success(mediaService.getRtspSessionById(sessionId)); case "rtmp": return AjaxResult.success(mediaService.getRtmpSessionById(sessionId)); case "webrtc": return AjaxResult.success(mediaService.getWebrtcSessionById(sessionId)); } return AjaxResult.error(); } @GetMapping("/getPushStreams") @ApiOperation("è·åæ¨æµä¿¡æ¯") public AjaxResult getPushStreams() { return AjaxResult.success(mediaService.getPushStreams()); } @GetMapping("/getPullStreams") @ApiOperation("è·åææµä¿¡æ¯") public AjaxResult getPullStreams() { return AjaxResult.success(mediaService.getPullStreams()); } /** * è·åæ¨æµå表 */ @PreAuthorize("@ss.hasPermi('media:stream:list')") @GetMapping("/pushList") @ApiOperation("è·åæ¨æµå表") @ApiOperationSupport(order = 6) public TableDataInfo getPushStreamList() { startPage(); return getDataTable(mediaService.getPushStreamList()); } /** * å 餿µåªä½ææµ */ @PreAuthorize("@ss.hasPermi('media:stream:remove')") @DeleteMapping("/{id}") public AjaxResult removePullStreamSession(@PathVariable String id) { List<StreamInfo> pullStreamList = mediaService.getPullStreamList(); StreamInfo streamInfo = pullStreamList.stream() .filter(object -> object.getId().equals(id)) .collect(Collectors.toList()).get(0); switch (streamInfo.getSessionType()) { case "rtsp": return AjaxResult.success(mediaService.kickRtspSession(id)); case "webrtc": return AjaxResult.success(mediaService.kickWebrtcSession(id)); case "rtmp": return AjaxResult.success(mediaService.kickRtmpSession(id)); } return AjaxResult.error(); } /** * è·åææµå表 */ @PreAuthorize("@ss.hasPermi('media:stream:list')") @GetMapping("/pullList") @ApiOperation("è·åææµå表") @ApiOperationSupport(order = 7) public TableDataInfo getPullStreamList() { startPage(); return getDataTable(mediaService.getPullStreamList()); ard-work/src/main/java/com/ruoyi/media/controller/VtduController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,104 @@ package com.ruoyi.media.controller; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.media.domain.Vtdu; import com.ruoyi.media.service.IVtduService; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.core.page.TableDataInfo; /** * æµåªä½ç®¡çController * * @author ard * @date 2023-08-29 */ @RestController @RequestMapping("/vtdu/media") public class VtduController extends BaseController { @Autowired private IVtduService vtduService; /** * æ¥è¯¢æµåªä½ç®¡çå表 */ @PreAuthorize("@ss.hasPermi('vtdu:media:list')") @GetMapping("/list") public TableDataInfo list(Vtdu vtdu) { startPage(); List<Vtdu> list = vtduService.selectVtduList(vtdu); return getDataTable(list); } /** * å¯¼åºæµåªä½ç®¡çå表 */ @PreAuthorize("@ss.hasPermi('vtdu:media:export')") @Log(title = "æµåªä½ç®¡ç", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, Vtdu vtdu) { List<Vtdu> list = vtduService.selectVtduList(vtdu); ExcelUtil<Vtdu> util = new ExcelUtil<Vtdu>(Vtdu.class); util.exportExcel(response, list, "æµåªä½ç®¡çæ°æ®"); } /** * è·åæµåªä½ç®¡ç详ç»ä¿¡æ¯ */ @PreAuthorize("@ss.hasPermi('vtdu:media:query')") @GetMapping(value = "/{name}") public AjaxResult getInfo(@PathVariable("name") String name) { return success(vtduService.selectVtduByName(name)); } /** * æ°å¢æµåªä½ç®¡ç */ @PreAuthorize("@ss.hasPermi('vtdu:media:add')") @Log(title = "æµåªä½ç®¡ç", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody Vtdu vtdu) { return toAjax(vtduService.insertVtdu(vtdu)); } /** * ä¿®æ¹æµåªä½ç®¡ç */ @PreAuthorize("@ss.hasPermi('vtdu:media:edit')") @Log(title = "æµåªä½ç®¡ç", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody Vtdu vtdu) { return toAjax(vtduService.updateVtdu(vtdu)); } /** * å 餿µåªä½ç®¡ç */ @PreAuthorize("@ss.hasPermi('vtdu:media:remove')") @Log(title = "æµåªä½ç®¡ç", businessType = BusinessType.DELETE) @DeleteMapping("/{names}") public AjaxResult remove(@PathVariable String[] names) { return toAjax(vtduService.deleteVtduByNames(names)); } } ard-work/src/main/java/com/ruoyi/media/domain/Vtdu.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,45 @@ package com.ruoyi.media.domain; import lombok.Data; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.core.domain.BaseEntity; /** * æµåªä½ç®¡ç对象 vtdu * * @author ard * @date 2023-08-29 */ @Data public class Vtdu extends BaseEntity { private static final long serialVersionUID = 1L; /** * 主é®åç§° */ @Excel(name = "åç§°") private String name; /** * rtspæºå°å */ @Excel(name = "rtspæºå°å") private String rtspUrl; /** * æ¯å¦è½¬ç */ @Excel(name = "æ¯å¦è½¬ç ") private String isCode; /** * è½¬ç æ¨¡å¼ */ @Excel(name = "è½¬ç æ¨¡å¼") private String codeType; } ard-work/src/main/java/com/ruoyi/media/mapper/VtduMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,60 @@ package com.ruoyi.media.mapper; import java.util.List; import com.ruoyi.media.domain.Vtdu; /** * æµåªä½ç®¡çMapperæ¥å£ * * @author ard * @date 2023-08-29 */ public interface VtduMapper { /** * æ¥è¯¢æµåªä½ç®¡ç * * @param name æµåªä½ç®¡çä¸»é® * @return æµåªä½ç®¡ç */ public Vtdu selectVtduByName(String name); /** * æ¥è¯¢æµåªä½ç®¡çå表 * * @param vtdu æµåªä½ç®¡ç * @return æµåªä½ç®¡çéå */ public List<Vtdu> selectVtduList(Vtdu vtdu); /** * æ°å¢æµåªä½ç®¡ç * * @param vtdu æµåªä½ç®¡ç * @return ç»æ */ public int insertVtdu(Vtdu vtdu); /** * ä¿®æ¹æµåªä½ç®¡ç * * @param vtdu æµåªä½ç®¡ç * @return ç»æ */ public int updateVtdu(Vtdu vtdu); /** * å 餿µåªä½ç®¡ç * * @param name æµåªä½ééåç§° * @return ç»æ */ public int deleteVtduByName(String name); /** * æ¹éå 餿µåªä½ç®¡ç * * @param names éè¦å é¤çæ°æ®ä¸»é®éå * @return ç»æ */ public int deleteVtduByNames(String[] names); } ard-work/src/main/java/com/ruoyi/media/service/IMediaService.java
@@ -14,30 +14,27 @@ * åèä¹ * 2023/8/12 13:56:52 */ public String addPath(String name, String rtspPath, String mode, String isCode); String addPath(String name, String rtspPath, String mode, String isCode); StreamInfo getPathInfo(String name); public void removePath(String[] names); void removePath(String[] names); public List<StreamInfo> paths(); public List<Items> rtspconns(); public List<Items> rtspsessions(); List<StreamInfo> paths(); RtspSession getRtspSessionById(String sessionId); WebrtcSession getWebrtcSessionById(String sessionId); RtmpSession getRtmpSessionById(String sessionId); List<RtspSession> getPushStreams(); List<RtspSession> getPullStreams(); WebrtcSession getWebrtcSessionById(String sessionId); RtmpSession getRtmpSessionById(String sessionId); List<StreamInfo> getPushStreamList(); List<StreamInfo> getPullStreamList(); Boolean kickRtspSession(String sessionId); Boolean kickRtmpSession(String sessionId); Boolean kickWebrtcSession(String sessionId); } ard-work/src/main/java/com/ruoyi/media/service/IVtduService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,61 @@ package com.ruoyi.media.service; import java.util.List; import com.ruoyi.media.domain.Vtdu; /** * æµåªä½ç®¡çServiceæ¥å£ * * @author ard * @date 2023-08-29 */ public interface IVtduService { /** * æ¥è¯¢æµåªä½ç®¡ç * * @param name æµåªä½ç®¡çä¸»é® * @return æµåªä½ç®¡ç */ public Vtdu selectVtduByName(String name); /** * æ¥è¯¢æµåªä½ç®¡çå表 * * @param vtdu æµåªä½ç®¡ç * @return æµåªä½ç®¡çéå */ public List<Vtdu> selectVtduList(Vtdu vtdu); /** * æ°å¢æµåªä½ç®¡ç * * @param vtdu æµåªä½ç®¡ç * @return ç»æ */ public int insertVtdu(Vtdu vtdu); /** * ä¿®æ¹æµåªä½ç®¡ç * * @param vtdu æµåªä½ç®¡ç * @return ç»æ */ public int updateVtdu(Vtdu vtdu); /** * æ¹éå 餿µåªä½ç®¡ç * * @param names éè¦å é¤çæµåªä½ç®¡ç主é®éå * @return ç»æ */ public int deleteVtduByNames(String[] names); /** * å 餿µåªä½ç®¡çä¿¡æ¯ * * @param name æµåªä½ç®¡çä¸»é® * @return ç»æ */ public int deleteVtduByName(String name); } ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java
@@ -2,7 +2,9 @@ import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.media.domain.*; import com.ruoyi.media.mapper.VtduMapper; import com.ruoyi.media.service.IMediaService; import com.ruoyi.utils.forest.MediaClient; import com.ruoyi.utils.tools.ArdTool; @@ -33,13 +35,16 @@ @Service @Slf4j(topic = "cmd") public class MediaService implements IMediaService { @Resource VtduMapper vtduMapper; @Resource MediaClient mediaClient; @Value("${mediamtx.host}") String mediamtxHost; @Value("${mediamtx.enabled}") Boolean mediamtxEnabled; @Value("${mediamtx.software_decoding}") Boolean softwareDecoding; String processName = "mediamtx.exe"; @@ -64,6 +69,10 @@ // CmdUtils.commandStart(command); } } List<Vtdu> vtduList = vtduMapper.selectVtduList(new Vtdu()); for (Vtdu v : vtduList) { addPath(v.getName(), v.getRtspUrl(), v.getCodeType(), v.getIsCode()); } } @PreDestroy @@ -81,18 +90,25 @@ public String addPath(String name, String rtspPath, String mode, String isCode) { String rtspUrl = "rtsp://" + mediamtxHost + ":7554/" + name; Conf mediaInfo = new Conf(); String rootPath = System.getProperty("user.dir").replaceAll("\\\\", "/"); //-vcodec libx264 //æå®è§é¢ç¼ç å¨ä¸º libx264ï¼ä½¿ç¨ H.264 ç¼ç æ ¼å¼è¿è¡è§é¢å缩 //-preset ultrafast //--presetç忰䏻è¦è°èç¼ç é度åè´¨éçå¹³è¡¡ï¼æultrafastï¼è½¬ç é度æå¿«ï¼è§é¢å¾å¾ä¹ææ¨¡ç³ï¼ãsuperfastãveryfastãfasterãfastãmediumãslowãslowerãveryslowãplaceboè¿10个é项ï¼ä»å¿«å°æ ¢ //-r 25 //设置è¾åºè§é¢ç帧ç为 25 帧/ç§ //-rtsp_transport tcp //è¿ä¸ªé项åè¯ FFmpeg ä½¿ç¨ TCP ä½ä¸º RTSP çä¼ è¾åè®® //-threads 4: æå®è¦ä½¿ç¨ççº¿ç¨æ°ä¸º 4ã//è¿å 许 FFmpeg å¨å¤æ ¸å¤çå¨ä¸ä½¿ç¨å¤ä¸ªçº¿ç¨æ¥è¿è¡è§é¢ç¼ç ï¼ä»¥å å¿«é度ã // -i //ç¨äºæå®è¾å ¥åªä½æä»¶æè¾å ¥æµçå°å // -bf 0 ç¦ç¨B帧ï¼å 为webrtcå¨ç½é¡µè°ç¨æ¶æ§å¶å°ä¸ç´è¾åº WebRTC doesnât support H264 streams with B-frames //-f rtsp //è¿ä¸ªé项åè¯ FFmpeg è¾åºä¸º RTSP æ ¼å¼ã //CPU软解ç ç¼ç String cmd = "ffmpeg -rtsp_transport tcp -i \"" + rtspPath + "\" -vcodec libx264 -preset:v ultrafast -r 25 -threads 4 -b:v 4096k -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH"; //String cmd = rootPath + "/lib/mediamtx/" +"ffmpeg -rtsp_transport tcp -i " + rtspPath + " -vcodec libx264 -preset:v ultrafast -r 25 -threads 4 -b:v 2048k -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH"; //GPU硬解ç ç¼ç -hwaccel cuvid -c:v h264_cuvid 使ç¨cudaè§£ç -c:v h264_nvenc 使ç¨cudaç¼ç //String cmd = "ffmpeg -hwaccel cuvid -c:v h264_cuvid -rtsp_transport udp -i \"" + rtspPath + "\" -c:v h264_nvenc -r 25 -threads 4 -b:v 4096k -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH"; //String cmd = rootPath + "/lib/mediamtx/" + "ffmpeg -hwaccel cuvid -c:v h264_cuvid -rtsp_transport udp -i " + rtspPath + " -c:v h264_nvenc -r 25 -threads 4 -b:v 2048k -bf 0 -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH"; if (isCode.equals("1")) { String cmd = rootPath + "/lib/mediamtx/" + "ffmpeg -rtsp_transport tcp -i " + rtspPath + " -vcodec libx264 -preset:v ultrafast -r 25 -threads 4 -b:v 2048k -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH"; if (!softwareDecoding) { cmd = rootPath + "/lib/mediamtx/" + "ffmpeg -hwaccel cuvid -c:v h264_cuvid -rtsp_transport udp -i " + rtspPath + " -c:v h264_nvenc -r 25 -threads 4 -b:v 2048k -bf 0 -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH"; } if (mode.equals("1")) { mediaInfo.setRunondemand(cmd); mediaInfo.setRunondemandrestart(true); @@ -188,19 +204,6 @@ return pathInfoList; } @Override public List<Items> rtspconns() { String list = mediaClient.rtspconns(); JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class); return jsonsRoot.getItems(); } @Override public List<Items> rtspsessions() { String list = mediaClient.rtspsessions(); JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class); return jsonsRoot.getItems(); } @Override public RtspSession getRtspSessionById(String sessionId) { @@ -223,39 +226,11 @@ return rtmpSession; } @Override public List<RtspSession> getPushStreams() { List<RtspSession> rtspSessions = new ArrayList<>(); String list = mediaClient.paths(); JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class); List<Items> items = jsonsRoot.getItems(); for (Items item : items) { Source source = item.getSource(); RtspSession rtspSession = getRtspSessionById(source.getId()); rtspSession.setName(item.getName()); rtspSessions.add(rtspSession); } return rtspSessions; } @Override public List<RtspSession> getPullStreams() { List<RtspSession> rtspSessions = new ArrayList<>(); String list = mediaClient.paths(); JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class); List<Items> items = jsonsRoot.getItems(); for (Items item : items) { List<Readers> readers = item.getReaders(); for (Readers reader : readers) { RtspSession rtspSession = getRtspSessionById(reader.getId()); rtspSession.setName(item.getName()); rtspSessions.add(rtspSession); } } return rtspSessions; } /** * è·åæ¨æµå表 * åèä¹ * 2023/8/29 9:37:05 */ @Override public List<StreamInfo> getPushStreamList() { List<StreamInfo> PushStreamInfoList = new ArrayList<>(); @@ -329,6 +304,11 @@ return PushStreamInfoList; } /** * è·åææµå表 * åèä¹ * 2023/8/29 9:37:05 */ @Override public List<StreamInfo> getPullStreamList() { List<StreamInfo> PullStreamInfoList = new ArrayList<>(); @@ -380,12 +360,12 @@ //å¼å§ææµæ¶é´ info.setBeginTime(webrtcSession.getCreated()); //ä¸è¡æµé bytesReceived = webrtcSession.getBytesReceived(); formatReceivedSize = ArdTool.formatFileSize(bytesReceived); bytesReceived = webrtcSession.getBytesReceived(); formatReceivedSize = ArdTool.formatFileSize(bytesReceived); info.setUpTraffic(formatReceivedSize); //ä¸è¡æµé bytesSent = webrtcSession.getBytesSent(); formatSentSize = ArdTool.formatFileSize(bytesSent); bytesSent = webrtcSession.getBytesSent(); formatSentSize = ArdTool.formatFileSize(bytesSent); info.setDownTraffic(formatSentSize); //ææµæå¡å¨ info.setRemoteAddr(webrtcSession.getRemoteAddr()); @@ -421,6 +401,11 @@ return PullStreamInfoList; } /** * 踢åºrtspä¼è¯ * åèä¹ * 2023/8/29 9:37:05 */ @Override public Boolean kickRtspSession(String sessionId) { try { @@ -431,6 +416,11 @@ } } /** * 踢åºrtmpä¼è¯ * åèä¹ * 2023/8/29 9:37:05 */ @Override public Boolean kickRtmpSession(String sessionId) { try { @@ -441,6 +431,11 @@ } } /** * 踢åºwebrtcä¼è¯ * åèä¹ * 2023/8/29 9:37:05 */ @Override public Boolean kickWebrtcSession(String sessionId) { try { ard-work/src/main/java/com/ruoyi/media/service/impl/VtduServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,88 @@ package com.ruoyi.media.service.impl; import java.util.List; import com.ruoyi.common.utils.uuid.IdUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.media.mapper.VtduMapper; import com.ruoyi.media.domain.Vtdu; import com.ruoyi.media.service.IVtduService; /** * æµåªä½ç®¡çServiceä¸å¡å±å¤ç * * @author ard * @date 2023-08-29 */ @Service public class VtduServiceImpl implements IVtduService { @Autowired private VtduMapper vtduMapper; /** * æ¥è¯¢æµåªä½ç®¡ç * * @param name æµåªä½ç®¡çä¸»é® * @return æµåªä½ç®¡ç */ @Override public Vtdu selectVtduByName(String name) { return vtduMapper.selectVtduByName(name); } /** * æ¥è¯¢æµåªä½ç®¡çå表 * * @param vtdu æµåªä½ç®¡ç * @return æµåªä½ç®¡ç */ @Override public List<Vtdu> selectVtduList(Vtdu vtdu) { return vtduMapper.selectVtduList(vtdu); } /** * æ°å¢æµåªä½ç®¡ç * * @param vtdu æµåªä½ç®¡ç * @return ç»æ */ @Override public int insertVtdu(Vtdu vtdu) { return vtduMapper.insertVtdu(vtdu); } /** * ä¿®æ¹æµåªä½ç®¡ç * * @param vtdu æµåªä½ç®¡ç * @return ç»æ */ @Override public int updateVtdu(Vtdu vtdu) { return vtduMapper.updateVtdu(vtdu); } /** * æ¹éå 餿µåªä½ç®¡ç * * @param names éè¦å é¤çæ°æ®ä¸»é®éå * @return ç»æ */ @Override public int deleteVtduByNames(String[] names) { return vtduMapper.deleteVtduByNames(names); } /** * å 餿µåªä½ç®¡ç * * @param name æµåªä½ééåç§° * @return ç»æ */ @Override public int deleteVtduByName(String name) { return vtduMapper.deleteVtduByName(name); } } ard-work/src/main/resources/mapper/vtdu/VtduMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,69 @@ <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.media.mapper.VtduMapper"> <resultMap type="Vtdu" id="VtduResult"> <result property="name" column="name" /> <result property="rtspUrl" column="rtsp_url" /> <result property="isCode" column="is_code" /> <result property="codeType" column="code_type" /> </resultMap> <sql id="selectVtduVo"> select name, rtsp_url, is_code, code_type from vtdu </sql> <select id="selectVtduList" parameterType="Vtdu" resultMap="VtduResult"> <include refid="selectVtduVo"/> <where> <if test="name != null and name != ''"> and name like '%'||#{name}||'%'</if> <if test="rtspUrl != null and rtspUrl != ''"> and rtsp_url = #{rtspUrl}</if> <if test="isCode != null and isCode != ''"> and is_code = #{isCode}</if> <if test="codeType != null and codeType != ''"> and code_type = #{codeType}</if> </where> </select> <select id="selectVtduByName" parameterType="String" resultMap="VtduResult"> <include refid="selectVtduVo"/> where name = #{name} </select> <insert id="insertVtdu" parameterType="Vtdu"> insert into vtdu <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null">name,</if> <if test="rtspUrl != null">rtsp_url,</if> <if test="isCode != null">is_code,</if> <if test="codeType != null">code_type,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="name != null">#{name},</if> <if test="rtspUrl != null">#{rtspUrl},</if> <if test="isCode != null">#{isCode},</if> <if test="codeType != null">#{codeType},</if> </trim> </insert> <update id="updateVtdu" parameterType="Vtdu"> update vtdu <trim prefix="SET" suffixOverrides=","> <if test="rtspUrl != null">rtsp_url = #{rtspUrl},</if> <if test="isCode != null">is_code = #{isCode},</if> <if test="codeType != null">code_type = #{codeType},</if> </trim> where name = #{name} </update> <delete id="deleteVtduByName" parameterType="String"> delete from vtdu where name = #{name} </delete> <delete id="deleteVtduByNames" parameterType="String"> delete from vtdu where name in <foreach item="name" collection="array" open="(" separator="," close=")"> #{name} </foreach> </delete> </mapper> ard-work/src/main/resources/templates/mediaMTX.html
@@ -10,7 +10,7 @@ .video-container { display: inline-block; vertical-align: top; width: 25%; /* å 个è§é¢å¹³ååé ä¸è¡ç宽度 */ width: 33%; /* 3个è§é¢å¹³ååé ä¸è¡ç宽度 */ /*padding: 2px; !* å¯ä»¥æ ¹æ®éè¦è°æ´å è¾¹è· *!*/ box-sizing: border-box; } @@ -42,7 +42,16 @@ </div> </div> <script th:inline="javascript"> const restartPause = 2000; var chanMap = new Map(); window.onload = function () { chanMap.set("video1", "http://127.0.0.1:8889/164/"); chanMap.set("video2", "http://127.0.0.1:8889/164/"); chanMap.set("video3", "http://127.0.0.1:8889/164/"); chanMap.set("video4", "http://127.0.0.1:8889/165/"); chanMap.set("video5", "http://127.0.0.1:8889/165/"); console.log(chanMap); } const linkToIceServers = (links) => ( (links !== null) ? links.split(', ').map((link) => { const m = link.match(/^<(.+?)>; rel="ice-server"(; username="(.*?)"; credential="(.*?)"; credential-type="password")?/i); @@ -260,22 +269,37 @@ this.eTag = ''; this.queuedCandidates = []; } stop() { if (this.pc) { try { this.pc.close(); } catch (e) { console.log("Failure close peer connection:" + e); } this.pc = null; } } } let videoMap = new Map(); $('video').click(function (e) { let ID = e.target.id;//è·åå½åç¹å»äºä»¶çå ç´ console.log(ID); console.log(videoMap); if (videoMap.get(ID) != null) { closeVideo(ID, videoMap.get(ID)); closeVideo(ID); } else { let client = new WHEPClient("http://127.0.0.1:8889/165/", ID); let stream = chanMap.get(ID); let client = new WHEPClient(stream, ID); videoMap.set(ID, client); } }); function closeVideo(id) { let elementById = document.getElementById(id); elementById.pause(); console.log("å ³é" + id) let client = videoMap.get(id); client.stop(id); videoMap.delete(id); } </script>