フィルタグラフとは

フィルタグラフは、フィルタ(映像や音声を加工する部品)をつないだ処理の流れです。映像や音声のフレームがフィルタからフィルタへ順に流れ、それぞれのフィルタで加工されます。

入力 → [scale] → [overlay] → 出力
           ↑
         [logo入力]

入力も出力も1つだけの単純な処理は、-vf(映像)か -af(音声)で指定します。入力や出力が複数あるときや、別々の処理を並べるときは、-filter_complex を使います。

シンプルフィルタ:-vf と -af

映像フィルタ(-vf)

ffmpeg -i input.mp4 -vf "scale=1280:720" output.mp4
ffmpeg -i input.mp4 -vf "scale=1280:720,fps=30" output.mp4

複数のフィルタを , でつなぐと、左から順に処理されます。これをフィルタチェーンと呼びます。

音声フィルタ(-af)

ffmpeg -i input.mp4 -af "volume=2.0" output.mp4

フィルタチェーンの区切り文字

記号 意味
, 同一チェーン内で次のフィルタへ(前フィルタの出力が次の入力)
; 別のフィルタチェーンを開始(並列チェーン)

-filter_complex の基本

-filter_complex では、[name] の形の名前(ラベル)でストリームを区別します。

スケールして特定の出力ラベルにバインド

ffmpeg -i input.mp4 -filter_complex "[0:v]scale=640:360[v]" -map "[v]" -map 0:a output.mp4
  • [0:v]:入力0(1つ目のファイル)の映像ストリーム
  • scale=640:360:大きさを 640x360 に変えるフィルタ
  • [v]:出力に付けるラベル(名前は自由)
  • -map "[v]":ラベル [v] の映像を出力ファイルに入れる

複数フィルタのチェーン

ffmpeg -i input.mp4 -filter_complex "[0:v]scale=1280:720,fps=30[v]" -map "[v]" -map 0:a -c:a copy output.mp4

ウォーターマーク(画像オーバーレイ)

入力を2つ使う overlay フィルタの例です。

ffmpeg -i input.mp4 -i logo.png \
  -filter_complex "[0:v][1:v]overlay=10:10[v]" \
  -map "[v]" -map 0:a -c:a copy output.mp4
  • [0:v]:背景になる映像
  • [1:v]:ロゴの画像
  • overlay=10:10:左上から (10,10) の位置に重ねる

複数出力の作成(サムネイルと本編を同時生成)

ffmpeg -i input.mp4 \
  -filter_complex "[0:v]scale=1280:720[main];[0:v]scale=320:180[thumb]" \
  -map "[main]" -c:v libx264 -crf 23 main.mp4 \
  -map "[thumb]" -c:v libx264 -crf 28 thumb.mp4

1つの入力から、2つのファイルを同時に書き出します。

音声と映像を同時に処理する

映像の大きさの変更と、音量の調整を同時に行う例です。

ffmpeg -i input.mp4 \
  -filter_complex "[0:v]scale=1280:720[v];[0:a]volume=1.5[a]" \
  -map "[v]" -map "[a]" -c:v libx264 -crf 23 output.mp4

amix で複数音声を合成する

BGM と元の音声を混ぜる例です。

ffmpeg -i main.mp4 -i bgm.mp3 \
  -filter_complex "[0:a][1:a]amix=inputs=2:duration=first:dropout_transition=2[a]" \
  -map 0:v -map "[a]" -c:v copy output.mp4

split でストリームを分岐させる

1つの映像を2つに分けて、それぞれ別に処理する例です。

ffmpeg -i input.mp4 \
  -filter_complex "[0:v]split[v1][v2];[v1]scale=1280:720[main];[v2]scale=320:180[preview]" \
  -map "[main]" -c:v libx264 -crf 23 main.mp4 \
  -map "[preview]" -c:v libx264 -crf 30 preview.mp4

よくあるエラーと対処法

Filter 'split' has output 1 (b) unconnected

-filter_complex で名前を付けた出力(この例では [b])を、どの -map でも指定していないときに出ます。名前を付けた出力は、-map "[b]" のように必ずどれかの出力ファイルに割り当ててください。

Simple and complex filtering cannot be used together for the same stream

-filter_complex から出てきた映像や音声に、さらに -vf や -af をかけることはできません。フィルタはすべて -filter_complex の中にまとめてください。

実測: 処理時間とサイズ

1080p の動画1本から、本編用の 720p とプレビュー用の 360p を同時に書き出して計測しました。計測したコマンドは次のとおりです。

