FFmpeg手撕視頻(Android端)

前言

FFmpeg是很是強大的音視頻處理工具,咱們可使用它來處理視頻合成、剪輯、加特效等等操做。html

官方文檔至上 FFmpeg的官方文檔git

FFmpeg的官方文檔命令真的是太多太多,並且都是英文,感受精通完這些命令,都夠學一門新語言了!github

SO 爲了讓一些小夥伴們快速的用上FFmpeg,我整理了一些FFmpeg的經常使用的知識和大部分平常用到的命令供你們查閱!算法

還不收藏嗎?廢話很少說上乾貨!bash

Android端使用FFmpeg

FFmpeg的環境集成挺麻煩的推薦你們使用這個庫,一鍵集成FFmpeg! Skr~ide

RxFFmpeg工具

關於音視頻須要瞭解的東西

音/視頻流

在音視頻領域,咱們把一路音/視頻稱爲一路流。如咱們小時候常用VCD看港片,在裏邊能夠選擇粵語或國語聲音,其實就是CD視頻文件中存放了兩路音頻流,用戶能夠選擇其中一路進行播放。oop

容器

咱們熟悉的mp4,rmvb,mkv,avi是多媒體容器文件格式(或稱多媒體封裝格式),所謂容器是指將不一樣的數據流(視頻流,音頻流,字幕流等)封裝在一個文件(載體)中。 播放時各類流分別進行解碼等處理後,而後輸出到顯示器和音響等設備進行播放。多媒體容器格式不一樣於編碼格式,一個容器中能夠封裝多種編碼格式的媒體流。 流封裝了實際的媒體數據,如視頻流,音頻流和字幕流等。通常狀況下,流中的數據只能使用一種編碼格式。性能

channel

是音頻中的概念,稱之爲聲道。在一路音頻流中,能夠有單聲道,雙聲道或立體聲。測試

幀率

幀率(frames per second, fps)是每秒畫面刷新的次數,幀率越高視頻越流暢。通常來講30fps就是能夠接受的,60fps則能夠明顯提高交互感和逼真感,可是通常超過75fps通常就不容易察覺到有明顯的流暢度提高了。

分辨率

分辨率表示畫面的精細程度,一般用像素密度來表示,經常使用的單位爲ppi(像素每英寸)。一般像素密度越高畫面越精細,模糊程度越低。對於視頻文件而言,像素密度是沒法控制的(由播放器和顯示設備決定)。咱們一般用視頻的像素數來表示它的分辨率如1080x640, 640x320等。

比特率

比特率(bit rate)又稱碼率,表示多媒體流每秒輸出的字節數,單位爲KB/s,Kbps等。一樣的壓縮算法下,比特率越高音視頻的質量越好。

可變碼率(Variable Bitrate, VBR)

指的是編碼器的輸出碼率能夠根據輸入源信號的複雜度進行自適應調整,以在輸出質量保持不變的條件下儘量減小數據量。VBR適用於存儲,不太適用流式傳輸。

固定碼率(Constant Bitrate, CBR)

指的是編碼器輸出碼率固定,CBR不適合存儲,對於複雜內容可能沒有足夠碼率進行編碼,從而致使質量降低,同時會在簡單內容部分浪費一些碼率。

採樣率

每秒鐘對音頻信號的採樣次數,採樣頻率越高聲音還原度越高,聲音更加天然,單位是赫茲 Hz。音頻文件通常使用的採樣率是 44.1kHz,也就是一秒鐘採樣44100次,實驗發現低於這個值就會有較明顯的損失,而高於這個值人的耳朵已經很難分辨,並且增大了數字音頻所佔用的空間。

視頻編碼

