springboot實(shí)現(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(); /** * 啟動(dòng) 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("啟動(dòng) RTSP 失敗"+e.getMessage()); throw new RuntimeException("啟動(dòng) 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("視頻解碼錯(cuò)誤"); return null; } } }
4、測(cè)試代碼
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(); // 生成測(cè)試幀 rtspStreamer.pushFrame(image); try { Thread.sleep(33); // 約30幀/秒 } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.setDaemon(true); thread.start(); } // 生成測(cè)試幀(漸變顏色) 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工具測(cè)試
測(cè)試地址:rtsp://localhost:8554/live,其中l(wèi)ocalhost:8554為rtsp服務(wù)器的地址
到此這篇關(guān)于springboot實(shí)現(xiàn)rtsp視頻推流的示例代碼的文章就介紹到這了,更多相關(guān)springboot rtsp視頻推流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringMVC框架使用 Apache POI實(shí)現(xiàn)導(dǎo)出Excel
Excel 作為最常用的數(shù)據(jù)處理工具之一,經(jīng)常被用來存儲(chǔ)和展示數(shù)據(jù),本文將介紹如何在 SpringMVC 框架中使用 Apache POI 庫來實(shí)現(xiàn) Excel 文件的導(dǎo)出功能,有需要的可以參考一下2025-04-04Mybatis-plus與Mybatis依賴沖突問題解決方法
,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧這篇文章主要介紹了Mybatis-plus與Mybatis依賴沖突問題解決方法2021-04-04堆排序?qū)嵗?Java數(shù)組實(shí)現(xiàn))
下面小編就為大家分享一篇使用Java數(shù)組實(shí)現(xiàn)堆排序的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12springboot+vue前后端分離項(xiàng)目中使用jwt實(shí)現(xiàn)登錄認(rèn)證
本文介紹了如何在SpringBoot+Vue前后端分離的項(xiàng)目中使用JWT實(shí)現(xiàn)登錄認(rèn)證,內(nèi)容包括后端的響應(yīng)工具類、JWT工具類、登錄用戶實(shí)體類、登錄接口、測(cè)試接口、過濾器、啟動(dòng)類以及前端的登錄頁面實(shí)現(xiàn),感興趣的可以了解一下2024-10-10Spring中的ContextLoaderListener詳細(xì)解析
這篇文章主要介紹了Spring中的ContextLoaderListener詳細(xì)解析,在web容器即Tomact容器啟動(dòng)web應(yīng)用即servlet應(yīng)用時(shí),會(huì)觸發(fā)ServletContextEvent時(shí)間,這個(gè)事件會(huì)被ServletContextListener監(jiān)聽,需要的朋友可以參考下2023-12-12一文帶你搞懂Java中Synchronized和Lock的原理與使用
這篇文章主要為大家詳細(xì)介紹了Java中Synchronized和Lock的原理與使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下2023-04-04通過Java 程序獲取Word中指定圖片的坐標(biāo)位置
本文介紹通過Java程序獲取Word文檔中指定圖片的坐標(biāo)位置,程序運(yùn)行環(huán)境是jdk1.8開發(fā)環(huán)境idea,通過java程序代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-05-05Java使用dom4j實(shí)現(xiàn)對(duì)xml簡(jiǎn)單的增刪改查操作示例
這篇文章主要介紹了Java使用dom4j實(shí)現(xiàn)對(duì)xml簡(jiǎn)單的增刪改查操作,結(jié)合實(shí)例形式詳細(xì)分析了Java使用dom4j實(shí)現(xiàn)對(duì)xml簡(jiǎn)單的增刪改查基本操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-05-05