springboot實現(xiàn)rtsp視頻推流的示例代碼
1、搭建rtsp服務(wù)(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>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>7.1-1.5.11</version>
</dependency>
3、新建RtspStreamer服務(wù)類
package com.example.superior_conjuncte_iot_rtspvideo.system_config.config;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.Base64;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Component
@Slf4j
public class RtspStreamer {
static {
FFmpegLogCallback.set();
// 強(qiáng)制加載 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 final Java2DFrameConverter converter = new Java2DFrameConverter();
/**
* 啟動 RTSP 流服務(wù)
* @param rtspUrl 例如: "rtsp://localhost:8554/live"
* @param width 視頻寬度
* @param height 視頻高度
*/
public void startStream(String rtspUrl, int width, int height) {
try {
recorder = new FFmpegFrameRecorder(rtspUrl, width, height);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setFormat("rtsp");
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFrameRate(30);
recorder.setVideoBitrate(2_000_000); // 碼率設(shè)為 2Mbps
recorder.setVideoOption("preset", "medium");
recorder.setVideoOption("tune", "zerolatency");
recorder.setVideoOption("g", "30");
recorder.start();
} catch (Exception e) {
log.error("啟動 RTSP 失敗"+e.getMessage());
throw new RuntimeException("啟動 RTSP 失敗", e);
}
}
/**
* 推送視頻幀
* @param image 視頻幀圖像
*/
public void pushFrame(BufferedImage image) {
executor.submit(() -> {
try {
//轉(zhuǎn)換格式
BufferedImage bgrImage = convertToBGR(image);
Frame frame = converter.getFrame(bgrImage);
recorder.record(frame);
} catch (Exception e) {
log.error("推送視頻幀失敗"+e.getMessage());
e.printStackTrace();
}
});
}
//轉(zhuǎn)換格式,很關(guān)鍵
private BufferedImage convertToBGR(BufferedImage image) {
BufferedImage bgrImage = new BufferedImage(
image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR
);
bgrImage.getGraphics().drawImage(image, 0, 0, null);
return bgrImage;
}
@PreDestroy
public void stopStream() {
if (recorder != null) {
try {
recorder.stop();
recorder.release();
} catch (Exception e) {
log.error("停止 RTSP 失敗"+e.getMessage());
}
}
executor.shutdown();
}
//字符串視頻流解碼
public BufferedImage getBufferedImage(String base64Image){
try {
byte[] imageBytes = Base64.getDecoder().decode(base64Image);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
return image;
}catch (Exception ex){
log.error("視頻解碼錯誤");
return null;
}
}
}
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
@Lazy
private RtspStreamer rtspStreamer;
@Override
public 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,其中l(wèi)ocalhost:8554為rtsp服務(wù)器的地址
到此這篇關(guān)于springboot實現(xiàn)rtsp視頻推流的示例代碼的文章就介紹到這了,更多相關(guān)springboot rtsp視頻推流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring配置多個數(shù)據(jù)源并實現(xiàn)動態(tài)切換示例
本篇文章主要介紹了Spring配置多個數(shù)據(jù)源并實現(xiàn)動態(tài)切換示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
springboot中如何實現(xiàn)kafa指定offset消費(fèi)
這篇文章主要介紹了springboot中如何實現(xiàn)kafa指定offset消費(fèi),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12
Maven中引入 springboot 相關(guān)依賴的方式(最新推薦)
這篇文章主要介紹了Maven中引入 springboot 相關(guān)依賴的方式(最新推薦),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2025-04-04
SpringBoot實現(xiàn)動態(tài)增刪啟停定時任務(wù)的方式
在spring?boot中,可以通過@EnableScheduling注解和@Scheduled注解實現(xiàn)定時任務(wù),也可以通過SchedulingConfigurer接口來實現(xiàn)定時任務(wù),但是這兩種方式不能動態(tài)添加、刪除、啟動、停止任務(wù),本文給大家介紹SpringBoot實現(xiàn)動態(tài)增刪啟停定時任務(wù)的方式,感興趣的朋友一起看看吧2024-03-03
Spring Cloud之服務(wù)監(jiān)控turbine的示例
這篇文章主要介紹了Spring Cloud之服務(wù)監(jiān)控turbine的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
SpringBoot Security安裝配置及Thymeleaf整合
這篇文章主要介紹了SpringBoot Security安裝配置及Thymeleaf整合,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-12-12
java實現(xiàn)英文詞頻統(tǒng)計(附帶源碼)
英文詞頻統(tǒng)計作為文本數(shù)據(jù)分析中的基礎(chǔ)工作,廣泛應(yīng)用于自然語言處理、輿情分析、信息檢索、文本挖掘以及數(shù)據(jù)可視化等領(lǐng)域,下面我們就來看看如何使用java實現(xiàn)英文詞頻統(tǒng)計吧2025-06-06

