「入力破損に強くする」「Iだけに寄せる」「レンジを明示して画を安定させる」をそのままPNG書き出し版に落とします。ポイントは、PNGは圧縮プリセットやCRFの世界じゃないので、代わりに「どのフレームを出すか」「色レンジ」「連番の吐き方」が主役になります。
推奨:Iフレーム(キーフレーム)だけをPNG連番で出力(レンジ明示+破損耐性込み)
ffmpeg -hide_banner -y \
-fflags +discardcorrupt \
-err_detect ignore_err \
-skip_frame nokey \
-i "data/input.mp4" \
-vf "unsharp=5:5:1.0:5:5:0.0,scale=in_range=full:out_range=tv,format=rgb24" \
-vsync 0 \
"output/iframe_%06d.png"
処理の要点
-
-skip_frame nokey:I以外をデコードしない方向に寄せて、参照欠落系エラーを踏みにくくする -
-fflags +discardcorrupt/-err_detect ignore_err:壊れたNALU/フレームを捨てつつ進む -
scale=in_range=full:out_range=tv:フルレンジ入力を明示的に扱って、濃淡の事故を避ける -
format=rgb24:PNGはRGBで保存するのが安定(特にOCR前処理で扱いやすい) -
-vsync 0:フレーム複製/間引きをしない(抽出した分だけ吐く)
代替:skip_frame が取りこぼす場合の保険(select方式)
コンテナのkeyframeフラグが怪しいと -skip_frame nokey が想定より出ないことがある。その場合は、あなたが最初にやってた方式に戻して「I判定はデコーダ後」にします(ログエラーは増えうるが、取りこぼしにくい)。
ffmpeg -hide_banner -y \
-fflags +discardcorrupt \
-err_detect ignore_err \
-i "data/input.mp4" \
-vf "select='eq(pict_type\,I)',unsharp=5:5:1.0:5:5:0.0,scale=in_range=full:out_range=tv,format=rgb24" \
-vsync 0 \
"output/iframe_%06d.png"
OCR向け
グレースケールに寄せたい場合、format=gray(もしくは format=gray,format=rgb24 は不要)に変える:
-vf "...,scale=in_range=full:out_range=tv,format=gray"