blackdetect は、画面がほぼ真っ黒になっている区間を探すフィルタです。見つけた区間ごとに、始まりと終わりの時刻、長さを秒で表示します。シーンの区切りや CM の切れ目を探すときに使います。

基本コマンド

ffmpeg -i input.mp4 -vf blackdetect -f null /dev/null

黒い区間の時刻が、標準エラー出力(ターミナルに流れるログ)に表示されます。-f null /dev/null は、ファイルを書き出さずに解析だけをする指定です。

出力の読み方

[Parsed_blackdetect_0 @ 0x...] black_start:0 black_end:2.04 black_duration:2.04
[Parsed_blackdetect_0 @ 0x...] black_start:123.5 black_end:126 black_duration:2.5

1 行が 1 つの黒い区間です。

フィールド 説明
black_start 黒い区間が始まる時刻(秒)
black_end 黒い区間が終わる時刻(秒)
black_duration 黒い区間の長さ(秒)

パラメータの調整

デフォルト値

パラメータ デフォルト 説明
black_min_duration (d) 2.0 この秒数以上続いた黒い区間だけを表示する
picture_black_ratio_th (pic_th) 0.98 画面の98%以上が黒い画素(ピクセル)なら、黒いフレームとみなす
pixel_black_th (pix_th) 0.10 明るさ(黒を0、白を1とした値)がこの値以下の画素を、黒い画素とみなす

カスタム例:0.5秒以上の黒区間を検出

pic_th をデフォルトの 0.98 より小さくして、少しゆるく判定しています。

ffmpeg -i input.mp4 -vf "blackdetect=d=0.5:pic_th=0.95:pix_th=0.10" -f null /dev/null
  • d を小さくすると、短い黒い区間も拾います(CM の切れ目など)。
  • pic_th を小さくすると、黒以外の画素が少し混ざっていても黒いフレームとみなします。
  • pix_th を大きくすると、少し明るい画素も黒として数えます。そのため、やや明るいフレームも黒と判定されます。

応用例:テレビ録画のCM境界を検出

テレビ録画で、番組と CM の切れ目に黒い画面が入るときは、その黒い区間を探して切れ目を見つけられます。切れ目の黒い画面は短いこともあるので、d を小さくします。d=0.1 なら、0.1 秒(30fps で 3 フレーム)以上続く黒い区間を拾います。

ffmpeg -i recording.mp4 -vf "blackdetect=d=0.1:pix_th=0.10" -f null /dev/null 2>&1 | grep black_

grep black_ で、黒い区間の行だけを取り出しています。Windows のコマンドプロンプトでは、grep black_ の代わりに findstr black_ を使います。

出力をテキストファイルに保存

ffmpeg -i input.mp4 -vf blackdetect -f null /dev/null 2>&1 | grep black_ > black_segments.txt

黒い区間の行だけが black_segments.txt に保存されます。

誤検出しやすいケース

blackdetect は、画面の暗さだけで機械的に判定します。そのため、次のような映像では狙いと違う結果になりがちです。

ケース 原因 対策
暗転演出(フェードイン・フェードアウト) 演出で暗くなった部分を区切りと判定してしまう pic_th を 0.99 まで上げる。d を長めにする(デフォルトの 2 秒より短くしない)
黒背景のテロップ 文字以外がほぼ真っ黒 pic_th を上げる(0.99)。テロップの部分を外したいときは、-ss/-to で調べる時間を絞る
レターボックス(上下の黒帯) 黒帯のせいで pic_th=0.5 程度でも引っかかる crop で本編の部分だけを切り出してから blackdetect をかける
H.264 固定QPの暗いシーン 圧縮ノイズで完全な黒にならない pix_th を 0.15〜0.20 に上げて、許容範囲を広げる

blackdetect と silencedetect の組み合わせ

画面が黒く、同時に音も消えている区間だけを拾うと、CM の切れ目やチャプターの区切りをより正確に見つけられます。silencedetect は、無音の区間を探すフィルタです。次の Python の例は、FFmpeg を1回実行して両方のフィルタの結果を読み取り、無音と重なる黒い区間だけを返します。

import re
import subprocess

def parse_blackdetect(log):
    return [(float(m.group(1)), float(m.group(2)))
            for m in re.finditer(r'black_start:([\d.]+).+?black_end:([\d.]+)', log)]

def parse_silencedetect(log):
    starts = [float(m.group(1)) for m in re.finditer(r'silence_start: ([\d.]+)', log)]
    ends = [float(m.group(1)) for m in re.finditer(r'silence_end: ([\d.]+)', log)]
    return list(zip(starts, ends))

def overlap(a, b):
    return max(a[0], b[0]) <= min(a[1], b[1])

def find_boundaries(video_path):
    log = subprocess.run(
        ['ffmpeg', '-i', video_path,
         '-vf', 'blackdetect=d=0.1:pic_th=0.99',
         '-af', 'silencedetect=n=-30dB:d=0.5',
         '-f', 'null', '/dev/null'],
        capture_output=True, text=True, check=False
    ).stderr
    blacks = parse_blackdetect(log)
    silences = parse_silencedetect(log)
    return [b for b in blacks if any(overlap(b, s) for s in silences)]

戻り値は、条件に合った黒い区間を(開始秒, 終了秒)の組で並べたリストです。

関連記事

よくある質問

blackdetect の閾値はどう設定する?

d=2:pix_th=0.10(2 秒以上続く区間を拾い、明るさが 0.10 以下の画素を黒とみなす。どちらもデフォルト値)では、2 秒以上続く黒い画面を拾えます。それより短い黒は、d を下げると拾えます。pix_th を 0.05 にすると、判定が厳しくなります。

見えてる黒フレームを blackdetect が見逃す

黒い部分が 2 秒より短い可能性があります。デフォルトの d=2 では、2 秒未満の黒い区間は表示されません。d を小さくしてください(たとえば d=0.1)。1 フレームだけの黒なら、d=0 にします。真っ黒ではなく、濃いグレーになっている可能性もあります。明るさが pix_th(デフォルト 0.10)を超える画素は黒と数えられないので、pix_th を 0.15 まで上げて、もう一度試してください。ロゴや字幕など、画面の一部だけが黒くないときは、pic_th を下げます。

黒フレームで自動分割するには?

スクリプトを書いて処理します。blackdetect の出力から黒い区間の時刻を読み取り、それをもとに -ss で範囲を決めて、区間ごとに ffmpeg -c copy で切り出します。-c copy は再エンコードしない分、切れ目が直前のキーフレーム(単独で表示できるフレーム)の位置にずれることがあります。フレーム単位でぴったり切りたいときは、-c copy を外して再エンコードしてください。

シーン検出と blackdetect の関係は?

役割が一部重なります。select='gt(scene,0.4)' は、画面の大きな変化全般を拾います。blackdetect は、黒やほぼ黒の画面が続く区間だけを狙います。チャプターの境目に黒いフェードが入る映像なら、blackdetect の方が確実です。

静止画にも使える?

d=0 を付ければ使えます。画像 1 枚だと黒い区間の長さが 0 秒になるので、デフォルトの d=2 では何も表示されません。黒い画像なら、ffmpeg -i image.png -vf blackdetect=d=0 -f null /dev/null で black_start:0 black_end:0 black_duration:0 と表示されます。