ffmpeg -i input.mp4 -filter_complex "[0:v]split=2[v1][v2];[v1]scale=1280:720[main];[v2]scale=640:360[preview]" -map "[main]" -c:v libx264 -crf 23 -an main.mp4 -map "[preview]" -c:v libx264 -crf 28 -an preview.mp4
項目 実測値
処理時間 17.52 秒(6.85倍速)
出力サイズ 41.14 MB

出力サイズの 41.14 MB は、720p の main.mp4 の大きさです。360p のプレビューも同じ処理の中で書き出していますが、この数字には含めていません。

計測環境: 1920x1080 / 30fps / 120秒 / 351.4 MB の素材(Big Buck Bunny をループ、CC BY 3.0)、Core i9-14900KF(32スレッド)、FFmpeg 8.1(gyan.dev)、2026-09-05、各コマンドを1つずつ順に実行。元データはデータセットで公開しています。

この数字になる理由

出力を2本にしても、処理時間は 720p を1本だけ出すときとほぼ同じでした。同じ素材を 720p に縮小するだけのコマンドは 18.43 秒、split で 720p と 360p を同時に出したこのコマンドは 17.52 秒です。

これは、この処理にかかる時間の大部分が、デコードではなく、エンコードする画素の数で決まるからです。split を使うと入力のデコードは1回で済み、増えるのは 640x360 の小さな映像をもう1本エンコードする分だけです。一方、1080p のままフィルタなしで再エンコードすると 27.97 秒かかりました。解像度を下げてから再エンコードするほうが、下げずに再エンコードするより速く終わります。

ただし、フィルタを使うと必ず再エンコードになります。同じ計測環境で映像を再エンコードしない操作は、ストリームの入れ替えが 0.41 秒、moov atom の移動が 0.49 秒、映像はコピーのまま音声だけを再エンコードする音声フェードが 1.03 秒でした。フィルタを1つでも使うと、今回の例では 17.52 秒かかります。分割や縮小が本当に必要か、コンテナの操作だけで済まないかを、先に確かめてください。

つまずきやすいポイント

  • , と ; を取り違えて、フィルタがつながらない。 , は同じチェーンの中で次のフィルタにつなぐ記号で、; は別のチェーンを始める記号です。1本のストリームを順に処理するなら ,、ラベルで分けたりまとめたりするなら ; を使います。例:scale=...,fps=... は順につながった処理、[0:v]...[v];[0:a]...[a] は別々に並んだ処理です。

  • Output with label 'x' does not exist というエラーが出る。 -map "[x]" で指定したラベルが -filter_complex の中にないか、名前が合っていないか、同じラベルをすでに別の -map で使っています。ラベル名は、大文字と小文字まで同じにします。

  • グラフの中で付けたラベルを2回使うと、片方の出力が加工されないままになる。 [v1] のようにグラフの中で付けたラベルは、一度しか使えません。FFmpeg 8.1 では、2回目に使ってもエラーは出ず、そこには1つ目の入力ファイルの映像や音声が加工なしで入ります。[v1] のようなラベルの場合、FFmpeg 6.1 では matches no streams のエラーで止まります。同じ映像を何度も使うときは、split(映像)や asplit(音声)で複製し、別のラベルに分けます。上の split の例を見てください。[0:v] のような入力ファイルの指定は、何度使ってもかまいません。

  • 同じストリームに -filter_complex と -vf の両方を使ってエラーになる。 1つのストリームに両方はかけられません(別々のストリームなら、一緒に使えます)。そのストリームのフィルタは、すべて -filter_complex の中にまとめます。

よくある質問

Q. -vf と -filter_complex はいつ使い分けますか。 A. 入力も出力も1つの単純な処理なら、-vf(音声は -af)で足ります。入力が複数あるとき(重ねる、混ぜる)、出力が複数あるとき、途中で分けたりまとめたりするときは、-filter_complex を使います。

Q. ラベル名に決まりはありますか。 A. [v] や [main] など、英数字で自由に付けられます。[thumb] のように役割がわかる名前にすると、読みやすくなります。入力ファイルのストリームは、[0:v] や [1:a] のように「入力番号:種類」で指定します。

Q. 1回のデコードで複数出力を作れますか。 A. できます。split でストリームを複製し、それぞれを別の -map で別のファイルに出力します。入力のデコードは1回で済み、同じファイルを何度も読まずに済みます。

Q. 音声と映像を同時に処理できますか。 A. できます。[0:v]...[v];[0:a]...[a] のように別々のチェーンで処理し、-map "[v]" -map "[a]" で両方を出力に入れます。

Q. フィルタの順序は結果に影響しますか。 A. します。たとえば crop を scale の前に入れるか後に入れるかで、結果が変わります。, でつないだフィルタは左から順にかかるので、やりたい順に並べてください。

関連記事