視頻流能夠看作圖片的序列,咱們把這個序列中的一張圖片稱爲一幀。若存儲視頻中全部幀則會數據量過大,不便於存儲和傳輸。所幸統計代表大多數視頻相鄰幀之間的區別並不大,因此對於一段變化不大的視頻,咱們能夠先完整編碼幀A,其後的B幀只須要編碼與A幀不一樣的部分,B幀後的C幀則只編碼與B幀的差別。如此遞推,將一段視頻編碼爲一個序列。當某個圖像與以前的圖像變化很大沒法參考前面的幀來生成,咱們就結束上一個序列將該幀完整編碼開始一個新的序列。

H264是目前流行的一種視頻編碼算法,它定義了三種幀:完整編碼的I幀,參考I幀生成只包含差別的P幀,以及以及參考先後幀編碼的B幀。

H264採用的核心算法是幀內壓縮和幀間壓縮,幀內壓縮是生成I幀的算法,幀間壓縮是生成B幀和P幀的算法。一般,咱們也把完整編碼的I幀稱爲關鍵幀。由於解碼非關鍵幀須要解碼其參考的幀,所以在截圖等不須要所有解碼的操做中,常常截取關鍵幀以提高性能。

FFmpeg的基本字符命令

-i 輸入文件的地址

-y 表示直接覆蓋已經存在的輸出文件

-n 表示若某個輸出文件已經存在則退出(若沒有設置-y或-n選項,且某個輸出文件已經存在ffmpeg會詢問是否要覆蓋輸出文件)

-codec(-c) 指定輸入輸出的解碼編碼器 copy 則將輸入流直接複製到輸出流不進行編解碼操做

-c:v 或-vcodec 能夠爲全部視頻流指定編碼器,-c:v:1爲第2個視頻流指定編解碼器。xvid(使用XVID編碼壓縮視頻,不能改的)

-c:a 或-acodec 能夠爲全部音頻流指定編碼器,-c:a:12爲第13個視頻流指定編解碼器。

-pixel_format/-pix_fmt 指定轉換格式 例:yuv420p

-vol 音量

-ss 選項用於設置流的開始時間,能夠設置輸入輸出或者濾鏡。在開始時間以前的幀將被跳過不被處理(輸入不被解碼,輸出不被編碼,濾鏡不被處理)。

例:ffmpeg -ss 2 -t 10 -i test.mp4 test.mov

時長的格式:如-t 10, -t 23.167 時分秒: 如-t 10:23, -t 21:31:00.233

-t 選項用於用於設置輸入輸出,-t在-i前能夠限制輸入時長,-t在輸出文件前能夠限制輸出時長

-to 選項相似於-t選項,不一樣的是-to指定結束時刻,-t指定持續時間

-f 強制設置輸入輸出的文件格式,默認狀況下ffmpeg會根據文件後綴名判斷文件格式

-filter / -filter_complex 使用過濾器對流進行處理 複雜過濾器

-vf 代替-filter:v處理視頻流

-af 代替-filter:a處理音頻流

-vframes 設置要輸出的視頻幀的數量: 例:ffmpeg -i test.mp4 -vframes 10 test.mov

-aframes 設置要輸出的音頻幀的數量。這是-frames:a的一個過期的別名。

-vn 不將視頻流寫到輸出文件中無視頻的意思 例:ffmpeg -i test.mp4 -vn -a:c copy out.mp3

-an 不將音頻流寫到輸出文件中無音頻的意思 例:ffmpeg -i test.mp4 -v:c copy -an out.mp4

-r 設置某個流的幀率按ffmpeg官方文檔說-r與-framerate做用相同,但實際測試時發現不一樣。-framerate 用於限制輸入,而-r用於限制輸出 例:ffmpeg -i test.mp4 -r:v 30 test.mov

-s 設置幀的大小 例:ffmpeg -i test.mp4 -s 1080x680 out.mp4

-aspect [:stream_specifier] 寬高比(輸出,每一個流) 設置方面指定的視頻顯示寬高比。aspect能夠是浮點數字符串,也能夠是num:den形式的字符串,其中num和den是寬高比的分子和分母。例如「4:3」,「16:9」,「1.3333」和「1.7777」是有效的參數值。若是與-vcodec副本一塊兒使用,則會影響存儲在容器級別的寬高比,但不會影響存儲在編碼幀中的寬高比(若是存在)。

