From 0dcba4fd1cb536ab426622e31213d8a0194449ff Mon Sep 17 00:00:00 2001 From: puzhibing <393733352@qq.com> Date: 星期五, 25 四月 2025 14:12:30 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/JavaCVStreamUtil.java | 132 +++++++++++++++++++++++++------------------ 1 files changed, 77 insertions(+), 55 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/JavaCVStreamUtil.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/JavaCVStreamUtil.java index 1ad357d..0b80278 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/JavaCVStreamUtil.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/JavaCVStreamUtil.java @@ -1,8 +1,11 @@ package com.ruoyi.system.util; +import cn.hutool.core.io.FileUtil; +import com.ruoyi.common.core.utils.StringUtils; import org.bytedeco.ffmpeg.global.avcodec; import org.bytedeco.ffmpeg.global.avutil; import org.bytedeco.javacv.*; +import org.springframework.stereotype.Component; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -10,34 +13,49 @@ /** * 音视频推流拉流工具类 * 参考资料:https://juejin.cn/post/7311230172237561866 + * * @author zhibing.pu * @Date 2025/4/8 16:03 */ +@Component public class JavaCVStreamUtil { private static Map<Integer, FFmpegFrameGrabber> grabberMap = new ConcurrentHashMap<>(); + + private static Map<Integer, OpenCVFrameGrabber> grabberMap1 = new ConcurrentHashMap<>(); private static Map<Integer, FFmpegFrameRecorder> frameRecorderMap = new ConcurrentHashMap<>(); private static Map<Integer, Boolean> statusMap = new ConcurrentHashMap<>(); + public static void main(String[] args) { + String url = "rtmp://127.0.0.1:1935/flv/test"; + JavaCVStreamUtil.push_flv("C:\\Users\\39373\\Desktop\\图片\\trailer.mp4", url, 0); + } + + + /** * 视频拉流和推流 */ - public static void push_flv(String inputUrl, String outputUrl, Integer deviceNumber){ + public static void push_flv(String inputUrl, String outputUrl, Integer deviceNumber) { // OpenCVFrameGrabber grabber = null; FFmpegFrameGrabber grabber = null; FFmpegFrameRecorder recorder = null; try { //关闭上一个没有正确关闭的流 FFmpegFrameGrabber fFmpegFrameGrabber = grabberMap.get(deviceNumber); - if(null != fFmpegFrameGrabber){ + if (null != fFmpegFrameGrabber) { fFmpegFrameGrabber.close(); } + OpenCVFrameGrabber openCVFrameGrabber = grabberMap1.get(deviceNumber); + if (null != openCVFrameGrabber) { + openCVFrameGrabber.close(); + } FFmpegFrameRecorder fFmpegFrameRecorder = frameRecorderMap.get(deviceNumber); - if(null != fFmpegFrameRecorder){ + if (null != fFmpegFrameRecorder) { fFmpegFrameRecorder.close(); } @@ -52,50 +70,52 @@ grabber.setOption("timeout", "120000"); grabber.start(); grabberMap.put(deviceNumber, grabber); - + // grabber = new OpenCVFrameGrabber(0); // grabber.start(); +// grabberMap1.put(deviceNumber, grabber); //录制视频,推送到流媒体服务器(nginx) recorder = new FFmpegFrameRecorder(outputUrl, grabber.getImageWidth(), grabber.getImageHeight()); recorder.setFormat("flv"); // 设置视频比特率 recorder.setVideoBitrate(grabber.getVideoBitrate()); -// // 设置帧率 -// recorder.setFrameRate(grabber.getVideoFrameRate()); -// // 设置关键帧间隔 -// recorder.setGopSize((int) grabber.getVideoFrameRate()); + // 设置帧率 + recorder.setFrameRate(grabber.getVideoFrameRate()); + // 设置关键帧间隔 + recorder.setGopSize((int) grabber.getVideoFrameRate()); // CRF 是一种用于控制视频/音频质量的参数,它允许在保持目标质量的同时动态地调整比特率。较低的CRF值表示更高的质量,但也可能导致较大的文件大小 recorder.setAudioOption("crf", "23"); //设置音频编码为AAC -// if (grabber.getAudioChannels() > 0) { + if (grabber.getAudioChannels() > 0) { recorder.setAudioChannels(grabber.getAudioChannels()); recorder.setAudioBitrate(grabber.getAudioBitrate()); recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); -// } + } recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //将解码后的帧记录到输出文件中 //recorder.start通常用于处理已经解码成图像的视频数据 recorder.start(); + frameRecorderMap.put(deviceNumber, recorder); + //设置状态为开始 + statusMap.put(deviceNumber, true); + Frame frame; while ((frame = grabber.grab()) != null) { recorder.record(frame); + //判断状态为停止,则结束此线程任务 + if (!statusMap.get(deviceNumber)) { + break; + } + Thread.sleep(500); } } catch (FrameGrabber.Exception | FrameRecorder.Exception e) { e.printStackTrace(); - }finally { - try { - statusMap.put(deviceNumber, false); - if(null != grabber){ - grabber.stop(); - } - if(null != recorder){ - recorder.stop(); - } - }catch (Exception e){ - e.printStackTrace(); - } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + close(deviceNumber, null); } } @@ -103,7 +123,7 @@ /** * 视频拉流和推流 */ - public static void push_hls(String inputUrl, String outputUrl, Integer deviceNumber){ + public static void push_hls(String inputUrl, String outputUrl, Integer deviceNumber, String folderPath) { OpenCVFrameGrabber grabber = null; // FFmpegFrameGrabber grabber = null; FFmpegFrameRecorder recorder = null; @@ -111,11 +131,16 @@ try { //关闭上一个没有正确关闭的流 FFmpegFrameGrabber fFmpegFrameGrabber = grabberMap.get(deviceNumber); - if(null != fFmpegFrameGrabber){ + if (null != fFmpegFrameGrabber) { fFmpegFrameGrabber.close(); } + OpenCVFrameGrabber openCVFrameGrabber = grabberMap1.get(deviceNumber); + if (null != openCVFrameGrabber) { + openCVFrameGrabber.close(); + ; + } FFmpegFrameRecorder fFmpegFrameRecorder = frameRecorderMap.get(deviceNumber); - if(null != fFmpegFrameRecorder){ + if (null != fFmpegFrameRecorder) { fFmpegFrameRecorder.close(); } @@ -133,6 +158,7 @@ grabber = new OpenCVFrameGrabber(0); grabber.start(); + grabberMap1.put(deviceNumber, grabber); //录制视频,推送到流媒体服务器(nginx) recorder = new FFmpegFrameRecorder(outputUrl, grabber.getImageWidth(), grabber.getImageHeight()); @@ -182,61 +208,57 @@ while ((frame = grabber.grab()) != null) { recorder.record(frame); //判断状态为停止,则结束此线程任务 - if(!statusMap.get(deviceNumber)){ + if (!statusMap.get(deviceNumber)) { break; } } } catch (FrameGrabber.Exception | FrameRecorder.Exception e) { e.printStackTrace(); - }finally { - try { - statusMap.put(deviceNumber, false); - if(null != grabber){ - grabber.stop(); - } - if(null != recorder){ - recorder.stop(); - } - }catch (Exception e){ - e.printStackTrace(); - } + } finally { + close(deviceNumber, folderPath); } } /** * 关闭推流和拉流进程 + * * @param deviceNumber */ - public static void close(Integer deviceNumber){ + public static void close(Integer deviceNumber, String folderPath) { //设置状态为停止 + Boolean status = statusMap.get(deviceNumber); + if (null == status || !status) { + return; + } statusMap.put(deviceNumber, false); FFmpegFrameGrabber fFmpegFrameGrabber = null; + OpenCVFrameGrabber openCVFrameGrabber = null; FFmpegFrameRecorder fFmpegFrameRecorder = null; try { fFmpegFrameGrabber = grabberMap.get(deviceNumber); - if(null != fFmpegFrameGrabber){ + if (null != fFmpegFrameGrabber) { + fFmpegFrameGrabber.flush(); fFmpegFrameGrabber.close(); } + openCVFrameGrabber = grabberMap1.get(deviceNumber); + if (null != openCVFrameGrabber) { + openCVFrameGrabber.flush(); + openCVFrameGrabber.close(); + } fFmpegFrameRecorder = frameRecorderMap.get(deviceNumber); - if(null != fFmpegFrameRecorder){ + if (null != fFmpegFrameRecorder) { + fFmpegFrameRecorder.flush(); fFmpegFrameRecorder.close(); } - }catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); - }finally { - try { - fFmpegFrameGrabber = grabberMap.get(deviceNumber); - if(null != fFmpegFrameGrabber){ - fFmpegFrameGrabber.close(); - } - fFmpegFrameRecorder = frameRecorderMap.get(deviceNumber); - if(null != fFmpegFrameRecorder){ - fFmpegFrameRecorder.close(); - } - }catch (Exception e){ - e.printStackTrace(); - } + } + //开始清除视频文件 + if (StringUtils.isNotEmpty(folderPath)) { + FileUtil.del(folderPath); } } + + } -- Gitblit v1.7.1