JAVA代碼調(diào)用ffmpeg程序進行視頻轉(zhuǎn)碼和推流方式
一、前言
FFmpeg是一款多媒體視頻處理工具,有非常強大的功能包括:視頻采集、視頻推流、視頻格式轉(zhuǎn)換、視頻抓圖、給視頻加水印等功能。
FFmpeg本身是一個命令行程序,需要通過執(zhí)行 ffmpeg命令來實現(xiàn)功能,如下:
ffmpeg -i 123.mp4 -c:a copy -c:v libx264 -f flv rtmp://127.0.0.1:1935/live/test ffmpeg -i 123.mp4 -c copy -f hls -hls_list_size 5 -hls_flags 50 -hls_time 10 D:\hls\test.m3u8
在實際開發(fā)工作中,會需要通過JAVA代碼去調(diào)用ffmpeg程序去完成功能,而不是手動去執(zhí)行ffmpeg命令。本篇文章將介紹如何通過JAVA代碼去調(diào)用執(zhí)行ffmpeg程序。
二、JAVA代碼調(diào)用ffmpeg
本篇文章將介紹兩種方式實現(xiàn) JAVA代碼去調(diào)用ffmpeg程序。
方式一:采用第三方封裝調(diào)用ffmpeg接口的jar包實現(xiàn)
1. 在Maven項目pom.xml文件中引入jar包依賴
<dependency>
<groupId>net.bramp.ffmpeg</groupId>
<artifactId>ffmpeg</artifactId>
<version>0.6.2</version>
</dependency>2. 編寫java代碼
//創(chuàng)建FFmpeg對象
FFmpeg ffmpeg = new FFmpeg("D:\\ffmpeg\\bin\\ffmpeg.exe"); //參數(shù)是:ffmpeg命令工具的安裝路徑
//創(chuàng)建FFmpegBuilder對象,設置推流/轉(zhuǎn)碼參數(shù)
FFmpegBuilder builder = new FFmpegBuilder()
.setInput("D:\\111.mp4") //輸入視頻源地址
.overrideOutputFiles(true) //設置是否覆蓋已存在的輸出文件
.addOutput("D:\\hls\\test.m3u8") //輸出流地址
.setFormat("hls") //輸出流格式 -f hls
.setAudioCodec("copy") //設置音頻轉(zhuǎn)碼 copy表示不轉(zhuǎn)碼
.setVideoCodec("libx264") //設置視頻轉(zhuǎn)碼 copy表示不轉(zhuǎn)碼
.setVideoQuality(1) //設置視頻質(zhì)量,一般為1到5(1代表質(zhì)量最高)
.setVideoFrameRate(25) //設置視頻幀率
.addExtraArgs("-t", "30") //設置推流持續(xù)時間
.addExtraArgs("-hls_list_size", "5") //設置輸出文件個數(shù)(hls輸出流特有的參數(shù))
.addExtraArgs("-hls_flags", "50") //設置輸出文件替換(hls輸出流特有的參數(shù))
.addExtraArgs("-hls_time", "6") //設置輸出文件每個時長多少秒(hls輸出流特有的參數(shù))
.done(); //最后調(diào)用done()完成參數(shù)配置
//創(chuàng)建FFmpegExecutor對象,用于執(zhí)行ffpmeg轉(zhuǎn)流任務
FFmpegExecutor executor=new FFmpegExecutor(ffmpeg);
//執(zhí)行ffpmeg轉(zhuǎn)流任務,并添加了監(jiān)聽器ProgressListener,可以監(jiān)聽ffpmeg運行狀態(tài)情況
executor.createJob(builder, new ProgressListener() {
@Override
public void progress(Progress progress) {
System.out.println("-----------");
System.out.println(progress);
}
}).run();3. 第三方jar包實現(xiàn)優(yōu)缺點:
- 優(yōu)點:封裝好了ffmpeg調(diào)用功能,代碼實現(xiàn)簡單易用
- 缺點:沒有提供停止ffmpeg程序的方法,無法實現(xiàn)手動終止任務。就算手動殺死JAVA程序也無法終止ffmpeg程序的執(zhí)行,只有等ffmpeg轉(zhuǎn)流任務完成了程序自行停止。
方式二:采用ProcessBuilder類創(chuàng)建進程的方式調(diào)用ffmpeg實現(xiàn)
ProcessBuilder 類是JDK中java.lang包下提供的用于創(chuàng)建操作系統(tǒng)進程的類, 可以通過JDK API 文檔查看其用法。

