ffmpegで動画の音声を差し替える

タイトル通り、ffmpegで動画の音声を差し替える方法について記述していきます。
プレゼンの時にちょっとした動画が必要となり、無音の動画の音声をつける必要があったので、その際に使用したコマンドをメモしておきます。

ffmpegとは

動画のトリムやコーデックの変更など、コマンドラインでサクッと動画編集ができるフリーのソフトウェアです。皆さんも触ったことはあるのではないでしょうか。

先ほども「コマンドラインで」と書いたように、ffmpeg単体ではGUIを持ちません。「ffmpeg GUI」などでググればffmpegのGUIもたくさん転がっているようです。(筆者はコマンドラインで十分事足りているので、使ってはいませんが。)

youtubeからpytubeでミュージックビデオを落としてきて、音声のみ手持ちのCD音質に差し替えるといった使い方もできるのではないでしょうか。(書いている時に気がつきましたが、音声と映像のオフセットを厳密に合わせないとだめですね。)

ffmpegのインストール

macの方はbrewで

$ brew install ffmpeg

ubuntuの方はapt-getでインストールすることができます。

$ sudo apt-get install ffmpeg

音声の差し替え

動画ファイルと、音声ファイルを使って音声を差し替えるためのコマンドです。

$ ffmpeg -i <input_movie> -i <input_audio> -map 0:0 -map 1 -vcodec copy -acodec copy <output_movie>

-i <input_movie>
使用する動画ファイルを指定します。

-i <input_audio>
使用する音声ファイルを指定します。

-map 0:0
「0番目に指定したファイル(ここでは<input_movie>)の0番目の要素(映像)を使用する。」という指定。
.mp4などの動画ファイルは、映像ファイルと音声ファイルを格納するコンテナで、多くの場合は0番目に映像ファイル、1番目に音声ファイルが格納されている。
動画ファイルの中身を確認したい場合、以下コマンドで確認できる。

$ ffmpeg -i <input_movie>

-map 1
1番目に指定したファイル(ここでは<input_audio>)を使用する。」という指定。音声ファイルはコンテナではないので、-map 1:1のようにする必要はない。<input_audio>のところに.mp4コンテナなどを使用した場合には-map 1:1となる。

-vcodec copy -acodec copy
videoのコーデックとaudioのコーデックを指定します。それぞれcopyにすることで、再エンコードすることなく書き出しができます。コーデックを指定することで、音声・映像のコーデックを変更することも可能です。(ファイルサイズを小さくする時などに利用できます。もちろん画質・音質を損なうことにもなりますが。)
指定できるコーデックの文字列は、以下のコマンドで確認することができます。

 $ ffmpeg -codec

<output_file>
最後に、出力するファイル名を指定します。
ファイル名の拡張子にも注意が必要で、例えば.mp4というコンテナはpcm(.wav)音声を格納することができなかったりします。.mp4を使用したい場合は-acodecでaacを指定してあげるなどの工夫が必要です。(pcmを使いたい場合は.movを使用しましょう。)

動画をトリムする 1

開始地点と、切り出し長さの指定。

$ ffmpeg -ss 35 -i <input_movie> -t 60 -c copy <output_movie>

-ss 35, -t 60 : 35秒の地点から60秒間、動画をトリムします。

動画をトリムする 2

開始地点と終了地点の指定。

$ ffmpeg -ss 35 -i <input_movie> -to 95 -c copy <output_movie>

-ss 35, -to 95 : 35秒の地点から95秒の地点まで、動画をトリムします。

<ffmpegでの時間指定について>
ffmpegでは、以下の2種類の時間指定ができます。

[-][HH:]MM:SS[.m...]
[-]S+[.m...]

1つ目はHH:MM:SSで時間を指定する方法です。HH:は省略することができます。例えば01:23:45とすれば、開始から1時間23分45秒の地点を表します。
2つ目は秒数で時間を指定する方法。短い動画ではこちらの方が楽かもしれません。こちらは例えば、1234と指定すれば先頭から1234秒後の地点を表します。

2つの表記に共通して、ドット以下にミリ秒を指定することが可能です。また、先頭に-(マイナス)をつけるとマイナス時間を表します。

動画をトリムする 3

開始フレーム、終了フレームを指定する。

$ ffmpeg -i <input_video> -vf trim=start_frame=500:end_frame=1200,setpts=PTS-STARTPTS -an <output_file>

-vf trim=start_frame=500:end_frame=1200,setpts=PTS-STARTPTS :
500フレームから1200フレームまでを切り出します。

上記指定では音声は切り取れないので、-anオプションにて無音にする処理を加えている。(atrimという音声のサンプル数を指定して切り取るオプションも存在するが、動画と音声のサンプルレートが異なるため、しっかり計算しないと機能しません。)

動画から音声を取り出す

$ ffmpeg -i <input_video> -map 0:1 -acodec copy <output_file>

-map 0:1
動画から音声を取り出す場合は-map 0:1を指定します。(多くの動画コンテナの場合、0番目に映像、1番目に音声ファイルが格納されているため。)

-acodec copy
音声ファイルを再エンコードせずにそのままコピーします。

<output_file>
アウトプットのファイル名を指定します。適切な拡張子を付与してあげる必要があるので注意しましょう。
例えば、動画コンテナにaacの音声ファイルが入っていて、それを-acodec copyで取り出した際、拡張子を.m4a以外のものを指定するとエラーとなります。
事前にどういったフォーマットの音声ファイルが含まれているかを以下コマンドで確認する必要があります。

$ ffmpeg -i <input_video>

以上、ffmpegで動画の音声を差し替える方法についてでした。