2017年5月27日 星期六

FFmpeg : 指定要加特效的時間點

2017年5月27日 星期六
2016年底的這一篇「雄 : FFmpeg : 影片剪接與加馬賽克」中利用了 youtube-dl 下載影片,並以 FFmpeg 為剪接、加馬賽克的工具,不過,當時不知道自己的 FFmpeg 版本太舊,以致於Timeline editing 的選項一直沒試成功,最後是用土法鍊鋼的方法完成了想達到的效果。這兩天心血來潮,更新了 FFmpeg ,花了一點時間研究了 Timeline editing 選項,再次體驗了 FFmepg 的強大。

這一篇就來細說重頭,一步驟一步驟的練功,最後建構出在指定位置、指定時段打馬賽克的影片。

準備工作

首先當然是要先下載最新版的 FFmpeg。如果想使用 FFmpeg 的 Timeline editing 來設定套用特效起始和結束時間,必須為 version 2.0 以後的版本,相關資訊可以查 FFmpeg 的Changelog :

再來就是下載要測試的影片,為了測試方便,可以將影片檔和 ffmpeg 放在一起。

好了就可以開始來玩一下影片的剪裁和加馬賽克了。

crop 剪裁畫面

我們可以利用「crop」對來源影片由某個座標指定要裁剪的畫面大小。

例如:想在 (640, 270) 剪下 230 x 180 的矩形,可以用下面的語法:

crop=230:180:640:270

crop 使用的四個參數分別為「橫向寬度(width)」、「蹤向高度(height)」、「左邊座標(x)」和「上方座標(y)」。所以上面的語法會將畫面由左上角座標 (640, 270) 起將寬度 230、高度 270 的範圍剪裁下來。

如果原始的影片檔名為「source.mp4」,可以用底下的指令來實作看看:

ffmpeg -i source.mp4 -vf "crop=230:180:640:270" -c:a copy -y  output.mp4

參數說明:

  • -i : 指定原始影片的檔名。
  • -vf : 指定視訊的濾鏡( video filter ),本例只用 crop 來剪裁,其實可以混合多種。詳細的說明參考 Simple filtergraphics
  • -c:a copy : 聲音的部份和來源的一樣,不做做任何處理。
  • -y : 覆蓋已存在的檔案

成功的話,目錄中應該會多一個剪裁過的影片檔,檔名為「output.mp4」。

詳細的說明建議參考官方文件  FFmepg Filters 中的 crop。

boxblur 模糊特效(加馬賽克)

利用「boxblur」可以幫我們把影像變模糊。例如:

boxblur=10

上面的 10 是 luma_radius,可以想成是是模糊的程度,數字愈大(最大的是有限制的),原始的畫面愈看不清楚。

如果原始的影片檔名為「source.mp4」,可以用底下的指令來實作看看:

ffmpeg -i source.mp4 -vf "boxblur=10" -c:a copy -y  output.mp4


boxblur 其實有六個參數可以用來控制怎麼「糊」法,有興趣可以再玩玩吧!詳細的說明建議參考官方文件 FFmpeg Filters 中的 boxblur。


Timeline editing 在指定的時問加馬賽克

前面試過 boxblur 把畫面變模糊,在 FFmepg version 2.0 以後,有些特效我們還可以利用 Timline editing 的參數(enable)來指定要在哪一個片段才套用特效。boxblur 是可以使用 Timeline editing 的。

下面把前一小節中 boxblur 的那個例子再延伸一下,變成:

boxblur=10:enable='between(t,10,20)'

觀察一下,第一個參數「10」的後面多了個冒號和「enable='between(t,10,20)'」。

「enable」告訴 FFmpeg 要在後面條件時才套用特效。

「between」則是設定了一個時間範圍,括號中的三個參數分別為:
  • t : 單位使用秒數。
  • 10 : 由第 10 秒開始。
  • 20 : 在第 20 秒結束。
要特別注意的是「between」頭尾各有一個單引號,可別漏打了。

如果原始的影片檔名為「source.mp4」,可以用底下的指令來實作看看:

ffmpeg -i source.mp4 -vf "boxblur=10:enable='between(t,10,20)'" -c:a copy -y  output.mp4

完成以後,output.mp4 影片中應該會在 10~20 秒間才加上模糊的特效。


overlay 覆疊兩個影片

如果我們將要打馬賽克的畫面裁剪過以後,再覆疊在原來的位置,這樣子就像是只有針對該位置打馬賽克一般。想到達到這樣的目的,只要將前面的例子再加上「overlay」的特效即可。

既然要使用覆疊,當然要有兩個影片,照前面說的,我們打算覆疊的一個是原始影片,一個是打過馬賽克的影片。