-threads 設置處理線程數 例:ffmpeg -threads 8 -i test.mp4 out.mp4

-shortest 當最短的輸入流結束後即中止編碼和輸出 例:ffmpeg -i bgm.mp3 -i test.mp4 -shortest output.mp4

-sample_fmts 設置音頻採樣格式。使用-sample_fmts獲取支持的樣本格式列表。

-b:a 指定音頻碼率。 b 是 bitrate的縮寫, a是 audio的縮寫

-b:v 指定視頻碼率。 b 是 bitrate的縮寫, v是 video的縮寫

-loop 循環輸入流。只工做於圖像流

concat 拼接視頻 例:ffmpeg -i "concat:1.mp4|2.mp4|3.mp4" -c copy output.mp4

Filter(濾鏡)

複雜過濾器(filter_complex)

過濾器會對已解碼的幀進行處理,處理後的幀會被從新編碼輸出

scale

指定操做源的大小,iw指定按整型取視頻的寬度,ih指定按整型取視頻的高度。-1爲按原圖比例變化 例:iw/2:-1視頻縮小一倍

overlay

指定操做源擺放的位置 overlay=30:10 main_w和main_h爲底層視頻的寬和高,overlay_w和overlay_h爲疊加視頻的寬和高

delogo

刪除水印 例:delogo=x=800:y=20:w=70:h=80

crop

裁剪 格式:crop=out_w:out_h: x :y out_w: 輸出的寬度。可使用 in_w 表式輸入視頻的寬度。 out_h: 輸出的高度。可使用 in_h 表式輸入視頻的高度。 x : X座標 y : Y座標 x和y 設置爲 0,說明從左上角開始裁剪。若是不寫是從中心點裁剪

setpts

setpts=0.5*PTS表示每幀視頻的pts時間戳都乘0.5,也就是視頻加快一倍

-map

可用於處理複雜輸出,如能夠將指定的多路流輸出到一個輸出文件,也能夠指定輸出到多個文件。"[v]" 複雜濾鏡輸出的別名做爲輸出文件的一路流。上面 map的用法是將複雜濾鏡輸出的視頻和音頻輸出到指定文件中。

水平翻轉hflip

鏡像

crop=iw/2:ih:0:0,split[left][tmp];[tmp]hflip[right]

各類特效curves

curves='vintage'(復古) 'strong_contrast'(強對比度)'lighter'(變亮) 'negate'(底片) 'none' 'color_negative'(彩色底片);

邊緣檢測edgedetect

光暈vignette=PI/4

變暗

colorlevels=rimin=0.058:gimin=0.058:bimin=0.058

增長對比度

fftfilt=dc_Y=0:weight_Y='exp(-4 * ((Y+X)/(W+H)))

降噪

hqdn3d=luma_spatial=15.0

銳化

fftfilt=dc_Y=0:weight_Y='1+squish(1-(Y+X)/100)'

低通濾波

fftfilt=dc_Y=0:weight_Y='squish((Y+X)/100-1)'

高通濾波

fftfilt=dc_Y=128:weight_Y='squish(1-(Y+X)/100)'

fade 視頻淡入淡出效果

例:fade=in:0:25, fade=out:975:25 從0楨開始淡入25幀,從975開始淡出25幀 fade=in:5:20:color=yellow 開始淡入前爲黃色 fade=in:0:25:alpha=1 淡入完成後過去15幀的透明度 fade=t=in:st=5.5:d=0.5 5.5秒開始,淡入0.5秒 d爲時長

fps濾鏡經過刪除幀或者複製幀的方法強制設置幀率 例:ffmpeg -y -i test.mp4 -vf "fps=60" out.mp4

經常使用命令

視頻格式轉換

ffmpeg -i out.mp4 -y out.avi

視頻轉Gif

視頻轉Gif

ffmpeg -i out.mp4 -y out.gif

從0開始截10s轉Gif

