JavaCV之rtmp推流(FLV和M3U8)

JavaCV與FFmpeg

FFmpeg是一款開源的多媒體處理工具集,它包含了一系列用于處理音頻、視頻、字幕等多媒體數據的庫和工具。
JavaCV集成了FFmpeg庫,使得Java開發者可以使用FFmpeg的功能,比如視頻解碼、編碼、格式轉換等。
除了FFmpeg,Javacv封裝了以下庫:

  1. OpenCV: JavaCV封裝了OpenCV(Open Source Computer Vision Library),這是一個廣泛用于計算機視覺應用的開源庫。
  2. FlyCapture: 用于 Point Grey 系列相機的庫。
  3. ARToolKit: 一個增強現實(Augmented Reality)庫,用于跟蹤相機圖像中的標記。
  4. JavaCpp: 這是JavaCV的底層庫,用于在Java中調用C++代碼,是整個JavaCV項目的基礎。
  5. Libdc1394: 用于相機和攝像機的庫。
  6. JavaCV Presets: 提供了一系列預設,將原生的C/C++函數封裝為Java接口,簡化了在Java中調用這些功能的過程。

準備

1、引入maven包

<dependency> 
<groupId>org.bytedeco</groupId> 
<artifactId>javacv-platform</artifactId> 
<version>1.5.6</version> 
</dependency>

2、類與方法說明

FFmpegFrameGrabber FFmpegFrameRecorder 是 JavaCV 中用于處理視頻的兩個關鍵類,分別用于抓取視頻幀和錄制視頻幀,底層使用了 FFmpeg 庫。
我們可以使用 FFmpegFrameGrabber 打開視頻文件,獲取視頻信息,然后不斷地從視頻中獲取幀。
FFmpegFrameRecorder則從輸入視頻中抓取幀,進行解碼后,將每一幀寫入輸出視頻文件。
FFmpegFrameGrabber FFmpegFrameGrabber 配合使用,可以實現從視頻源中抓取幀并將幀寫入視頻文件的完整流程。

2、推流流程

image.png

3、Nginx搭建rtmp服務器

(1)下載帶有rtmp模塊的nginx(Gryphon) http://nginx-win.ecsds.eu/download/
(2)在nginx中的conf文件夾配置rtmp。nginx-win.conf增加如下代碼:

rtmp {server {listen 1935;application flv-live{live on;record off;allow play all;}}
}

添加后,cmd跳轉到nginx目錄,執行命令 nginx.exe -c conf/nginx-win.conf 即可

FLV直播和HLS直播

FLV(Flash Video)直播:

  1. 傳輸協議: FLV 使用 RTMP(Real-Time Messaging Protocol)作為傳輸協議。RTMP 是一種實時通信協議,通常用于傳輸音頻、視頻和數據。
  2. 實時性: FLV 提供較低的延遲,通常在數秒到十幾秒之間,適用于需要更快實時性的應用場景。
  3. 支持性: FLV 需要 Flash 播放器來播放,而在現代瀏覽器和設備中,對 Flash 的支持逐漸減少。這導致了使用 FLV 的限制。

HLS(HTTP Live Streaming)直播:

  1. 傳輸協議: HLS 使用 HTTP 協議,這使得它更容易穿越防火墻和代理服務器。它通常基于標準的 HTTP 80/443 端口,因此更容易被防火墻允許。
  2. 實時性: 相對于 FLV,HLS 通常有更高的延遲,通常在 10 到 30 秒之間。這使得它不太適合需要極低延遲的實時應用。
  3. 支持性: HLS 更廣泛地支持各種設備和瀏覽器,因為它基于標準的 HTTP 和 HTML5 規范,無需專門的插件或播放器。
  4. 自適應比特率: HLS 提供了自適應比特率功能,可以根據用戶的網絡情況自動調整視頻質量,提供更好的觀看體驗。

選擇 FLV 還是 HLS 取決于你的具體需求。如果需要較低的延遲,并且可以接受使用 Flash 播放器的限制,那么 FLV 可能是一個合適的選擇。如果需要更廣泛的設備和瀏覽器支持,并且可以接受稍高的延遲,那么 HLS 可能更適合。在實際應用中,有時候也會結合兩者,使用不同的協議來滿足不同的需求。

實現Flv推流

拿一個h264格式的mov視頻來演示,先將mov轉為flv并且進行推流。

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;public class RtmpFlv {private static final String outputUrl = "rtmp://localhost:1935/flv-live/test";private static final String inputUrl = "D:\視頻.mov";public static void main(String[] args) throws FrameGrabber.Exception, FrameRecorder.Exception, InterruptedException {//設置FFmpeg日志級別avutil.av_log_set_level(avutil.AV_LOG_INFO);FFmpegLogCallback.set();//以文件路徑的方式傳入視頻,當然也支持以流的方式傳入FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);//開始捕獲視頻流grabber.start();//用于將捕獲到的視頻流轉換為輸出URL的mp4格式。FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputUrl, grabber.getImageWidth(), grabber.getImageHeight());recorder.setFormat("flv");recorder.setVideoBitrate(grabber.getVideoBitrate()); // 設置視頻比特率recorder.setFrameRate(grabber.getVideoFrameRate()); // 設置幀率recorder.setGopSize((int) grabber.getVideoFrameRate()); // 設置關鍵幀間隔// CRF 是一種用于控制視頻/音頻質量的參數,它允許在保持目標質量的同時動態地調整比特率。較低的CRF值表示更高的質量,但也可能導致較大的文件大小recorder.setAudioOption("crf", "23");Frame frame;//設置音頻編碼為AACif (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();while ((frame = grabber.grab()) != null) {recorder.record(frame);}recorder.close();grabber.close();}
}

運行后,打開vlc軟件,點擊媒體-》打開串流網絡 ,輸入rtmp://localhost:1935/flv-live/test 進行播放

image.png

實現M3U8推流

代碼和上面的大同小異,將一個H264的mp4視頻轉為hls,利用http播放m3u8文件。

import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;public class RtmpM3U8 {private static final String outputUrl = "D:\nginx_rtmp\html\test.m3u8";private static final String inputUrl = "D:\視頻.mp4";public static void main(String[] args) throws FrameGrabber.Exception, FrameRecorder.Exception {//設置FFmpeg日志級別avutil.av_log_set_level(avutil.AV_LOG_ERROR);FFmpegLogCallback.set();//以文件路徑的方式傳入視頻,當然也支持以流的方式傳入FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);//開始捕獲視頻流grabber.start();AVFormatContext avFormatContext = grabber.getFormatContext();//獲取視頻時長//long duration = avFormatContext.duration();//檢查文件是否媒體流(視頻流、音頻流)if (avFormatContext.nb_streams() == 0) {//表明沒有媒體流return;}//用于將捕獲到的視頻流轉換為輸出URL的mp4格式。FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputUrl, grabber.getImageWidth(), grabber.getImageHeight(),grabber.getAudioChannels());recorder.setFormat("hls");recorder.setVideoBitrate(grabber.getVideoBitrate()); // 設置視頻比特率recorder.setFrameRate(grabber.getVideoFrameRate()); // 設置幀率recorder.setGopSize((int) grabber.getVideoFrameRate()); // 設置關鍵幀間隔// 設置HLS切片參數//將每個切片時長設置為10秒recorder.setOption("hls_time", "15");//設置切片數大小recorder.setOption("hls_list_size", "20");//設置切片循環次數為50recorder.setOption("hls_wrap", "20");//每次切片完成后,都會刪除之前的切片文件。如果不設置或設置為其他值,則不會刪除之前的切片文件。recorder.setOption("hls_flags", "delete_segments");//在使用 H.264 編碼時,通常要求輸入的像素格式為 YUV420P。如果輸入的像素格式不匹配,就可能導致 avcodec_send_frame() 錯誤recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);//CRF 是一種用于控制視頻/音頻質量的參數,它允許在保持目標質量的同時動態地調整比特率。較低的CRF值表示更高的質量,但也可能導致較大的文件大小recorder.setAudioOption("crf", "23");Frame frame;//設置音頻編碼為AACif (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);//設置音頻編碼為AACif (grabber.getAudioChannels() > 0) {recorder.setAudioChannels(grabber.getAudioChannels());recorder.setAudioBitrate(grabber.getAudioBitrate());recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);}//將解碼后的幀記錄到輸出文件中//recorder.start通常用于處理已經解碼成圖像的視頻數據recorder.start();while ((frame = grabber.grab()) != null) {recorder.record(frame);}recorder.close();grabber.close();}}

開始推流后,會在D:\nginx_rtmp\html\生成m3u8和ts文件,我們只需要播放m3u8文件即可。

image.png

打開vlc軟件,點擊媒體-》打開串流網絡 ,輸入http://localhost:8080/test.m3u8 進行播放

優化TODO

后繼利用高性能網絡框架netty進行直播多路復用,避免視頻重復解碼推流,詳情關注最新文章!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/214964.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/214964.shtml
英文地址,請注明出處:http://en.pswp.cn/news/214964.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode力扣每日一題(Java):35、搜索插入位置

一、題目 二、解題思路 1、我的思路&#xff08;又稱&#xff1a;論API的重要性&#xff09; 讀完題目之后&#xff0c;我心想這題目怎么看著這么眼熟&#xff1f;好像我之前學過的一個API呀&#xff01; 于是我回去翻了翻我之前寫的博客&#xff1a;小白備戰藍橋杯&#xf…

通用的AGI 安全風險

傳統安全風險 平臺基礎設施安全風險 模型與數據層安全風險 應用層安全風險 平臺基礎設施安全風險 &#xff08;1&#xff09;物理攻擊&#xff1a;機房管控不到位 &#xff08;2&#xff09;網絡攻擊 &#xff08;3&#xff09;計算環境&#xff1a;自身安全漏洞&#xf…

編輯器Sublime text 常用快捷命令 列模式 替換空行

平替notepad 下載可取官網 www.sublimetext.com 據說可以無限試用&#xff0c;沒有功能限制 1、快速刪除空行 ctrl h選擇正則表達式 .*Find輸入&#xff1a; ^(\t)*$\nReplace輸入&#xff1a;點擊Replace All 2、快速選擇指定字符 用鼠標選中alt f3修改 3、列編輯模式 ct…

如何理解HTML下的網頁結構?

HTML&#xff08;Hypertext Markup Language&#xff09;是一種標記語言&#xff0c;用于描述網頁的結構和內容。以下是對網頁結構的理解以及網絡爬蟲在處理不同類型網頁時可能遇到的情況&#xff1a; 1. HTML基本結構 HTML文檔的基本結構通常包括以下幾個部分&#xff1a; …

宇視科技視頻監控 main-cgi 文件信息泄露漏洞復現

0x01 產品簡介 宇視(Uniview)高清網絡攝像機是一種高性能的網絡攝像機,它可以通過網絡進行視頻傳輸和監控。該攝像機采用先進的視頻技術,具有高清晰度、低照度、寬動態等特點,能夠提供高質量的視頻圖像。 0x02 漏洞概述 宇視(Uniview)高清網絡攝像機存在信息泄露漏洞…

ppt編輯密碼如何設置?

大家在PPT中設置了限制編輯&#xff0c;發現后面任然可以編輯文件。那么如何將PPT文件設置成禁止修改模式呢&#xff1f;今天分享幾個方法給大家。 方法一 將PPT文件直接保存或者另存為一份文件&#xff0c;在保存時&#xff0c;將文件格式選擇為PowerPoint圖片演示文稿 方法…

.NET 8 編寫 LiteDB vs SQLite 數據庫 CRUD 接口性能測試(測試篇)

WebAppDbTest 項目測試 測試工具 ltt介紹安裝使用方式1、Drill2、Hammer3、Nailgun 測試主機規格配置CRUD 性能測試對比1、ltt 工具測試1.1、AddSingle 單條數據添加1.2、AddBulk 批量數據&#xff08;1000&#xff09;條添加1.3、GetSingle 單條數據查詢1.4、GetAll 多條&…

Spring Boot使用JUnit和Mockito進行Service層單元測試

文章目錄 前言一、單元測試是什么二、為什么要寫單元測試三、簡單示例假設我們有一個簡單的UserService類&#xff0c;其中包含了一些用戶相關的邏輯&#xff1a;首先&#xff0c;我們需要引入JUnit和Mockito的依賴。在Maven項目中&#xff0c;可以在pom.xml文件中添加以下依賴…

多合一iPhone 解鎖工具:iMyFone LockWiper iOS

多合一iPhone 解鎖工具 無需密碼解鎖 iPhone/iPad/iPod touch 上所有類型的屏幕鎖定 在幾分鐘內解鎖 iPhone Apple ID、Touch ID 和 Face ID 立即繞過 MDM 并刪除 iPhone/iPad/iPod touch 上的 MDM 配置文件 支持所有 iOS 版本和設備&#xff0c;包括最新的 iOS 17 和 iPhone 1…

SQL語句---查詢數據

介紹 使用sql語句查詢數據。 命令 select 字段1,字段2 from 表名;例子 查詢指定字段&#xff1a; select id,name from a;使用*查詢所有字段&#xff1a; select * from a;

JAVA實操經驗

零&#xff1a; 按照需要&#xff0c;可以使用需要某個類下&#xff08;主要是java提供的&#xff09;的方法來實現某個功能。&#xff08;主要是用在不同類下的方法會進行重寫功能不同&#xff09; 方法和構造方法不同&#xff1a;方法是方法&#xff0c;構造方法是構造器&a…

Kotlin 中的 `use` 關鍵字:優化資源管理(避免忘記inputStream.close() ?)

在 Android開發中&#xff0c;正確且高效地管理資源是至關重要的。use 關鍵字在 Kotlin 中為資源管理提供了一個簡潔且強大的解決方案。它主要用于自動管理那些需要關閉的資源&#xff0c;比如文件、網絡連接等。 一、use 關鍵字的工作原理 &#x1f916; use 是一個擴展函數…

基于FPGA的視頻接口之高速IO

簡介 相對于其他視頻接口來說,高速IO接口(以Xilinx公司為例,spartan 6系列的GTP、Artix7系列的GTP,KENTEX7系列的GTX和GTH等)具有簡化設計、充分利用FPGA資源、降低設計成本等功能。 高速IO接口傳輸視頻,一般會被拓展為萬兆以太網、40G以太網、10G光纖、40G光纖、3G-SDI、…

c語言插入排序及希爾排序詳解

目錄 前言&#xff1a; 插入排序&#xff1a; 希爾排序&#xff1a; 前言&#xff1a; 排序在我們生活中無處不在&#xff0c;比如學生成就排名&#xff0c;商品價格排名等等&#xff0c;所以排序在數據結構的學習中尤為重要&#xff0c;今天就為大家介紹兩個經典的排序算法&…

adb 查找啟動的包名以及導出安裝包

查看安卓內包名 adb 查看所有安裝的包 adb shell pm list packages查看安裝的第三方app的包名 adb shell pm list packages -3查看啟動的app的包名 adb shell dumpsys activity top | find "ACTIVITY"adb shell dumpsys activity activities | findstr "Run…

深入解析C++中的虛函數和虛繼承:實現多態性與繼承關系的高級特性

這里寫目錄標題 虛函數虛函數實現動態綁定虛繼承抽象類 虛函數 虛函數是在C中用于實現多態性的一種特殊函數。它通過使用關鍵字"virtual"進行聲明&#xff0c;在基類中定義&#xff0c;可在派生類中進行重寫。虛函數允許在運行時根據對象的實際類型來調用相應的函數…

pip 通過git安裝庫

舉例&#xff1a;安裝peft庫 git clone https://github.com/huggingface/peft.git cd peft python -m pip install . 解釋&#xff1a; 使用git clone克隆PEFT庫的代碼。進入克隆的目錄。使用python -m pip install .來安裝PEFT庫。 補充&#xff1a;使用pip安裝到指定編譯器…

BigData之Google Hadoop中間件安裝

前言 Hadoop / Zookeeper / Hbase 因資源有限 這三個都是安裝在同一臺Centos7.9的機器上 但通過配置 所以在邏輯上是distributed模式 1 Java安裝 1.1 下載java11 tar/opt/java/jdk-11.0.5/ 1.2 環境配置修改 文件/etc/profile export JAVA_HOME/opt/java/jdk-11.0.5/ e…

新網站如何被搜索引擎迅速收錄

說到搜索引擎收錄新站的問題&#xff0c;大家應該對這個問題產生了一個共鳴&#xff0c;那就是要想要網站被收&#xff0c;難! 難于上青天。那是不是說這青天我們就上不了了呢&#xff0c;不是的&#xff0c;其實要想百度快速收錄新站&#xff0c;還是有訣竅的&#xff0c;關鍵…

【UE c++】 UE中c++如何使用回調(關卡動畫回調為例)

本文使用關卡動畫回調為例 1.創建關卡動畫 FString assetsPath "你的路徑"; FStringAssetReference sequenceName(assetsPath);ULevelSequence* sequenceAsset Cast<ULevelSequence>(sequenceName.TryLoad());ALevelSequenceActor* currentLevelSequenceAc…