在 FFmpeg 中,可以用 [v:0] 來代表第一個用「-i」指定的原始影片。

另外,我們也可以利用中括號裡加文字,效果類似標籤,可以為加特效以後的影片命名,讓 FFmpeg 可以識別它。例如將影片在 10~20 秒間加馬賽克並剪裁大小以後的影片命名為 [blurLogo1],語法如下:

crop=230:180:640:270, boxblur=10:enable='between(t,10,20)'[blurLogo1]

上面的語法要注意兩個地方:
  • crop 語法的尾巴後面和 boxblur 的前面有一個逗號,表示這兩種特效是合併使用的。
  • boxblur 語法的最後面多了 [blurLogo1],表示這個 crop + boxblur 的結果命名為  [blurLogo1],可以供後續的特效指定使用這處理過的影片。

有了前面的 [v:0] 和  [blurLogo1] 兩個影片以後,我們就可以使用 overlay 來將兩者結合。例如這樣的語法:

[v:0] [blurLogo1]overlay=640:270

前面的語法會將 [blurLogo1] 覆疊在 [v:0] 的座標 (640,270) 上。

所以有關特效的語法變成這樣長:

crop=230:180:640:270, boxblur=10:enable='between(t,10,20)'[blurLogo1]; [v:0] [blurLogo1]overlay=640:270

我們將影片在 10~20 秒間打馬賽克,並由座標 (640,270) 處剪裁起,再將它貼回原始影片的相同位置才輸出。要特別注意語法中的分號「;」不要漏了。分號之前是處理打馬賽克的語法,分號之後則是處理覆疊的部份。


如果原始的影片檔名為「source.mp4」,可以用底下的指令來實作看看:

ffmpeg -i source.mp4 -filter_complex "crop=230:180:640:270, boxblur=10:enable='between(t,10,20)'[blurLogo1]; [v:0] [blurLogo1]overlay=640:270" -c:a copy -y  output.mp4

哈!不知道有沒看出來,在指定特效的語法字串前面已經不是用「-vf」而是用「-filter_complex」?

「-vf」只適用在一輸入,一輸出的影片處理,這次是要影片輸出為 [blurLogo1],同時將有特效和原始影片兩個影片疊合以後再輸出,就必須使用「-filter_complex」,不然會出現錯誤訊息而無法執行。

完成以後,output.mp4 影片中應該會在 10~20 秒間才在 (640,27) 加上 230 x 180 的模糊特效。

【補充說明】
哈!有沒有人堅持要使用 -vf 而不使用 -filter_complex 的?
其實也是可以利用「split」,讓一個來源分為兩條線後再合併的,這樣就可以用「-vf」了!

語法如下:

ffmpeg -i source.mp4 -vf "split [main][temp]; [temp]crop=230:180:640:270, boxblur=10:enable='between(t,10,20)'[blurLogo1]; [main] [blurLogo1]overlay=640:270" -c:a copy -y  output.mp4

隨你玩啦!對於 FFmpeg 只能再讚嘆一次!


在兩個不同時間加上馬賽克

如何在兩個不同時間、不同位置加上不同大小的馬賽克呢?

其實語法還是類似的,最重要的是順序要注意而已。假設打算:
  1. 在 2:28.501~2:30.800 期間加入第一個馬賽克(blurLogo1),覆疊後稱為 Overlay1。
  2. 在 2:46.800~2:49.500 期間加入第二個馬賽克(blurLogo2),覆疊後稱為 Overlay2。

所以
  • [Overlay1] = [v:0] + [blurLogo1]
  • [Overlay2] = [Overlay1] + [blurLogo2]

第一次是將原始影片( [0:v] ) 和第一個馬賽克( [blurLogo1] ) 結合為 [Overlay1]。
第二次是將前一段結果( [Overlay1] ) 和第二個馬賽克( [blurLogo2] ) 結合為 [Overlay2]。
整個最後的目標是要得到 [Overlay2] 的結果。

先來個簡化指令的大概樣子( ..... 為省略的部份):

"[v:0]crop=...... , boxblur=......[blurLogo1];
[v:0]crop=...... , boxblur=......[blurLogo2]; [v:0] [blurLogo1]overlay=......[Overlay1]; [Overlay1]:[blurLogo2]overlay=......
[Overlay2]"

上的的語法中共用了三個分號「;」,前兩段指令先定義了兩個打馬賽克並剪裁的 [blurLogo1] 和 [blurLogo2],都是針對第一個輸入的影片 [v:0] 加入特效;緊接著則是依序進行了兩次覆疊;還滿好玩的,像不像玩「接龍」?

