🔙

FFmpeg入門

TL;DR

ffmpeg -i input.mkv -vcodec libx265 -acodec libopus output.mkv #エンコード
ffmpeg -encoders #搭載されているエンコーダ一覧表示
-crf,-preset #エンコーダーに与える指示 前者は整数値で品質、後者はエンコード時間と圧縮率の調整。
-b:v,-b:a #それぞれ動画/音声のビットレート指定
-s #画面サイズ指定
-r #フレームレート指定
-ss -to #時間指定。-iの前に置くのがよい
-i "concat:input1.mkv|input2.mkv|input3.mkv…|inputn.mkv" #動画の結合
-vf reverse -af areverse #逆再生
-vf setpts=2*PTS -af asetpts=2*PTS #2倍速

コーデックはx265とOpusが現実的なエンコード速度で最高効率。mp3とか時代遅れのやつ使うはそろそろ止めにしましょう。

あとFFmpegで出来ないことを無理にFFmpegでやろうとしないこと。

(前提)FFmpegができること、できないこと

できること

  • 動画、音声のエンコード(トランスコード)
    • H.264/AVC -> H.265/HEVC
    • PCM -> AAC
  • 簡単な動画編集
    • 逆再生
    • スローモーション
    • 動画の分割、結合
    • 字幕の焼入れ

など結構幅広いことができる