1. 編寫java代碼
//創(chuàng)建一個命令List集合,用于存放ffmpeg執(zhí)行的命令參數(shù)
List<String> command = new ArrayList<>();
command.add("D:\\ffmpeg\\bin\\ffmpeg.exe");
command.add("-i");
command.add("D:\\123.mp4"); //輸入視頻源或者流地址
command.add("-c");
command.add("copy");
command.add("-f");
command.add("hls");
command.add("-hls_time");
command.add("10");
command.add("-hls_list_size");
command.add("5");
command.add("-hls_flags");
command.add("50");
command.add("D:\\hls\\test.m3u8"); //輸出流地址
//創(chuàng)建ProcessBuilder對象,傳入集合
ProcessBuilder builder = new ProcessBuilder(command);
//start()方法創(chuàng)建一個系統(tǒng)進程,執(zhí)行ffmpeg命令工具
Process process = builder.start();
//注意:使用ProcessBuilder執(zhí)行任務,必須要手動接收正常輸出信息和錯誤輸出信息,不然ProcessBuilder任務會阻塞卡住
//多線程讀取正常輸出信息 process.getInputStream()
new Thread(() -> {
try {
InputStream is = process.getInputStream();
//將正常輸出信息寫入到normal.txt文件中
RandomAccessFile raf = new RandomAccessFile("D:\\normal.txt", "rw");
byte[] data = new byte[128];
int len = -1;
while((len = is.read(data)) != -1) {
raf.write(data, 0, len);
}
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}, "Thread-Normal").start();
//多線程讀取錯誤輸出信息 process.getErrorStream()
new Thread(() -> {
try {
InputStream is = process.getErrorStream();
//將錯誤輸出信息寫入到error.txt文件中
RandomAccessFile raf = new RandomAccessFile("D:\\error.txt", "rw");
byte[] data = new byte[128];
int len = -1;
while((len = is.read(data)) != -1) {
raf.write(data, 0, len);
}
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}, "Thread-Error").start();
//destroy()方法可以停止進程,從而終止ffmpeg程序
//process.destroy();2. ProcessBuilder實現(xiàn)優(yōu)缺點:
- 優(yōu)點:可以手動調(diào)用destory()方法隨時停止ffmpeg程序的執(zhí)行
- 缺點:需要手動寫代碼去主動接收任務進程產(chǎn)生的正常輸出信息和錯誤信息,不然進程會被卡住。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
詳解Springboot整合Dubbo之代碼集成和發(fā)布
本篇文章主要介紹了Springboot整合Dubbo之代碼集成和發(fā)布,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
關于Spring MVC同名參數(shù)綁定問題的解決方法
Spring MVC中的參數(shù)綁定還是蠻重要的,最近在使用中遇到了同名參數(shù)綁定的問題,想著總結(jié)分享出來,下面這篇文章主要給大家介紹了關于Spring MVC同名參數(shù)綁定問題的解決方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-08-08
解讀HttpServletRequestWrapper處理request數(shù)據(jù)流多次讀取問題
在Java Web開發(fā)中,獲取HTTP請求參數(shù)是常見需求,本文詳細討論了通過POST方式獲取參數(shù)的兩種主要方法:使用request.getParameter()適用于application/x-www-form-urlencoded和multipart/form-data內(nèi)容類型;而對于application/json類型的數(shù)據(jù)2024-10-10

