From 510c29eecab77493816d3f0cdb5e5c4462083cc8 Mon Sep 17 00:00:00 2001
From: ‘liusuyi’ <1951119284@qq.com>
Date: Tue, 29 Aug 2023 14:03:55 +0800
Subject: [PATCH] 增加流媒体数据库业务 增加电子围栏接口
---
ard-work/src/main/java/com/ruoyi/media/mapper/VtduMapper.java | 60 ++++
ard-work/src/main/java/com/ruoyi/media/controller/MediaController.java | 178 ++++++++-----
ard-work/src/main/java/com/ruoyi/media/service/impl/VtduServiceImpl.java | 88 ++++++
ard-work/src/main/resources/mapper/vtdu/VtduMapper.xml | 69 +++++
ard-work/src/main/resources/templates/mediaMTX.html | 36 ++
ard-work/src/main/java/com/ruoyi/media/controller/VtduController.java | 104 ++++++++
ard-work/src/main/java/com/ruoyi/alarmpoints/elecwall/controller/ArdWallController.java | 9
ard-work/src/main/java/com/ruoyi/media/service/IMediaService.java | 19
ard-work/src/main/java/com/ruoyi/media/service/IVtduService.java | 61 ++++
ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java | 101 +++----
ard-work/src/main/java/com/ruoyi/media/domain/Vtdu.java | 45 +++
11 files changed, 627 insertions(+), 143 deletions(-)
diff --git a/ard-work/src/main/java/com/ruoyi/alarmpoints/elecwall/controller/ArdWallController.java b/ard-work/src/main/java/com/ruoyi/alarmpoints/elecwall/controller/ArdWallController.java
index 786865c..07d9c27 100644
--- a/ard-work/src/main/java/com/ruoyi/alarmpoints/elecwall/controller/ArdWallController.java
+++ b/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}")
diff --git a/ard-work/src/main/java/com/ruoyi/media/controller/MediaController.java b/ard-work/src/main/java/com/ruoyi/media/controller/MediaController.java
index ca50877..e91ca81 100644
--- a/ard-work/src/main/java/com/ruoyi/media/controller/MediaController.java
+++ b/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());
diff --git a/ard-work/src/main/java/com/ruoyi/media/controller/VtduController.java b/ard-work/src/main/java/com/ruoyi/media/controller/VtduController.java
new file mode 100644
index 0000000..e6847aa
--- /dev/null
+++ b/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));
+ }
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/domain/Vtdu.java b/ard-work/src/main/java/com/ruoyi/media/domain/Vtdu.java
new file mode 100644
index 0000000..bbf9d60
--- /dev/null
+++ b/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;
+
+
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/mapper/VtduMapper.java b/ard-work/src/main/java/com/ruoyi/media/mapper/VtduMapper.java
new file mode 100644
index 0000000..db474de
--- /dev/null
+++ b/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);
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/service/IMediaService.java b/ard-work/src/main/java/com/ruoyi/media/service/IMediaService.java
index bd99555..8337a5f 100644
--- a/ard-work/src/main/java/com/ruoyi/media/service/IMediaService.java
+++ b/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);
}
diff --git a/ard-work/src/main/java/com/ruoyi/media/service/IVtduService.java b/ard-work/src/main/java/com/ruoyi/media/service/IVtduService.java
new file mode 100644
index 0000000..7fb33dd
--- /dev/null
+++ b/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);
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java b/ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java
index 090961e..9b69946 100644
--- a/ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java
+++ b/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 {
diff --git a/ard-work/src/main/java/com/ruoyi/media/service/impl/VtduServiceImpl.java b/ard-work/src/main/java/com/ruoyi/media/service/impl/VtduServiceImpl.java
new file mode 100644
index 0000000..ebf5978
--- /dev/null
+++ b/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);
+ }
+}
diff --git a/ard-work/src/main/resources/mapper/vtdu/VtduMapper.xml b/ard-work/src/main/resources/mapper/vtdu/VtduMapper.xml
new file mode 100644
index 0000000..30dd0fb
--- /dev/null
+++ b/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>
\ No newline at end of file
diff --git a/ard-work/src/main/resources/templates/mediaMTX.html b/ard-work/src/main/resources/templates/mediaMTX.html
index 2ae58db..b3a39ee 100644
--- a/ard-work/src/main/resources/templates/mediaMTX.html
+++ b/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>
--
Gitblit v1.9.3