FFmpeg command line tool(Android中使用FFmpeg命令行)

關於轉碼:

網絡限制了視頻傳輸的帶寬。因爲帶寬限制,這就要求咱們在傳輸以前經過實時視頻轉碼將視頻數據轉換成帶寬效率更高的格式。轉碼的意義在於能夠在視頻質量幾乎不損失的前提下節省大量的網絡帶寬。FFmpeg主要就是作轉碼這件事情。html

FFmpeg轉碼流程示意圖:

_______              ______________
|       |            |              |
| 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 => 能夠理解爲流的過濾器:

    • -map[0:v] 就是選擇第一輸入源的視頻流,流向輸出。
    • -map[1:a] 就是選擇第二輸入源的音頻流,流向輸出。
  • -max_muxing_queue_size=>若是視頻比較大,須要指定這個值比較大(好比9999),不然程序執行會中斷。

  • -fps 幀率

  • -vframes 幀數

  • -r幀率

  • -preset

    • preset和crd參數同樣,會影響壓縮效果,preset能夠很大程度影響程序的執行速度,每條命令均可以加,通常加載命令尾部,output以前:
    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
    複製代碼

    Concat protocol

視頻音頻流變速

  • How to speed up / slow down a video 視頻速度變成原來的兩倍:
    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 複製代碼

裁剪時長

  • -ss 裁剪開始時間,單位秒
  • -t 須要裁剪多長時間,單位秒 從第一秒,裁剪3秒視頻生成新視頻 -y -i input.mp4 -s 1 -t 3 ouput.mp4

生成縮率圖

  • 這裏涉及兩個指令-vframes ,-fps;
    • -vframes是幀數
    • -fps是幀率,(frames per second),時間(秒)fps=vframs -生成某個時刻的縮率圖: 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

圖片生成幻燈片(多圖合成視頻)

  • 如何輸出的圖片是規則的,img001png,img002.pmg,img003.pn... 我生成每秒10幀的幻燈片,默認是25幀每秒: ffmpeg -framerate 10 -i img%03d.png output.mp4 注意:若是生成是h264的視頻,加上 -vf format=yuv420p 或者 -pix_fmt yuv420p能夠防止某些播放器沒法解碼視頻。 生成幻燈片相關
  • 若是文件名是不規則,也可使用concat協議:
    • 先生成一個text文件,寫上對應的file和duration(時長):
      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指令

水印

  • 疊加一張靜態圖,overlay是picture左上角對應的座標,(座標系:以視頻左上角爲原點,向右爲正方向,向下爲正方向): ffmpeg -i input -i picture -filter_complex overlay=0:0 output
  • 疊加GIF,若是想要GIF無限循環,使用這條指令(不然能夠用上面的指令): 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

GIF

從視頻前兩秒片斷中抽出一張幀率是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相關

Android 使用:

  • 生成一個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) {
          }
    複製代碼

如何獲取處理進度:

  • FFmpeg在處理的過程會打印出一些信息,好比 frame= 1 fps=0.0 q=0.0 size= 0kB time=00:01:02.71 bitrate= 0.0kbits/s speed=2.88x 咱們能夠拿到time信息,這是處理到哪一個時間點的信息,把他專程秒,處理視頻時長,就能夠獲得處理進度。
相關文章
相關標籤/搜索