Răsfoiți Sursa

`添加视频转换`

wenhongquan 2 luni în urmă
părinte
comite
684c89c38a

+ 4 - 0
ruoyi-admin/src/main/resources/application.yml

@@ -48,6 +48,10 @@ user:
   difyUrl: ${difiurl:http://172.16.5.83/v1}
   difykey: ${difykey:app-bam2jWvQRd16MnfFaaGWK0Lj}
   ffmpegpath: ${ffmpegpath:/Users/wenhongquan/miniforge3/bin/ffmpeg}
+  hls:
+    # 直播流保存路径
+    path: ${hlspath:./ruoyi/hls/}
+    url: ${hlsurl:http://jtjai.xt.wenhq.top:8083/hls/}
   password:
     # 密码最大错误次数
     maxRetryCount: 5

+ 43 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/TblDeviceController.java

@@ -1,11 +1,18 @@
 package org.dromara.system.controller;
 
+import java.io.File;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.codec.Base64Decoder;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.system.utils.Utils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -102,4 +109,40 @@ public class TblDeviceController extends BaseController {
                           @PathVariable Long[] ids) {
         return toAjax(tblDeviceService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    private Map<String, Utils.PrintStream> rtmptohlsmap = new HashMap<>();
+    @Value(value = "${user.hls.path}")
+    private String path;
+    @Value(value = "${user.hls.url}")
+    private String url;
+    @Value("${user.ffmpegpath}")
+    private String ffmpegFilePath = "/usr/local/bin/ffmpeg";
+
+    @GetMapping("/rtmp/{from}")
+    public R<Object> getHlsCode(@PathVariable("from") String from) {
+        Object data = "";
+        try {
+
+            from = Base64Decoder.decodeStr(from);
+            String p[] = from.split("/");
+            if (rtmptohlsmap.get(from) != null && rtmptohlsmap.get(from).isAlive()) {
+
+            } else {
+                File pc = new File(path + p[p.length - 1] + "");
+                if (!pc.exists()) {
+                    pc.mkdir();
+                    pc.setWritable(true, false);
+                    File pc1 = new File(path + p[p.length - 1] + "/playlist.m3u8");
+                    pc1.createNewFile();
+                    pc1.setWritable(true, false);
+
+                }
+                rtmptohlsmap.put(from, Utils.push(ffmpegFilePath, from, path + p[p.length - 1] + "/playlist.m3u8"));
+            }
+            data = url + p[p.length - 1] + "/playlist.m3u8";
+        } catch (Exception e) {
+
+        }
+        return R.ok(data);
+    }
 }

+ 58 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/utils/Utils.java

@@ -84,6 +84,64 @@ public class Utils {
         }
     }
 
+    /**
+     * @param input  可以是一个InputStream的流、动态图片(apng,gif等等),视频文件(mp4,flv,avi等等),流媒体地址(http-flv,rtmp,rtsp等等)
+     * @param output hls切片存放地址
+     * @throws org.bytedeco.javacv.FrameGrabber.Exception
+     * @throws org.bytedeco.javacv.FrameRecorder.Exception
+     * @Title: push
+     * @Description: hls切片
+     * @return: void
+     **/
+    public static PrintStream push(String ffmpegpath, String input, String output) {
+//                 public boolean exchangeToMp4(String ffmpegPath, String upFilePath, String codcFilePath) throws Exception {
+        // 创建List集合来保存转换视频文件为flv格式的命令
+        List<String> convert = new ArrayList<String>();
+        convert.add(ffmpegpath); // 添加转换工具路径
+        convert.add("-y"); // 该参数指定将覆盖已存在的文件
+        convert.add("-i");
+        convert.add(input);
+        convert.add("-vcodec");
+        convert.add("copy");
+        convert.add("-acodec");
+        convert.add("copy");
+        convert.add("-c:a");
+        convert.add("aac");
+        convert.add("-vbsf");
+        convert.add("h264_mp4toannexb");
+        convert.add("-f");
+        convert.add("hls");
+        convert.add("-hls_list_size");
+        convert.add("5");
+        convert.add("-hls_time");
+        convert.add("10");
+//        convert.add("-hls_wrap");
+//        convert.add("6");
+
+        // convert.add("-vf"); // 添加水印
+        // convert.add("movie=watermark.gif[wm];[in][wm]overlay=20:20[out]");
+        convert.add(output);
+
+        boolean mark = true;
+
+        try {
+            Process videoProcess = new ProcessBuilder(convert).redirectErrorStream(true).start();
+
+            PrintStream p = new PrintStream(videoProcess.getInputStream());
+            p.start();
+            return p;
+//                     videoProcess.waitFor(); // 加上这句,系统会等待转换完成。不加,就会在服务器后台自行转换。
+
+        } catch (Exception e) {
+            mark = false;
+            System.out.println(e);
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+
 //    public static void main(String[] args) {
 //        try {
 //                Utils.cropMp4("/Users/wenhongquan/Downloads/aliyunmedia.mp4", 0, 22,"/Users/wenhongquan/Desktop/tmp/aa.mp4");