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)の列が付きます。