できないこと(得意としないこと)

  • 複雑な動画編集
    • 出来ないこともないけど面倒。パソコンがあるのに膨大な計算を紙とペンでやるようなもの
  • 動画ダウンロード
    • 出来ないこともないけど(ry

FFmpegの使い方

FFmpeg Download : https://ffmpeg.org/download.html

FFmpeg Documentation : https://ffmpeg.org/documentation.html ←困ったらここを見ましょう…(ネット上の古い記事にはもはや使われていないオプションが散見される)

入出力

FFmpegは基本的にffmpeg -i hogehoge.mp4 -fuga fiz -piyo buz output.mp4のように指定して使う。

-iは入力ファイルを指定するオプションである(ほぼ必須)。必要に応じて複数使うことも可能。

基本的には全てのオプションの前に付ける。例外としてよくある例では後述する-ss,-toというシークオプションがある。これらは普通-iの前につけることが推奨されている1

-fuga,-piyoで示したのは各種オプションである。代表例にサイズ変更の-s、fps変更の-r、動画コーデック指定の-vcodec/-c:v 2、音声コーデック指定の-acodec/-c:a、利用するビデオフィルターを指定する-vfなど。

出力ファイルはただ書くだけ。拡張子に合わせたフォーマットで出力してくれる3

エンコード

ある動画input.mkvがあって、その形式を変換したい。

形式の基礎知識

まず、動画フォーマットの仕組みを軽く説明する。動画ファイルは基本的に3種類の規格を組み合わせてできている。

ちなみにコーデックとは、Encoder,Decoderの合成であり、フォーマットに従ってファイルを変換するソフトウェアを指す。

#### コンテナフォーマット

.aviとか、.movとか、.m2ts.mkvみたいなファイル形式の一番外側に出てくるフォーマット4。動画データと音声データ、加えてメタデータ(タイトルとかチャプターとか)を全部まとめて1ファイルにするための規格。

基本Matroska5使っとけばOKみたいな雰囲気はある。

動画フォーマット

MP46とかDvixとかH.264/AVCとかH.265/HEVC、AV1みたいな動画そのものをデジタルデータとして圧縮したり扱いやすくするための規格。

現状よく使われているのはほぼH.265/HEVC7 将来的な規格として有望視されているのはH.266/VVCとAV1

音声フォーマット

MP3とかAACとかOpusみたいな音声そのものをデジタルデータとして圧縮したり扱いやすくするための規格。

現状よく使われているのはMP3,AAC,FLAC8 普及していないものの優秀なものはOpusなど

実際にエンコードするには(CRF,VBR,2pass)

形式を変換したいというのはほぼほぼファイルサイズを削減したいという理由だと思う。

まずコマンド例を示す。

ffmpeg -i input.mkv -vcodec libx265 -acodec libopus output.mkv

-vcodec libx265はx265というコーデックで動画を変換せよ -acodec libopusはopusというコーデックで映像を変換せよ 最後のoutput.mkvは出力ファイルをoutput.mkvという名前で書き出せという指示であるが、FFmpegは.mkvからMatroska形式で出力せよという指示を自動で汲み取ってくれる。

これが現状で最も高圧縮かつ現実的な時間で実行できるコーデックの組み合わせだと思う。

さらに工夫を加えたコマンド例を以下に示す。

ffmpeg -i input.mkv -vcodec libx265 -preset slow -crf 17 -acodec libopus -ab 192k output.mkv

-preset slowはlibx265/libx264に対するコマンドで、エンコード速度を犠牲にする代わりに圧縮率を上げることができる。 -crf 17もエンコーダーに対するコマンドで、品質をcrf値9で指定する。17前後だとほぼほぼ視覚的な差はなくなる。x265でのデフォルト値は28。

-ab 192kはオーディオに対するビットレート指定である。

同様に、映像のエンコードにおいてもビットレートを指定してエンコードすることができる。

ffmpeg -i input.mkv -vcodec libx265 -b:v 7000k (省略)

このようにすると、エンコーダーは平均7000kbps,つまり7Mbps10でエンコードするよう努力するが、エンコーダーにとってはどこにビットレートを使うべきか、という配分がわからずあまり良い品質が得られない。

したがって、2-passエンコードという方法をとる。

ffmpeg -y -i input.mkv -vcodec libx265 -b:v 7000k -pass 1 -passlogfile LOG -an -f null NUL
ffmpeg -i input.mkv -vcodec libx265 -b:v 7000k -pass 2 -passlogfile LOG -acodec copy output.mkv

1つ目のコマンドでLOGというファイルにエンコードするために必要なデータを保存し、2つ目でそれを参考にしながら実際にエンコードを行う。

-passで何パス目なのかをエンコーダーに教える。 -anは音声を無視せよという指示。 -passlogfileは一時ファイルの名前を指定する。複数エンコードを同時にしたりしないのであれば指定する必要なし。 -fはフォーマットの指定(上書き)。1回目では何も出力しないためnull。

また、

ffmpeg -i input.mkv -c copy output.mkv
ffmpeg -i input.mkv -vcodec copy -acodec (適当なコーデック) output.mkv

といった形で、コーデックを指定するところでcopyを用いると単にデータをそのままコピーできる。

編集

リサイズ,フレームレート,シーク,結合

リサイズ

ffmpeg -i input.mkv -s 1280x720 ()

-sリサイズを行う。アスペクト比はそのまま残るので、例えば16:9の動画を4:3相当にしたいなら別途-aspectで指定してやる必要がある。

ちなみに-iの前に置くとサイズ情報を持たない特殊なビデオに対して画面サイズを指定するオプションとして扱われる。

フレームレート変換

ffmpeg -i input.mkv -r 24 ()

-rフレームレートを変える。フレーム補間はされず単に同じフレームを繰り返すかフレームを捨てることで変更される。

非整数の場合、できれば小数で指定するのではなく分数で指定するべきである。

ちなみに-iの前に置くと読み込む動画自体のタイムテーブルを変更して読み込む。

シーク

ffmpeg -ss hh:mm:ss.SSS -to hh:mm:ss.SSS -i ()
もしくは
ffmpeg -ss hh:mm:ss.SSS -t (継続時間)

-ssは開始時間、-toは終了時間、-tは継続時間を表す。

これもまた-iの前後で挙動が変わる。基本的には前においておけば良い。-vcodec copyの時は後ろに置いたほうがいいかもしれない

結合

ffmpeg -i "concat:input1.mkv|input2.mkv|input3.mkv…|inputn.mkv" -c copy output.mkv

ただし、全ての動画ファイルが同じ形式である場合のみ-c copyにより結合できる。

(応用)フィルタ

FFmpegにたくさんのビデオフィルタが内蔵されている。

ffmpeg -i input.mkv -vf "ほげほげ" ()

という形で利用できる。

ビデオフィルタには

  • transpose 回転

  • scale サイズ変更

  • yadif デインターレース

  • subtitile 字幕の描画

  • loop ループ動画の作成

  • reverse 逆再生(全動画を一度読み込んで変換するので重い)

  • format フォーマット指定(普通は使わない) 11

  • setpts 速度変更

    • setpts=[倍速数(小数可)]*PTSのようにする。e.g., setpts=2*PTS

など沢山の種類があり、複数のフィルタを,でつないで同時に利用することもできる。

字幕描画に関して例を上げると

ffmpeg -i input.mkv -vf "subtitle=sub.ass" output.mkv

のようにすれば字幕が映像そのものに描画された状態で出力される。

また、オーディオに対するフィルタも内蔵されており

ffmpeg -i input.wav -af areverse output.wav

のようにすると、オーディオが反転される。 各種フィルタに関しては公式ドキュメントを参照。

(応用)連番画像と動画の相互変換

ffmpeg -i input.mkv image%03d.png
ffmpeg -i image%03d.png -r 24 input.mkv #fpsを指定

%03dは"0"を3つ付けた連番。%04dなら4つになる。

(応用)多重化

先程から述べているように、一般的な動画ファイルは複数の動画、音声、字幕を一つのファイルに押し込んで出来ている。FFmpegを利用してそれらを取り出したり、複数ファイルから必要なものだけを拾って1つに再び押し込んだりというdemux/remux作業を行うことが出来る11

ffmpeg -i input.mkv output.wav #単に音声を抜き出すだけならこれでも可
ffmpeg -i input1.mkv -i input2.mkv -map 0:v -map 1:a output.mkv #1つ目の動画+2つ目の音声
ffmpeg -i input.mkv -map 0:v -map 0:m:language:jpn output.mkv #動画と日本語として扱われる全て
ffmpeg -i input.mkv -map -0:v output.mkv # -をつけると否定の意味になる

例えば-map 0:a:3とすると1つ目の入力の、3番目の音声がマップされる。

このmapオプション、非常に複雑なので公式Wikiを読むことを推奨する。

なお基本的にdemux/remuxを行う際は-c copyをつけることを推奨する。

まとめ

全てを網羅的に書くことは出来ていないが、初心者には役立つ内容に出来たと思う。
FFmpegはかなり万能ではあるが、操作が難しいこともありあまり使われていないように思える。

これをきっかけにFFmpegが少しでも普及したらよい。


参考文献

  1. FFmpeg Documentaiton (再掲)

  2. FFmpeg Bug Tracker and Wiki

  3. FFmpegでよく使う例、コーデックをまとめてみた(2021年版) - Qiita

  4. FFmpeg速習 - 昔書いたGist 本記事はこれを基に改稿。


  1. シークの挙動が変化する。ここ に詳しい解説があるが、基本的には入力ファイルをシークしてから処理する。 ↩︎

  2. 一部のshellでは:を特殊な文字として扱うためそれを避けた-vcodecも利用できる。-acodecやビットレート指定についても同様。 ↩︎

  3. 後述-fオプションでオーバーライド可能。 ↩︎

  4. 正確な表現ではない。 ↩︎

  5. マトリョーシカと読む。とにかく動画/音声フォーマットとの互換性が高い。 ↩︎

  6. .mp4のファイルがすべてmpeg4の動画コーデックを採用していないことに注意。MPEG-4は動画、音声、コンテナその他諸々のフォーマットや仕様を規定している。 ↩︎

  7. なのでH.265使っとけば間違いない。ただ、一部動画サイトはH.264しか受け付けなかったりするので注意。 ↩︎

  8. そろそろMP3使うのやめましょう。30年前の規格ですし。互換性の問題がないならAACかOpusに。 ↩︎

  9. libx264/libx265では0から51。6増えるとビットレートが倍になる(らしい)。 ↩︎

  10. 8b(ビット)=1B(バイト) ↩︎

  11. Multiplexing(多重化)→Muxingからdemuxで1ファイルをそれぞれ分割、remuxで複数ファイルから1つのファイルにまとめる。 ↩︎ ↩︎