From dab37ef8c41decd4a26468ebd9fe77093051b996 Mon Sep 17 00:00:00 2001
From: ‘liusuyi’ <1951119284@qq.com>
Date: Tue, 29 Aug 2023 17:12:29 +0800
Subject: [PATCH] 更新流媒体mediaMTX版本V1.0.0
---
ard-work/src/main/java/com/ruoyi/media/service/impl/MediaService.java | 251 +++++++++++++++++++++++++++++++------------------
1 files changed, 159 insertions(+), 92 deletions(-)
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 9852e1d..c9bc8b8 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,25 +2,22 @@
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;
-import com.ruoyi.utils.tools.CmdUtils;
+import com.ruoyi.utils.process.CmdUtils;
import com.sun.jna.Platform;
-import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -38,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";
@@ -69,6 +69,15 @@
// CmdUtils.commandStart(command);
}
}
+ List<StreamInfo> paths = paths();
+ for(StreamInfo path:paths)
+ {
+ mediaClient.removePath(path.getName());
+ }
+ List<Vtdu> vtduList = vtduMapper.selectVtduList(new Vtdu());
+ for (Vtdu v : vtduList) {
+ addPath(v.getName(), v.getRtspUrl(), v.getCodeType(), v.getIsCode());
+ }
}
@PreDestroy
@@ -86,18 +95,24 @@
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);
@@ -135,9 +150,7 @@
if (matcher.find()) {
info.setRtspSource(matcher.group());
info.setIsCode("1");
- }
- else
- {
+ } else {
info.setRtspSource(item.getConf().getSource());
info.setIsCode("0");
}
@@ -169,7 +182,7 @@
info.setMode("1");
} else {
runoninit = item.getConf().getRunoninit();
- info.setMode("2");
+ info.setMode("0");
}
//RTSP源地址
String regex = "rtsp://[^\\s\"]+";
@@ -195,19 +208,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) {
@@ -217,38 +217,24 @@
}
@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;
+ public WebrtcSession getWebrtcSessionById(String sessionId) {
+ String list = mediaClient.getWebrtcsessionById(sessionId);
+ WebrtcSession webrtcSession = JSONObject.parseObject(list, WebrtcSession.class);
+ return webrtcSession;
}
@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;
+ public RtmpSession getRtmpSessionById(String sessionId) {
+ String list = mediaClient.getRtmpsessionById(sessionId);
+ RtmpSession rtmpSession = JSONObject.parseObject(list, RtmpSession.class);
+ return rtmpSession;
}
+ /**
+ * 获取推流列表
+ * 刘苏义
+ * 2023/8/29 9:37:05
+ */
@Override
public List<StreamInfo> getPushStreamList() {
List<StreamInfo> PushStreamInfoList = new ArrayList<>();
@@ -260,11 +246,17 @@
//ID
String name = item.getName();
info.setName(name);
+ //RTMP播放地址
+ String rtmpUrl = "rtmp://" + mediamtxHost + ":1935/" + name;
+ info.setRtmpUrl(rtmpUrl);
//RTSP播放地址
String rtspUrl = "rtsp://" + mediamtxHost + ":7554/" + name;
info.setRtspUrl(rtspUrl);
+ //WEBRTC播放地址
+ String webrtcUrl = "http://" + mediamtxHost + ":8889/" + name;
+ info.setWebrtcUrl(webrtcUrl);
Source source = item.getSource();
- if (source.getId().equals("")) {
+ if (source == null || source.getId().equals("")) {
//会话ID
info.setId("0");
//上行流量
@@ -301,18 +293,10 @@
Matcher matcher = pattern.matcher(runoninit);
if (matcher.find()) {
info.setRtspSource(matcher.group());
- }
- else
- {
+ } else {
info.setRtspSource(item.getConf().getSource());
}
//传输协议
-// regex = "-rtsp_transport\\s+(\\w+)";
-// pattern = Pattern.compile(regex);
-// matcher = pattern.matcher(runoninit);
-// if (matcher.find()) {
-// info.setProtocol(matcher.group(1));
-// }
info.setProtocol(item.getConf().getSourceprotocol());
//拉流数量
List<Readers> readers = item.getReaders();
@@ -324,6 +308,11 @@
return PushStreamInfoList;
}
+ /**
+ * 获取拉流列表
+ * 刘苏义
+ * 2023/8/29 9:37:05
+ */
@Override
public List<StreamInfo> getPullStreamList() {
List<StreamInfo> PullStreamInfoList = new ArrayList<>();
@@ -337,46 +326,124 @@
//ID
String name = item.getName();
info.setName(name);
- //RTSP播放地址
- String rtspUrl = "rtsp://" + mediamtxHost + ":8554/" + name;
- info.setRtspUrl(rtspUrl);
- RtspSession rtspSession = getRtspSessionById(reader.getId());
- //会话ID
- info.setId(rtspSession.getId());
- //开始拉流时间
- info.setBeginTime(rtspSession.getCreated());
- //上行流量
- long bytesReceived = rtspSession.getBytesReceived();
- String formatReceivedSize = ArdTool.formatFileSize(bytesReceived);
- info.setUpTraffic(formatReceivedSize);
- //下行流量
- long bytesSent = rtspSession.getBytesSent();
- String formatSentSize = ArdTool.formatFileSize(bytesSent);
- info.setDownTraffic(formatSentSize);
-
//传输协议
-// String runoninit = item.getConf().getRunondemand();
-// String regex = "-rtsp_transport\\s+(\\w+)";
-// Pattern pattern = Pattern.compile(regex);
-// Matcher matcher = pattern.matcher(runoninit);
-// if (matcher.find()) {
-// info.setProtocol(matcher.group(1));
-// }
info.setProtocol(item.getConf().getSourceprotocol());
- //拉流服务器
- info.setRemoteAddr(rtspSession.getRemoteAddr());
- PullStreamInfoList.add(info);
+
+ String type = reader.getType();
+ switch (type) {
+ case "rtmpConn":
+ info.setSessionType("rtmp");
+ //webrtc播放地址
+ String url = "rtmp://" + mediamtxHost + ":1935/" + name;
+ info.setRtspUrl(url);
+ RtmpSession rtmpSession = getRtmpSessionById(reader.getId());
+ //会话ID
+ info.setId(rtmpSession.getId());
+ //开始拉流时间
+ info.setBeginTime(rtmpSession.getCreated());
+ //上行流量
+ long bytesReceived = rtmpSession.getBytesReceived();
+ String formatReceivedSize = ArdTool.formatFileSize(bytesReceived);
+ info.setUpTraffic(formatReceivedSize);
+ //下行流量
+ long bytesSent = rtmpSession.getBytesSent();
+ String formatSentSize = ArdTool.formatFileSize(bytesSent);
+ info.setDownTraffic(formatSentSize);
+ //拉流服务器
+ info.setRemoteAddr(rtmpSession.getRemoteAddr());
+ PullStreamInfoList.add(info);
+ break;
+ case "webRTCSession":
+ info.setSessionType("webrtc");
+ //webrtc播放地址
+ url = "http://" + mediamtxHost + ":8889/" + name;
+ info.setRtspUrl(url);
+ WebrtcSession webrtcSession = getWebrtcSessionById(reader.getId());
+ //会话ID
+ info.setId(webrtcSession.getId());
+ //开始拉流时间
+ info.setBeginTime(webrtcSession.getCreated());
+ //上行流量
+ bytesReceived = webrtcSession.getBytesReceived();
+ formatReceivedSize = ArdTool.formatFileSize(bytesReceived);
+ info.setUpTraffic(formatReceivedSize);
+ //下行流量
+ bytesSent = webrtcSession.getBytesSent();
+ formatSentSize = ArdTool.formatFileSize(bytesSent);
+ info.setDownTraffic(formatSentSize);
+ //拉流服务器
+ info.setRemoteAddr(webrtcSession.getRemoteAddr());
+ PullStreamInfoList.add(info);
+ break;
+ case "rtspSession":
+ info.setSessionType("rtsp");
+ //RTSP播放地址
+ String rtspUrl = "rtsp://" + mediamtxHost + ":8554/" + name;
+ info.setRtspUrl(rtspUrl);
+ RtspSession rtspSession = getRtspSessionById(reader.getId());
+ //会话ID
+ info.setId(rtspSession.getId());
+ //开始拉流时间
+ info.setBeginTime(rtspSession.getCreated());
+ //上行流量
+ bytesReceived = rtspSession.getBytesReceived();
+ formatReceivedSize = ArdTool.formatFileSize(bytesReceived);
+ info.setUpTraffic(formatReceivedSize);
+ //下行流量
+ bytesSent = rtspSession.getBytesSent();
+ formatSentSize = ArdTool.formatFileSize(bytesSent);
+ info.setDownTraffic(formatSentSize);
+ //拉流服务器
+ info.setRemoteAddr(rtspSession.getRemoteAddr());
+ PullStreamInfoList.add(info);
+ break;
+ }
}
}
- Comparator<StreamInfo> comparator = Comparator.comparing(streamInfo ->streamInfo.getBeginTime() ); // 使用Collections.sort方法进行排序 Collections.sort(personList, comparator);
+ Comparator<StreamInfo> comparator = Comparator.comparing(streamInfo -> streamInfo.getBeginTime()); // 使用Collections.sort方法进行排序 Collections.sort(personList, comparator);
Collections.sort(PullStreamInfoList, comparator.reversed());
return PullStreamInfoList;
}
+ /**
+ * 踢出rtsp会话
+ * 刘苏义
+ * 2023/8/29 9:37:05
+ */
@Override
public Boolean kickRtspSession(String sessionId) {
try {
- mediaClient.kick(sessionId);
+ mediaClient.kickRtspSessions(sessionId);
+ return true;
+ } catch (Exception ex) {
+ return false;
+ }
+ }
+
+ /**
+ * 踢出rtmp会话
+ * 刘苏义
+ * 2023/8/29 9:37:05
+ */
+ @Override
+ public Boolean kickRtmpSession(String sessionId) {
+ try {
+ mediaClient.kickRtmpSessions(sessionId);
+ return true;
+ } catch (Exception ex) {
+ return false;
+ }
+ }
+
+ /**
+ * 踢出webrtc会话
+ * 刘苏义
+ * 2023/8/29 9:37:05
+ */
+ @Override
+ public Boolean kickWebrtcSession(String sessionId) {
+ try {
+ mediaClient.kickWebrtcSessions(sessionId);
return true;
} catch (Exception ex) {
return false;
--
Gitblit v1.9.3