From 35d87ba0e7567ec001123ef7d83e63f211dc02e7 Mon Sep 17 00:00:00 2001
From: ‘liusuyi’ <1951119284@qq.com>
Date: 星期四, 13 七月 2023 17:28:09 +0800
Subject: [PATCH] 增加流媒体编解码业务

---
 ard-work/src/main/java/com/ruoyi/media/domain/Conf.java                |  133 +++++++++++++++++++
 /dev/null                                                              |   15 --
 ard-work/src/main/java/com/ruoyi/media/domain/Items.java               |   23 +++
 ard-work/src/main/java/com/ruoyi/media/controller/MediaController.java |   50 +++++++
 ard-work/src/main/java/com/ruoyi/media/domain/JsonsRoot.java           |   23 +++
 ard-work/src/main/java/com/ruoyi/utils/forest/MediaClient.java         |   26 +++
 ard-work/src/main/java/com/ruoyi/media/domain/Source.java              |   16 ++
 ard-work/src/main/java/com/ruoyi/media/service/IMediaService.java      |   10 +
 ard-work/src/main/java/com/ruoyi/media/domain/MediaInfo.java           |   16 ++
 ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java  |   66 +++++++++
 10 files changed, 363 insertions(+), 15 deletions(-)

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
new file mode 100644
index 0000000..83bdeea
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/controller/MediaController.java
@@ -0,0 +1,50 @@
+package com.ruoyi.media.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.media.domain.MediaInfo;
+import com.ruoyi.media.service.IMediaService;
+import com.ruoyi.media.service.impl.MediaService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * @Description:
+ * @ClassName: controller
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�13鏃�9:26
+ * @Version: 1.0
+ **/
+@RestController
+@Api(tags = "娴佸獟浣撴帴鍙�")
+@Anonymous
+public class MediaController {
+    @Resource
+    private IMediaService mediaService;
+
+    @PostMapping("/add")
+    @ApiOperation("澧炲姞杞爜")
+    public AjaxResult addPath(@RequestBody MediaInfo mediaInfo) {
+        String rtsp = mediaService.addPath(mediaInfo.getName(), mediaInfo.getRtspPath());
+        return AjaxResult.success(rtsp);
+    }
+    @PostMapping("/remove")
+    @ApiOperation("绉婚櫎杞爜")
+    @ApiOperationSupport(includeParameters={"mediaInfo.name"})
+    public AjaxResult removePath(@RequestBody MediaInfo mediaInfo) {
+        mediaService.removePath(mediaInfo.getName());
+        return AjaxResult.success();
+    }
+    @GetMapping("/getList")
+    @ApiOperation("鑾峰彇褰撳墠杞爜鍒楄〃")
+    public AjaxResult getList() {
+        return AjaxResult.success(mediaService.list());
+    }
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/domain/Conf.java b/ard-work/src/main/java/com/ruoyi/media/domain/Conf.java
new file mode 100644
index 0000000..85480b8
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/domain/Conf.java
@@ -0,0 +1,133 @@
+package com.ruoyi.media.domain;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Description:
+ * @ClassName: MediaInfo
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�13鏃�9:32
+ * @Version: 1.0
+ **/
+@Data
+public class Conf {
+    private String source;
+    @JsonProperty("sourceFingerprint")
+    private String sourcefingerprint;
+    @JsonProperty("sourceOnDemand")
+    private boolean sourceondemand;
+    @JsonProperty("sourceOnDemandStartTimeout")
+    private String sourceondemandstarttimeout;
+    @JsonProperty("sourceOnDemandCloseAfter")
+    private String sourceondemandcloseafter;
+    @JsonProperty("publishUser")
+    private String publishuser;
+    @JsonProperty("publishPass")
+    private String publishpass;
+    @JsonProperty("publishIPs")
+    private List<String> publiships;
+    @JsonProperty("readUser")
+    private String readuser;
+    @JsonProperty("readPass")
+    private String readpass;
+    @JsonProperty("readIPs")
+    private List<String> readips;
+    @JsonProperty("disablePublisherOverride")
+    private boolean disablepublisheroverride;
+    private String fallback;
+    @JsonProperty("sourceProtocol")
+    private String sourceprotocol;
+    @JsonProperty("sourceAnyPortEnable")
+    private boolean sourceanyportenable;
+    @JsonProperty("rtspRangeType")
+    private String rtsprangetype;
+    @JsonProperty("rtspRangeStart")
+    private String rtsprangestart;
+    @JsonProperty("sourceRedirect")
+    private String sourceredirect;
+    @JsonProperty("rpiCameraCamID")
+    private int rpicameracamid;
+    @JsonProperty("rpiCameraWidth")
+    private int rpicamerawidth;
+    @JsonProperty("rpiCameraHeight")
+    private int rpicameraheight;
+    @JsonProperty("rpiCameraHFlip")
+    private boolean rpicamerahflip;
+    @JsonProperty("rpiCameraVFlip")
+    private boolean rpicameravflip;
+    @JsonProperty("rpiCameraBrightness")
+    private int rpicamerabrightness;
+    @JsonProperty("rpiCameraContrast")
+    private int rpicameracontrast;
+    @JsonProperty("rpiCameraSaturation")
+    private int rpicamerasaturation;
+    @JsonProperty("rpiCameraSharpness")
+    private int rpicamerasharpness;
+    @JsonProperty("rpiCameraExposure")
+    private String rpicameraexposure;
+    @JsonProperty("rpiCameraAWB")
+    private String rpicameraawb;
+    @JsonProperty("rpiCameraDenoise")
+    private String rpicameradenoise;
+    @JsonProperty("rpiCameraShutter")
+    private int rpicamerashutter;
+    @JsonProperty("rpiCameraMetering")
+    private String rpicamerametering;
+    @JsonProperty("rpiCameraGain")
+    private int rpicameragain;
+    @JsonProperty("rpiCameraEV")
+    private int rpicameraev;
+    @JsonProperty("rpiCameraROI")
+    private String rpicameraroi;
+    @JsonProperty("rpiCameraTuningFile")
+    private String rpicameratuningfile;
+    @JsonProperty("rpiCameraMode")
+    private String rpicameramode;
+    @JsonProperty("rpiCameraFPS")
+    private int rpicamerafps;
+    @JsonProperty("rpiCameraIDRPeriod")
+    private int rpicameraidrperiod;
+    @JsonProperty("rpiCameraBitrate")
+    private int rpicamerabitrate;
+    @JsonProperty("rpiCameraProfile")
+    private String rpicameraprofile;
+    @JsonProperty("rpiCameraLevel")
+    private String rpicameralevel;
+    @JsonProperty("rpiCameraAfMode")
+    private String rpicameraafmode;
+    @JsonProperty("rpiCameraAfRange")
+    private String rpicameraafrange;
+    @JsonProperty("rpiCameraAfSpeed")
+    private String rpicameraafspeed;
+    @JsonProperty("rpiCameraLensPosition")
+    private int rpicameralensposition;
+    @JsonProperty("rpiCameraAfWindow")
+    private String rpicameraafwindow;
+    @JsonProperty("rpiCameraTextOverlayEnable")
+    private boolean rpicameratextoverlayenable;
+    @JsonProperty("rpiCameraTextOverlay")
+    private String rpicameratextoverlay;
+    @JsonProperty("runOnInit")
+    private String runoninit;
+    @JsonProperty("runOnInitRestart")
+    private boolean runoninitrestart;
+    @JsonProperty("runOnDemand")
+    private String runondemand;
+    @JsonProperty("runOnDemandRestart")
+    private boolean runondemandrestart;
+    @JsonProperty("runOnDemandStartTimeout")
+    private String runondemandstarttimeout;
+    @JsonProperty("runOnDemandCloseAfter")
+    private String runondemandcloseafter;
+    @JsonProperty("runOnReady")
+    private String runonready;
+    @JsonProperty("runOnReadyRestart")
+    private boolean runonreadyrestart;
+    @JsonProperty("runOnRead")
+    private String runonread;
+    @JsonProperty("runOnReadRestart")
+    private boolean runonreadrestart;
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/domain/Items.java b/ard-work/src/main/java/com/ruoyi/media/domain/Items.java
new file mode 100644
index 0000000..bb933cd
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/domain/Items.java
@@ -0,0 +1,23 @@
+package com.ruoyi.media.domain;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Description:
+ * @ClassName: Items
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�13鏃�10:23
+ * @Version: 1.0
+ **/
+@Data
+public class Items {
+    private String name;
+    private String confname;
+    private Conf conf;
+    private Source source;
+    private boolean sourceready;
+    private List<String> tracks;
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/domain/JsonsRoot.java b/ard-work/src/main/java/com/ruoyi/media/domain/JsonsRoot.java
new file mode 100644
index 0000000..0c8808d
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/domain/JsonsRoot.java
@@ -0,0 +1,23 @@
+package com.ruoyi.media.domain;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Description:
+ * @ClassName: JsonObject
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�13鏃�10:06
+ * @Version: 1.0
+ **/
+@Data
+public class JsonsRoot {
+
+    private int itemcount;
+
+    private int pagecount;
+
+    private List<Items> items;
+
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/domain/MediaInfo.java b/ard-work/src/main/java/com/ruoyi/media/domain/MediaInfo.java
new file mode 100644
index 0000000..8def810
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/domain/MediaInfo.java
@@ -0,0 +1,16 @@
+package com.ruoyi.media.domain;
+
+import lombok.Data;
+
+/**
+ * @Description:
+ * @ClassName: MediaInfo
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�13鏃�10:11
+ * @Version: 1.0
+ **/
+@Data
+public class MediaInfo {
+    String name;
+    String rtspPath;
+}
diff --git a/ard-work/src/main/java/com/ruoyi/media/domain/Source.java b/ard-work/src/main/java/com/ruoyi/media/domain/Source.java
new file mode 100644
index 0000000..966d3d8
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/domain/Source.java
@@ -0,0 +1,16 @@
+package com.ruoyi.media.domain;
+
+import lombok.Data;
+
+/**
+ * @Description:
+ * @ClassName: Source
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�13鏃�10:24
+ * @Version: 1.0
+ **/
+@Data
+public class Source {
+    private String type;
+    private String id;
+}
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
new file mode 100644
index 0000000..b23fff6
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/service/IMediaService.java
@@ -0,0 +1,10 @@
+package com.ruoyi.media.service;
+import com.ruoyi.media.domain.Items;
+import java.util.List;
+
+public interface IMediaService {
+
+    public String addPath(String name, String rtspPath);
+    public void removePath(String name);
+    public List<Items>list();
+}
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
new file mode 100644
index 0000000..b360b82
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java
@@ -0,0 +1,66 @@
+package com.ruoyi.media.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.media.domain.Conf;
+import com.ruoyi.media.domain.Items;
+import com.ruoyi.media.domain.JsonsRoot;
+import com.ruoyi.media.service.IMediaService;
+import com.ruoyi.utils.forest.MediaClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * @Description:
+ * @ClassName: MediaService
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�13鏃�9:28
+ * @Version: 1.0
+ **/
+@Service
+public class MediaService implements IMediaService {
+
+    @Resource
+    MediaClient mediaClient;
+
+    @Value("${mediamtx.host}")
+    String mediamtxHost;
+
+    @Override
+    public String addPath(String name, String rtspPath) {
+        String apiUrl="http://"+mediamtxHost+":9997/v2";
+        String rtspUrl="rtsp://"+mediamtxHost+":8554/";
+        Conf mediaInfo = new Conf();
+        //-vcodec libx264 //鎸囧畾瑙嗛缂栫爜鍣ㄤ负 libx264锛屼娇鐢� H.264 缂栫爜鏍煎紡杩涜瑙嗛鍘嬬缉
+        //-preset ultrafast  //--preset鐨勫弬鏁颁富瑕佽皟鑺傜紪鐮侀�熷害鍜岃川閲忕殑骞宠 锛屾湁ultrafast锛堣浆鐮侀�熷害鏈�蹇紝瑙嗛寰�寰�涔熸渶妯$硦锛夈�乻uperfast銆乿eryfast銆乫aster銆乫ast銆乵edium銆乻low銆乻lower銆乿eryslow銆乸lacebo杩�10涓�夐」锛屼粠蹇埌鎱�
+        //-r 25 //璁剧疆杈撳嚭瑙嗛鐨勫抚鐜囦负 25 甯�/绉�
+        //-rtsp_transport tcp //杩欎釜閫夐」鍛婅瘔 FFmpeg 浣跨敤 TCP 浣滀负 RTSP 鐨勪紶杈撳崗璁�
+        //-threads 4: 鎸囧畾瑕佷娇鐢ㄧ殑绾跨▼鏁颁负 4銆�//杩欏厑璁� FFmpeg 鍦ㄥ鏍稿鐞嗗櫒涓婁娇鐢ㄥ涓嚎绋嬫潵杩涜瑙嗛缂栫爜锛屼互鍔犲揩閫熷害銆�
+        // -i //鐢ㄤ簬鎸囧畾杈撳叆濯掍綋鏂囦欢鎴栬緭鍏ユ祦鐨勫湴鍧�
+        //-f rtsp //杩欎釜閫夐」鍛婅瘔 FFmpeg 杈撳嚭涓� RTSP 鏍煎紡銆�
+        //CPU杞В鐮佺紪鐮�
+        //String cmd = "ffmpeg -rtsp_transport udp -i \"" + rtspPath + "\" -vcodec libx264 -preset:v veryfast  -r 25 -threads 4 -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH";
+        //GPU纭В鐮佺紪鐮�
+        String cmd = "ffmpeg -hwaccel cuvid -c:v h264_cuvid  -rtsp_transport udp  -i \"" + rtspPath + "\" -c:v h264_nvenc  -r 25 -threads 4 -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH";
+        mediaInfo.setRunoninit(cmd);
+        mediaInfo.setRunoninitrestart(true);
+        mediaClient.add(apiUrl, name, mediaInfo);
+        return rtspUrl + name;
+    }
+
+    @Override
+    public void removePath(String name) {
+        String apiUrl="http://"+mediamtxHost+":9997/v2";
+        mediaClient.remove(apiUrl, name);
+    }
+
+    @Override
+    public List<Items> list() {
+        String apiUrl="http://"+mediamtxHost+":9997/v2";
+        String list = mediaClient.list(apiUrl);
+        JsonsRoot jsonsRoot = JSONObject.parseObject(list, JsonsRoot.class);
+        return jsonsRoot.getItems();
+    }
+}
diff --git a/ard-work/src/main/java/com/ruoyi/utils/forest/MediaClient.java b/ard-work/src/main/java/com/ruoyi/utils/forest/MediaClient.java
new file mode 100644
index 0000000..0f8adfc
--- /dev/null
+++ b/ard-work/src/main/java/com/ruoyi/utils/forest/MediaClient.java
@@ -0,0 +1,26 @@
+package com.ruoyi.utils.forest;
+
+import com.dtflys.forest.annotation.Get;
+import com.dtflys.forest.annotation.JSONBody;
+import com.dtflys.forest.annotation.Post;
+import com.dtflys.forest.annotation.Var;
+import com.ruoyi.media.domain.Conf;
+
+/**
+ * @Description: mediamtx娴佸獟浣撳鎴风
+ * @ClassName: client
+ * @Author: 鍒樿嫃涔�
+ * @Date: 2023骞�07鏈�06鏃�9:51
+ * @Version: 1.0
+ **/
+public interface MediaClient {
+
+    @Post("{apiUrl}/config/paths/add/{name}")
+    String add(@Var("apiUrl") String apiUrl,@Var("name") String name, @JSONBody Conf body);
+
+    @Post("{apiUrl}/config/paths/remove/{name}")
+    String remove(@Var("apiUrl") String apiUrl,@Var("name") String name);
+
+    @Get("{apiUrl}/paths/list")
+    String list(@Var("apiUrl") String apiUrl);
+}
diff --git a/ard-work/src/main/java/com/ruoyi/utils/forest/client.java b/ard-work/src/main/java/com/ruoyi/utils/forest/client.java
deleted file mode 100644
index 3ad830a..0000000
--- a/ard-work/src/main/java/com/ruoyi/utils/forest/client.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.ruoyi.utils.forest;
-
-import com.dtflys.forest.annotation.Get;
-
-/**
- * @Description:
- * @ClassName: client
- * @Author: 鍒樿嫃涔�
- * @Date: 2023骞�07鏈�06鏃�9:51
- * @Version: 1.0
- **/
-public interface client {
-    @Get("http://www.baidu.com")
-    String getBaiDu();
-}

--
Gitblit v1.9.3