当前位置: 首页 > backend >正文

spring boot 实现resp视频推流

1、搭建resp服务(docker方式)

docker pull aler9/rtsp-simple-server
docker run -d --restart=always \--name rtsp-server \-p 8554:8554 \aler9/rtsp-simple-server

2、maven依赖

<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.11</version><exclusions><exclusion><groupId>org.bytedeco</groupId><artifactId>opencv</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg-platform</artifactId><version>7.1-1.5.11</version></dependency>

3、新建RtspStreamer服务类

package com.example.superior_conjuncte_iot_web.system_config.videoConfig;import jakarta.annotation.PreDestroy;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.stereotype.Component;import java.awt.image.BufferedImage;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@Component
public class RtspStreamer {static {// 强制加载 FFmpeg 核心库Loader.load(org.bytedeco.ffmpeg.global.avutil.class);Loader.load(org.bytedeco.ffmpeg.global.avcodec.class);Loader.load(org.bytedeco.ffmpeg.global.avformat.class);}private FFmpegFrameRecorder recorder;private ExecutorService executor = Executors.newSingleThreadExecutor();private boolean isStreaming = false;private final Java2DFrameConverter converter = new Java2DFrameConverter();/*** 启动 RTSP 流服务* @param rtspUrl 例如: "rtsp://localhost:8554/live"* @param width 视频宽度* @param height 视频高度*/public void startStream(String rtspUrl, int width, int height) {if (isStreaming) return;recorder = new FFmpegFrameRecorder(rtspUrl, width, height);recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 编码格式recorder.setFormat("rtsp"); // 输出格式
//        recorder.setFrameRate(30); // 帧率recorder.setFrameRate(25);try {recorder.start();isStreaming = true;} catch (Exception e) {e.printStackTrace();throw new RuntimeException("启动 RTSP 失败", e);}}/*** 推送视频帧* @param image 视频帧图像*/public void pushFrame(BufferedImage image) {if (!isStreaming) return;executor.submit(() -> {try {Frame frame = converter.getFrame(image);recorder.record(frame);} catch (Exception e) {e.printStackTrace();}});}@PreDestroypublic void stopStream() {if (recorder != null) {try {isStreaming = false;recorder.stop();recorder.release();} catch (Exception e) {e.printStackTrace();}}executor.shutdown();}
}

4、测试代码

package com.example.superior_conjuncte_iot_web.tj.project_video.service.impl;import com.example.superior_conjuncte_iot_web.system_config.videoConfig.RtspStreamer;
import com.example.superior_conjuncte_iot_web.tj.project_video.service.IVideoRtspService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;import java.awt.*;
import java.awt.image.BufferedImage;@Service
@Slf4j
public class VideoRtspServiceImpl implements IVideoRtspService, ApplicationRunner {@Resource@Lazyprivate RtspStreamer rtspStreamer;@Overridepublic void run(ApplicationArguments args)  {rtspStreamer.startStream("rtsp://localhost:8554/live", 640, 480);// 模拟生成视频帧(例如从摄像头或文件读取)Thread thread=new Thread(() -> {while (true) {BufferedImage image = generateTestFrame(); // 生成测试帧rtspStreamer.pushFrame(image);try {Thread.sleep(33); // 约30帧/秒} catch (InterruptedException e) {e.printStackTrace();}}});thread.setDaemon(true);thread.start();}// 生成测试帧(渐变颜色)private BufferedImage generateTestFrame() {BufferedImage img = new BufferedImage(640, 480, BufferedImage.TYPE_3BYTE_BGR);Graphics2D g2d = img.createGraphics();g2d.setColor(new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255)));g2d.fillRect(0, 0, 640, 480);g2d.dispose();return img;}
}

5、用VLC工具测试
测试地址:rtsp://localhost:8554/live,其中localhost:8554为rtsp服务器的地址

http://www.xdnf.cn/news/8136.html

相关文章:

  • 觉醒三境:在敦煌的风沙中寻找生命的纹路
  • 基于deepseek 以及豆包工具+nodejs 搭建A I自动化客服系统
  • 角度回归——八参数检测四边形Gliding Vertex
  • 树 Part 9
  • 【IC_Design】跨时钟域的寄存器更新后锁存
  • MyBatis-Plus的自带分页方法生成的SQL失败:The error occurred while setting parameters
  • (37)服务器增加ipv6配置方法
  • MySQL 查询用户权限的方法
  • redis-7.4.2 通过 systemd管理,rpmbuild spec文件参考
  • C++ JSON解析技术详解
  • QGIS DB Manager 导入 Shp 到 PostGIS 空间数据库
  • Mysql 刷题Day09
  • 常用快捷键大全
  • 在Pycharm中如何安装Flask
  • C++ 02.好用的命令行解析库cmdline和CLI11
  • 【Java高阶面经:数据库篇】19、分库分表查询困境:无分库分表键时的高效应对
  • 【RAG】ragflow源码亮点:文档embedding向量化加权融合
  • 【未来展望】云、AI与元宇宙的融合架构
  • dlib库的人脸检测案例实现
  • js中encodeURIComponent函数使用场景
  • MLpack 开源库介绍与使用指南
  • 操作系统学习笔记第1章 操作系统概述(灰灰题库
  • 数据库表索引维护策略
  • 大模型数据标注:驱动人工智能进化的基石
  • 前端学习笔记element-Plus
  • P22:LSTM-火灾温度预测
  • Tomcat优化
  • 《大数据之路:阿里巴巴大数据实践》笔记
  • 让电脑不再卡,从清理系统做起
  • DRIVEVLM: 大视觉语言模型和自动驾驶的融合