來實作一下吧!假設:

  • 玩一下這部影片:
    https://www.youtube.com/watch?v=s9OJYwsQlBI 
  • [blurLogo1] 預計要:
    將影片( [v:0] )於 2分28.501秒~2分30.800秒(148.501~150.800秒)時在座標 (640, 270) 處剪下 230 x 180 的大小。
  • [blurLogo2] 預計要:
    將影片( [v:0] )於 2分46.800秒~2分49.500秒(166.8秒~169.500秒)時在座標 (640, 440) 處剪下 850 x 220 的大小。
  • 輸入的影片檔名為 source.mp4,輸出到檔案 output.mp4

用底下的指令來實作看看:

ffmpeg -i source.mp4 -filter_complex "[v:0]crop=230:180:640:270, boxblur=10:enable='between(t,148.501,150.800)'[blurLogo1]; [v:0]crop=850:220:640:440, boxblur=10:enable='between(t,166.8,169.500)'[blurLogo2]; [v:0][blurLogo1]overlay=640:270[Overlay1];  [Overlay1][blurLogo2]overlay=640:440[Overlay2]" -map "[Overlay2]" -map 0:a -codec:a copy -y output.mp4

觀察一下,這次指令的後段多了什麼?

  • -map "[Overlay2]" :告訴 ffmpeg ,影片的最終結果是標註為 [Overlay2] 的那個。
  • -map 0:a :告訴 ffmpeg,聲音的輸出是由第一個輸入來源取得。
  • -codec:a copy : 告訴 ffmpeg,聲音直接和來源的編碼一樣,不重新編碼。

由於我測試的影片片長有三分多鐘,可以去喝杯茶,休息一下再來驗收成果。

裁取影片的部份片段

如果不想整部影片,只想要某段時間的影片,我們也可以用 FFmepg 來擷取。

底下先假設:
  • 下載回來的影片檔名為「source.mp4」。
  • 影片剪裁的範圍是由第 0 秒到 3 分 13 秒。
  • 最後輸出的檔名為「output.mp4」
執行下面的指令:

ffmpeg -ss 00:00:00.00 -t 00:03:13.00 -i source.mp4 -vcodec copy -acodec copy -y  output.mp4

或是

ffmpeg -ss 00:00:00.00 -t 00:03:13.00 -i source.mp4 -c copy -y output.mp4

上面使用到的參數:
  • -ss : 指定開始擷取的時間
  • -t : 指定擷取多長的時間
  • -i : 指定影音來源
  • -c : 指定串流的編碼或解碼方式,-c copy 表示和來源一樣。
  • -y : 檔案如果已存在,直接覆蓋。

語法產生器


用 JavaScript寫了個加馬賽克濾鏡用的語法產生器,可以玩玩看:
影片的來源:
輸出的檔名:
模糊的參數:


1.時間點:
   座標:(,),大小:x


FAQ

  • Q: 擷取了部份影片以後,要加特效時,卻出現 "Too many packets buffered for output stream 0:1." 的錯誤訊息,該怎麼處理?
    A: ffmpeg 的指令中加入底下的參數:
    -max_muxing_queue_size 400
    詳情可以參考: https://trac.ffmpeg.org/ticket/6375
  • Q: 使用骨灰級的 Windows XP,而由官方的網頁中下載的 FFmpeg 已不再支援 Windows XP,可以去哪裡下載?
    A: 可以試試:由「ffmpegwindowsbi 專案」來下載。
  • Q: 利用 -ss 和 -t 的選項剪裁影片,-ss 不能由第 0 秒(00:00:00.00)開始,而要由第5秒(00:00:05.00)開始,不然不但前五秒會變黑畫面(聲音正常),之後要加特效也會有問題。有別的方法可以處理嗎?
    A: 查了一下,黑畫面的原因是 FFmpeg 照我們的設定裁完影片,把 key frames 給切掉了,而播放軟體要一直到下一個 key frame 才會開始播放。這種狀況在選用不重新編碼的參數「-c copy」時,很容易發生。在底下的討論串中有深入的探討:
    https://github.com/mifi/lossless-cut/pull/13


相關文章



2 則留言:

  1. 非常感謝您用心地分享! 一直以來跟您學習到許多可以用在課堂中的工具尤其是筆順練習的寫字板仍在每課剛開使時運用!特別感恩!
    康筱君 (美國加州密爾必達市高中教師)

    回覆刪除
    回覆
    1. 康老師您好:
      您客氣了, 哈!您提到的 "筆順練習的寫字板" 會不會是陳榮紳老師的這個:
      應用軟體之03-中英文寫字練習板-[更新版]

      刪除

 
雄::gsyan © 2009. Design by Pocket