ffmpeg -i out.mp4 -ss 00:00:00 -t 10 -y out.gif

視頻轉多張圖片

每秒生成一個張圖片

ffmpeg -i input_test.mp4 -vf fps=1 out%03d.png

每分鐘生成一張圖片

ffmpeg -i input_test.mp4 -vf fps=1/60 out%03d.png

截取視頻中的某段視頻

ffmpeg -ss 2 -i test.mp4 -t 10 -y -f out_test.mp4

截取從2s開始10秒的視頻

視頻分片(把視頻切爲一段一段)

ffmpeg -i test.mp4 -c copy -map 0 -f segment -segment_time 10 video/part-%d.mp4

截取視頻中某個時間段的單張圖片或多張圖片

ffmpeg -ss 2 -i test.mp4 -r 1 -t 2 -y -f image2 image-%3.jpeg

單張圖片或多張圖片轉視頻

ffmpeg -loop 1 -i img%3d.png -t 10-y output.mp4

Gif轉視頻

ffmpeg -i input.gif -y output.mp4

多個視頻合併

ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4

修改視頻分辨率

ffmpeg -i input_test.mp4 -s 320*240 out_test.mp4

給視頻添加音頻

ffmpeg -i input.mp4 -i input1.mp3 -y output.mp4

提取視頻中的音頻

ffmpeg -i test.mp4 -vn -a:c copy out.mp3

視頻靜音

ffmpeg -i input.mp4 -vn -vcodec copy output.mp4

音頻合併

ffmpeg -i "concat:test1.mp3|test2.mp3" -acodec copy output.mp3

高級命令

音頻混音

ffmpeg -i input_01.wav -i input_02.wav -filter_complex amix=inputs=2:duration=shortest:dropout_transition=3 output.wav

以兩個音頻文件時長較短的音頻文件時長做爲最終輸出的時長

  • inputs: The number of inputs. If unspecified, it defaults to 2.//輸入的數量,若是沒有指明,默認爲2.
  • duration: 決定了流的結束
  • longest: 最長輸入的持續時間
  • shortest:最短輸入的持續時間
  • first: 第一個輸入的持續時間
  • dropout_transition: 輸入流結束時(音頻)容量重整化的轉換時間(以秒爲單位)。 默認值爲2秒。

添加文字水印

ffmpeg -y -i test.mp4 -vf "drawtext=fontfile=CourierNew.ttf:text='hello world':x=100:y=50:fontsize=24" out.mp4

Android端添加文字水印

因爲Android端字體庫的緣由,我能夠經過把文字轉成圖片,再加到視頻上的方式來添加,如下是文字轉圖片的源碼:

