fieldhint
フィルタで手動インターレース解除しH.264のハードウェアエンコードする。手動インターレース解除するとぎりぎり1倍速以上出るので縞フレームの場所が分かればライブ配信にも使える。patternオプションは2022年3月15日に追加されたものなのでffmpegはソースコードからビルドする。
jc-kynesim/rpi-ffmpeg: FFmpeg work for RPI
手動でフィールド処理を行う fieldhint
日常ものならば-b:v 4M指定でもよいが、動きが多いと-b:v 4Mではノイズが多い。1920×1080も-b:v 6M程度は必要かも。フレームタイプのフラグがこのままだとインターレースのままなので、setparams
フィルタでプログレッシブに変更できる。
コマンドは重複フレームをブレンドする例。
ffmpeg -analyzeduration 10MB -probesize 10MB -i input.ts \ -vf "setpts=PTS-STARTPTS,fieldhint=pattern2.txt:pattern,split[1],\ shuffleframes=0 1 2 -1 -1[0];\ [1]tblend=all_mode=average,shuffleframes=-1 -1 -1 3 -1, [0]interleave,setparams=field_mode=prog" \ -r 24000/1001 -c:v h264_v4l2m2m -num_output_buffers 64 -num_capture_buffers 128 \ -b:v 4M -c:a copy -bsf:a aac_adtstoasc output.mp4
エンコーダでh264_v4l2m2mをつかうと、なぜか1440×1080の解像度で映像が乱れるのでリサイズしなければならないが、リサイズしてもまだ1倍速以上をキープしていた。
ffmpeg -analyzeduration 10MB -probesize 10MB -i input.ts \ -vf "setpts=PTS-STARTPTS,fieldhint=pattern2.txt:pattern,split[1],\ shuffleframes=0 1 2 -1 -1[0];[1]tblend=all_mode=average,shuffleframes=-1 -1 -1 3 -1,\ [0]interleave,scale=1280:720,setparams=field_mode=prog" \ -r 24000/1001 -c:v h264_v4l2m2m -num_output_buffers 64 -num_capture_buffers 128 \ -b:v 4M -c:a copy -bsf:a aac_adtstoasc output.mp4
separatefields、weave
フィルタで代用することもできる。手元で試すとbwdif、decimate
フィルタ併用よりフレーム数が少し少ないのが気になった。この原因はshuffleframes
が扱うフレーム数によるもので、10フレーム処理するならフィールド分離して2倍フレームになるので下一桁5の倍数フレームないと最後近辺のフレームが抜ける仕様になっている。
-vf "separatefields,shuffleframes=0 1 4 3 6 5 8 9 -1 -1,setfield=tff,weave,setpts=(N*1001)/(24000*TB),setparams=field_mode=prog" -r 24000/1001 -fps_mode cfr
フレーム抜けを抑えるためにtpad
フィルタで末尾フレームをコピーして増やす。
-vf "tpad=stop=2:stop_mode=1,separatefields,shuffleframes=0 1 4 3 6 5 8 9 -1 -1,setfield=tff,weave,setpts=(N*1001)/(24000*TB),setparams=field_mode=prog" -r 24000/1001 -fps_mode cfr
ffprobeでフレーム数を調べるにはすぐに終わるメタデータから調べる方法と、
ffprobe -v error -i input -select_streams v:0 -show_entries stream=nb_frames -of csv=p=0
時間のかかる全フレームデコードする方法がある。
ffprobe -v error -i input -select_streams v:0 -show_entries stream=nb_read_frames -count_frames -of csv=p=0