2019年4月3日 星期三

用ffmpeg剪接影片

有時候,你就是會需要一點剪接,而且只是大量批次的處理,會讓你有點想...找個好方法
我就用我自己的換片頭案例筆記如下

首先剪掉原來dvd轉出影片的片頭,命令格式是
ffmpeg -i input.m4v -ss 00:01:13.00 -t 00:13:42.02 -acodec copy -vcodec copy -async 1 output.m4v
乍看之下,片頭開始時間-ss應該好解決,但是-t後面的片長就不好解決了。每個影片都不一樣長,怎麼辦?好吧,那找個函式抓片長時間
#getDuration(){ ffmpeg -i $1 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//; }
getDuration(){ len=$(ffmpeg -i $1 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//); echo $len "," $1 ;}

然後把檔案名單放進陣列裡
filelist=$( ls *.m4v)
然後來做個命令底稿
for filename in ${filelist}; do
length=(getDuration ${filename});
echo "ffmpeg -i ${filename} -ss 00:01:13.00 -t $length -acodec copy -vcodec copy -async 1 output/${filename}.m4v" >> batch1.sh;
done
檢視完沒問題,就試著執行看看結果。
這裡講到一個哲學問題,如果有把握,為何不直接把命令就湊下去給shell跑呢?因為我稱這種工作叫做lazy job,還沒有到daily routine,因此處在「不需要寫程式,但是需要改命令稿」的灰色地帶,因此把指令先放在文字檔,Try run後修修改改調整到ok,或是面對部份失敗的幾行命令可以剪貼出來重複執行,這樣反而比思考如何修改程式更有彈性。而使用的工具只需要簡單的筆記本的搜尋取代,就可以完成「改程式」。

因為片頭是網路下載的,我自己是先將解析度格式處理成一樣
ffmpeg -i Poli_cut.mp4 -vf scale=720:480 policut.mp4
然後又是一樣的招數,但是我選擇將影音重新編碼,因為前面截斷copy cut的會出現奇怪的問題。
for filename in ${filelist}; do
echo "ffmpeg -v quiet -stats -i policut.m4v -i $filename  -filter_complex final/$filename" >> batch2.sh;
done
但是實際命令格式是這樣
ffmpeg -v quiet -stats -i policut.m4v -i 01-1.m4v  -filter_complex "[0:v] [0:a] [1:v] [1:a] concat=n=2:v=1:a=1 [v] [a]" -map "[v]" -map "[a]" final/01-1.m4v
這就呼應到前面講的哲學,如果你要把它搞成很厲害的幾行程式碼,弄到來一個殺一個m來兩個殺一雙的無敵境界,那你要處理上面這些粗體字裡面的跳脫字元就搞不完,保證多拖你半小時。但是你用記事本搜尋取代插入這些字眼到指令稿,保證不到30秒。

第二是我果然某一部份處理錯誤,我做的事情只是把指令稿全部#註記起來,然後把要重複跑的幾行打開調整。這樣比起寫程式還有效率又好調整。

後記:
ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts
cat part1.ts part2.ts > parts.ts
ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4

沒有留言: