signalstatsとは

signalstats は、映像を解析する FFmpeg のフィルタです。フレームごとに、明るさ(輝度、Y)と色の成分(色差、Cb/Cr)の統計値を計算し、フレームメタデータ(フレームに付く付加情報)として記録します。

主な用途は次のとおりです。

  • 放送用の映像の品質チェック(QC)
  • クリッピング(輝度が 0 や 255 に張り付いている部分)の検出
  • 映像全体のノイズの量の分析
  • フレームごとの明るさの変化の確認

取得できる統計情報

統計名 説明
YMIN 輝度の最小値(0〜255)
YMAX 輝度の最大値(0〜255)
YAVG 輝度の平均値
YDIF 前のフレームとの輝度の差の平均
UMIN/UMAX/UAVG Cb(青色差)成分
VMIN/VMAX/VAVG Cr(赤色差)成分
SATMIN/SATMAX/SATAVG 彩度
HUEMED/HUEAVG 色相の中央値・平均値
TOUT 時間方向の外れ値ピクセルの指標
VREP 垂直ライン反復(VHS等のアーティファクト検出)
BRNG 放送範囲外のピクセルの指標

基本的な使い方

metadata=mode=print をつなげると、統計値がターミナル(標準エラー出力)に表示されます。

ffmpeg -i input.mp4 -vf "signalstats,metadata=mode=print" -f null /dev/null

表示の例です。

[Parsed_metadata_1 @ ...] lavfi.signalstats.YMIN=16
[Parsed_metadata_1 @ ...] lavfi.signalstats.YMAX=235
[Parsed_metadata_1 @ ...] lavfi.signalstats.YAVG=118.2

フレームメタデータとして取得する

signalstats の値(フレームメタデータ)を、metadata フィルタでファイルに書き出す方法です。

ffmpeg -i input.mp4 -vf signalstats=stat=tout+vrep+brng,metadata=mode=print:file=stats.txt -f null /dev/null

フレームごとの統計値が stats.txt に書き出されます。

CSV形式で出力してグラフ化

ffprobe -f lavfi -i "movie=input.mp4,signalstats" \
  -show_frames -select_streams v \
  -print_format csv \
  -show_entries frame_tags=lavfi.signalstats.YAVG,lavfi.signalstats.YMIN,lavfi.signalstats.YMAX \
  > signalstats_output.csv

できた CSV は、Excel や Python でグラフにできます。

輝度平均をリアルタイムにオーバーレイ表示

drawtext と組み合わせると、統計値を各フレームに重ねて、動画に書き込めます。

ffmpeg -i input.mp4 \
  -vf "signalstats,drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='YAVG\: %{metadata\:lavfi.signalstats.YAVG}':x=10:y=10:fontsize=20:fontcolor=white" \
  output_stats.mp4

TOUT・VREP・BRNG を追加する(stat オプション)

ffmpeg -i input.mp4 \
  -vf "signalstats=stat=tout+vrep+brng,metadata=mode=print" \
  -f null /dev/null
stat 値 追加される統計
tout TOUT(時間方向の外れ値ピクセルの割合)
vrep VREP(垂直ライン反復)
brng BRNG(放送範囲外ピクセル)

複数を指定するときは + でつなぎます。

放送品質チェックの実用例

放送用の映像では、輝度が16未満や235を超えるフレームがないかをよく確認します。そのために、各フレームの YMIN と YMAX を一覧にします。

ffprobe -f lavfi \
  -i "movie=input.mp4,signalstats" \
  -show_frames -select_streams v \
  -print_format flat \
  -show_entries frame_tags=lavfi.signalstats.YMIN,lavfi.signalstats.YMAX \
  2>/dev/null | grep -E "(YMIN|YMAX)"

YAVG推移をテキストファイルに保存する

フレームごとの輝度の平均値(YAVG)だけを、テキストファイルに記録します。

ffmpeg -i input.mp4 \
  -vf "signalstats,metadata=mode=print:key=lavfi.signalstats.YAVG:file=yavg.txt" \
  -f null /dev/null

よくある使い方まとめ

目的 コマンド
全統計を標準エラー出力 -vf "signalstats,metadata=mode=print" -f null /dev/null
TOUT/BRNG も出力 -vf "signalstats=stat=tout+brng,metadata=mode=print" -f null /dev/null
フレームにオーバーレイ signalstats,drawtext=text='%{metadata\:...}'
CSVで保存 ffprobe -f lavfi -i "movie=input.mp4,signalstats" ...

実測: 処理時間とサイズ

次のコマンドの処理時間を測りました。

ffprobe -f lavfi -i "movie=input.mp4,signalstats" -show_frames -select_streams v -print_format csv -show_entries frame_tags=lavfi.signalstats.YAVG
項目 実測値
処理時間 29.56 秒
実時間比 4.06 倍速
出力ファイル なし(解析のみ)

計測環境は Intel Core i9-14900KF(32スレッド)、FFmpeg 8.1 (gyan.dev) です。素材は 1920x1080 / 30fps / 120秒 / 351.4 MB(Big Buck Bunny をループしたもの、CC BY 3.0)で、2026-09-05 に計測しました。生データはデータセットにあります。

なぜこの時間になるのか

再エンコードをしなくても、処理は軽くありません。同じ素材を libx264(-crf 23 -preset medium)で丸ごと再エンコードすると 27.97 秒でした。signalstats の解析は、1フレームも書き出さないのに 29.56 秒かかり、再エンコードより長くなりました。

時間の大半は、デコード(圧縮された映像を1枚ずつの画像に戻す処理)ではなく、統計の計算にかかっています。同じ素材で、ストリームをコピーするだけの操作は 0.41 秒(ストリームのマッピング)と 0.49 秒(moov atom の移動)で終わりました。-c copy はフレームをまったくデコードしないからです。すべてのフレームをデコードする scdet(シーン検出)でも、7.09 秒で終わりました。signalstats は、すべてのフレームをデコードしたうえで、画素ごとに輝度や色の統計を計算します。デコードにかかるのは長くても 7 秒ほどで、残りの 20 秒あまりはこの計算です。x264 のエンコードがなくても、デコードと統計の計算は残るので、かかる時間は再エンコードと同じくらいになります。

signalstats にかかる時間は、素材を最後までデコードする時間よりずっと長く見積もってください。4.06 倍速という値は、デコードと統計の計算を合わせた速さです。素材の長さが2倍になれば、時間もおおむね2倍になります。

この計測では -show_entries frame_tags=lavfi.signalstats.YAVG の1項目だけを出し、CSV はファイルに保存せず画面(標準出力)に出しています。そのため出力ファイルはありません。10bit や 4K の素材では、デコードが重くなるぶん時間が延びます。4K では、統計を計算する画素の数も 4 倍になります。

つまずきやすいポイント

  • 症状: 値が何も表示されない。 原因: signalstats は値をフレームメタデータに記録するだけで、画面にもログにも出しません。対処: metadata=mode=print を必ず後ろにつなげます(例: -vf "signalstats,metadata=mode=print")。値は標準エラー出力に表示されます。映像のファイルが要らないときは、出力を -f null /dev/null にして捨てます。

  • 症状: Windows で 2>/dev/null がエラーになる。 原因: /dev/null は Linux や macOS で出力を捨てるための特別な場所で、Windows にはありません。-f null /dev/null のほうは、null 出力がファイルを開かないので Windows でも動きます。対処: cmd では 2>NUL、PowerShell では 2>$null を使います。metadata=...:file=stats.txt のようにファイルへ保存する方法なら、OS に関係なく動きます。

  • 症状: TOUT・VREP・BRNG が表示されない。 原因: これらは既定では計算されず、stat= で指定しないと出力されません。対処: signalstats=stat=tout+vrep+brng のように有効にします。複数を指定するときは + でつなぎます。

  • 症状: CSV の行数が思っていた数と違う。 原因: フレームレートや総フレーム数の見込みがずれています。対処: CSV は1フレームにつき1行なので、行数はほぼ総フレーム数(おおよそ 尺(秒) × fps)になります。2分・30fpsなら約3,600行です。

よくある質問

Q. signalstats は映像を再エンコードしますか。 A. 分析だけなら再エンコードしません。-f null で出力を捨てれば再エンコードは起きず、処理時間の大半は統計の計算にかかります。drawtext で値を映像に書き込むときだけ、再エンコードが必要です。

Q. クリッピング(白飛び・黒つぶれ)を検出したいです。 A. YMIN<16 や YMAX>235 で見つかるのは、放送用の範囲(8bit で 16〜235)からはみ出したフレームです。上の「放送品質チェックの実用例」のコマンドで、各フレームの値を一覧にできます。白飛び・黒つぶれは範囲の中でも起こるので、YMIN と YMAX だけでは判定できません。YHIGH(輝度の高いほうから1割の位置の値)が YMAX と同じなら、画面の1割以上が最大値に張り付いています。黒つぶれは YLOW と YMIN で同じように調べます。

Q. 値の単位や範囲は何ですか。 A. 8bit の映像では、Y・U・V とも 0〜255 です。10bit の素材では範囲が変わるので、しきい値も素材のビット深度に合わせて読み替えます。

Q. 特定の統計だけ軽く取りたいです。 A. stat= では軽くできません。YMIN や YAVG などの基本の統計は常にすべて計算され、stat= は TOUT・VREP・BRNG を追加で計算するので、指定すると計算は増えます。表示する値だけを絞りたいときは、metadata=mode=print:key=lavfi.signalstats.YAVG のようにキーを指定します。

Q. CSV をそのままグラフにできますか。 A. はい。-print_format csv で出力したファイルは、Excel や pandas(Python のデータ分析ライブラリ)で読み込めます。1列目は frame という文字で、フレームの情報(時刻や画像の形式など)の列が続き、最後に frame_tags の値が並びます。値の順番は指定した順ではなく、YMIN・YAVG・YMAX のようにフィルタが出す順です。行によっては、最後に付加情報(SEI)の列が付きます。

関連記事