/**
     * 文本轉成Bitmap
     * @param text 文本內容
     * @param context 上下文
     * @return 圖片的bitmap
     */
    private static Bitmap textToBitmap(String text , Context context) {
        float scale = context.getResources().getDisplayMetrics().scaledDensity;
        TextView tv = new TextView(context);
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        tv.setLayoutParams(layoutParams);
        tv.setText(text);
        tv.setTextSize(scale * TEXT_SIZE);
        tv.setGravity(Gravity.CENTER_HORIZONTAL);
        tv.setDrawingCacheEnabled(true);
        tv.setTextColor(TEXT_COLOR);
        tv.setBackgroundColor(Color.WHITE);
        tv.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
        tv.buildDrawingCache();
        Bitmap bitmap = tv.getDrawingCache();
        int rate = bitmap.getHeight() / 20;
        return Bitmap.createScaledBitmap(bitmap, bitmap.getWidth()/rate, 20, false);
    }
 
    /**
     * 文字生成圖片
     * @param filePath filePath
     * @param text text
     * @param context context
     * @return 生成圖片是否成功
     */
    public static boolean textToPicture(String filePath, String text , Context context){
        Bitmap bitmap = textToBitmap(text , context);
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(filePath);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }finally {
            try {
                if(outputStream != null){
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    } 
    
複製代碼

添加圖片水印

添加單個圖片水印

ffmpeg -i input.mp4 -i water.png -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-10:10" -y output.mp4

添加多個圖片水印

ffmpeg -i input.mp4 -i photo1.png -i photo2.png -filter_complex "[0:v]fade=in:st=0:d=2,curves=vintage[img];[1:v]scale=300:-1[img1];[img][img1]overlay=10:10[out1];[out1][2:v]overlay=main_w:main_h" -y output.mp4

添加了兩張圖片圖片,第一張設置爲寬度300,高度-1爲根據原圖片比例縮放,在視頻左上角,第二張圖片在視頻右下角,fade是淡入淡出效果器,視頻效果爲從0s開始淡入,淡入2s,視頻爲復古效果curves=vintage

跑馬燈效果

ffmpeg -i video2.mp4 -i logo.png -filter_complex "[1:v]scale=50*50[logo];[0:v]scale=200*200[bg];[bg][logo]overlay=x='if(gte(t,0),-overlay_w+(mod(n,main_w+overlay_w))+5,NAN)':y=0" -y output.mp4

含義: 時間t大於0,那麼就開始從子內容的寬度的x-overlay_w位置開始,而後每一幀n計數,幀數n除以(背景main_w+子內容背景overlay_w)求除數+1設置爲x座標,便可循環 overlay=30:10 main_w和main_h爲底層視頻的寬和高,overlay_w和overlay_h爲疊加視頻的寬和高

視頻去水印

ffmpeg -i test.flv -vf delogo=x=20:y=20:w=70:h=80 output.flv

x,y :指定水印的位置,即圖片左上角的座標 w,h:給出水印的寬高

添加動畫

ffmpeg -y -i test.mp4 -t 10 -loop 1 -framerate 6 -i test_%3d.png -filter_comple 'overlay=10:main_h-overlay_h-10' out.mp4

將多張圖片(test_001.png, ani002.png...)組成動畫, 而後將這個動畫疊加在視頻的左下角。-t 10 -loop 1會循環播放動畫,持續10s

淡入淡出效果器

ffmepg -i input.wav -filter_complex afade=t=in:ss=0:d-4 output.wav

(淡入)把 input 文件的前5s 作一個淡入效果,輸出到 output.wav 中

ffmpeg -i input.wav -filter_complex afade=t=out:st=200:d=5 output.wav

(淡出)將input.wav文件從200s開始,作5s的淡出效果,並放到output.wav文件中

視頻提亮效果器

ffmpeg -i input.flv -c:v libx264 -b:v 800k -c:a libfdk_aac -vf eq=brightness=0.25 -f mp4 output.mp4

提亮參數是brightness,取值範圍是從-1.0到1.0,默認值是0

爲視頻增長對比度效果

ffmpeg -i input.flv -c:v libx264 -b:v 800k -c:a libfdk_aac -vf eq=contrast=1.5 -f mp4 output.mp4

對比度參數是contrast,取值範圍是從-2.0到2.0,默認值是1.0

截取視頻區域

ffmpeg -i input.mp4 -an -vf "crop=480:480:120:0" -vcodec libx264 -b:v 800k output.mp4

旋轉視頻

ffmpeg -i input.mp4 -vf "transpose=1" -b:v 600k output.mp4

改變視頻音量

ffmpeg -i input.mp4 -af 'volume=0.5' output.mp4

壓縮視頻

視頻壓縮主要是改變視頻的碼率和分辨率去壓縮,可是須要控制好縮小的碼率和分辨率,以保證視頻的質量符合你的需求 ffmpeg -i input.mp4 -b:v 600k -y output.mp4

END

FFmpeg十分強大,本文的知識只是FFmpeg的一小部分,對於初識FFmpeg的同窗用於常見的視頻操做仍是徹底OK的,精通音視頻仍是有很長的路要走,更多的FFmpeg知道請移步FFmpeg的官方文檔

歡迎靚仔靚女們收藏一波,謝謝~

相關文章
相關標籤/搜索