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服务器的地址