網絡限制了視頻傳輸的帶寬。因爲帶寬限制,這就要求咱們在傳輸以前經過實時視頻轉碼將視頻數據轉換成帶寬效率更高的格式。轉碼的意義在於能夠在視頻質量幾乎不損失的前提下節省大量的網絡帶寬。FFmpeg主要就是作轉碼這件事情。html
_______ ______________
| | | |
| input | demuxer | encoded data | decoder
| file | ---------> | packets | -----+
|_______| |______________| |
v
_________
| |
| decoded |
| frames |
|_________|
________ ______________ |
| | | | |
| output | <-------- | encoded data | <----+
| file | muxer | packets | encoder
|________| |______________|
複製代碼
-y => 覆蓋輸出java
-i => 輸入源頭,好比一個視頻的絕對路徑:/sdcard/....,輸出咱們也是寫絕對路徑android
-f => 輸出格式,若是省略就取輸出錄製的後綴名爲輸出格式,好比輸入mp4格式:-y -i input -f mp4 outputgit
-c:v => 針對視頻流的編碼 ,等介於-vcodecgithub
-c:a => 針對音頻流的編碼,等介於-acodec數組
-c:v h264 => 指定視頻流h264編碼方式,有時候也寫成libx264,FFmpeg也能夠識別bash
-c:a aac => 指定音頻流aac編碼方式網絡
copy => 不編碼,如-c:v copy就是對視頻流不編碼,注意:若是加了沒必要要的編碼操做,會影響執行效率。app
-an => 禁用音頻ide
-vn => 禁用視頻
-x264-params keyint=10 => 爲視頻設置關鍵幀,每隔10幀生成一個關鍵幀
-crf => 動態碼率,壓縮效果佳,不是一味追求體積,畫質佳,H.264的CRF數字範圍在0~51,23是默認值。
-b:v => 靜態碼率,壓縮效率比較爆炸,一味控制體積
-filter_complex => 濾鏡,簡單濾鏡是-vf,經常使用的有變速濾鏡,水印濾鏡等
-map => 能夠理解爲流的過濾器:
-max_muxing_queue_size=>若是視頻比較大,須要指定這個值比較大(好比9999),不然程序執行會中斷。
-fps 幀率
-vframes 幀數
-r幀率
-preset
preset | 描述 |
---|---|
ultrafast | 編碼速度最快 ,壓縮效果最差 |
superfast | ··· |
veryfast | ··· |
faster | ··· |
fast | ··· |
medium | – default preset |
slow | ··· |
slower | ··· |
veryslow | 編碼速度最慢 ,壓縮效果從最好 |
h264編碼相關,涉及CRF,Preset等,Encode/H.264
使用concat協議:把視頻轉成ts流,contact合併多個ts生成視頻:
mp4-->ts:
remux an MP4 file containing an H.264 stream to mpegts format with ffmpeg,
you can use the command:
ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts
多個ts合併:
ffmpeg -i "concat:input1.ts|input2.ts|input3.ts" -c copy output
複製代碼
ffmpeg -i input.mkv -filter:v "setpts=0.5*PTS" output.mkv
音頻速度變成原來的兩倍: ffmpeg -i input.mkv -filter:a "atempo=2.0" -vn output.mkv
若是是音頻和視頻一致加速兩杯: 這裏會涉及到濾鏡的概念和-map指令的使用,輸入有多個流,咱們就可能用到-map指定: 假設有音頻流和視頻流:speed是目標速率,好比2.
-y -i input -filter_complex [0:v]setpts=" + 1d/speed + "*PTS[v];[0:a]atempo=" + speed + "[a] output
複製代碼
若是隻有視頻流:
-y -i input -vf [0:v]setpts=" + 1d/speed + "*PTS" output 複製代碼
-y -i input.mp4 -s 1 -t 3 ouput.mp4
ffmpeg -i input.flv -ss 00:00:14.435 -vframes 1 out.png
每秒生成一張圖片,命名爲thumb1.png,thumb2.png,thumb3.png.....(輸出是絕對路徑) ffmpeg -i input -vf fps=1 thumb%d.png
每秒生成兩張圖片,命名爲thumb001.png,thumb002.png,thumb003.png,-s指令來指定分辨率100100..... ffmpeg -i input -s 100X100 -vf fps=2 thumb%3d.png
ffmpeg -framerate 10 -i img%03d.png output.mp4
注意:若是生成是h264的視頻,加上 -vf format=yuv420p 或者 -pix_fmt yuv420p能夠防止某些播放器沒法解碼視頻。 生成幻燈片相關duration 5
file '/path/to/cat.png'
duration 1
file '/path/to/rat.png'
duration 3
file '/path/to/tapeworm.png'
duration 2
file '/path/to/tapeworm.png'
複製代碼
ffmpeg -f concat -i input.txt -vsync vfr -pix_fmt yuv420p output.mp4
ffmpeg -i input -s width*height -c:v h264 output
在起點(x,y)的地方裁剪下長高爲wh的區域對應的視頻(座標系:以視頻左上角爲原點,向右爲正方向,向下爲正方向) ffmpeg -i -vf crop=w:h:x:y output
crop指令
ffmpeg -i input -i picture -filter_complex overlay=0:0 output
ffmpeg -i input -ignore_loop 0 -i gif -filter_complex overlay=shortest=1
若是須要加座標: ffmpeg -i input -ignore_loop 0 -i gif -filter_complex overlay=x:y:shortest=1
從視頻前兩秒片斷中抽出一張幀率是10的GIF ffmpeg -i INPUT -ss 0 -t 2 -r 10 out.gif
上門的指令生成的GIF是比較模糊的,若是要生成高清的GIF: 先生成調色板,再利用調色板生成GIF,假設fps=10, ffmpeg -i INPUT -r 10 -vf fps=10,scale=300:-1:flags=lanczos,palettegen colorPalette.png
scale是縮放的意思,這裏是設置寬爲300,-1是保持寬高比. ffmpeg -i input -i colorPalette.png -r 10 -lavfi fps=10,scale=300:-1:flags=lanczos[x];[x][1:v]paletteuse
獲得清晰GIF相關
生成一個Shell命令數組,丟給FFmpeg可執行文件處理便可 tips:文檔上的命令都是用空格隔開,其實把他理解成數組就好,重點是數組內的元素不要錯便可;
String ffmpegSplitWord = "若是是空格容易出錯,儘可能是一個不容易和其餘命令出突的字符(儘可能和文件名不衝突)";
StringBuilder sb = new StringBuilder("-y");
sb.append(ffmpegSplitWord + "-i");
sb.append(ffmpegSplitWord + input.toString());
sb.append(ffmpegSplitWord + "-c:v");
sb.append(ffmpegSplitWord + "libx264");
sb.append(ffmpegSplitWord + "-x264-params");
sb.append(ffmpegSplitWord + "keyint=" + Constant.Camerasettings.keyint);
setBitRate(ffmpegSplitWord, sb);
setPreset(ffmpegSplitWord, sb);
sb.append(ffmpegSplitWord + output.toString());
String ffmpeg_s = sb.toString();
String[] command=ffmpeg_s.split(ffmpegSplitWord);
try {
FFmpeg.getInstance(IApplication.getInstance()).execute(command, new ExecuteBinaryResponseHandler() {
@Override
public void onFailure(String s) {
}
@Override
public void onSuccess(String s) {
}
@Override
public void onProgress(String s) {
}
@Override
public void onStart() {
}
@Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
}
複製代碼
frame= 1 fps=0.0 q=0.0 size= 0kB time=00:01:02.71 bitrate= 0.0kbits/s speed=2.88x
咱們能夠拿到time信息,這是處理到哪一個時間點的信息,把他專程秒,處理視頻時長,就能夠獲得處理進度。