フィールドオーダーが予め分かっている場合に、テキストファイルに正しいフィールドオーダーを記載することでどのインターレス解除フィルタよりも高速に逆テレシネ、プログレッシブ化できるfieldhint
フィルタの使い方。いわゆる逆テレシネフィルタである。
間引くフレームも分かるのでdecimate
フィルタではなくtrim
フィルタを使うことでより正確に処理ができる。フィールドを選択できるのがfieldhint
フィルタでフレームを選択するのがselect
フィルタ。固定周期なら一度の指定で済むが途中で周期が変わると ffmpeg だけでは場所の特定が難しい。weave
フィルタでフィールドをフレームに並べてshuffleframes
フィルタで一定周期のフレームを間引ける。
- ffmpeg でインターレース解除
- 指定フレーム毎に順番を入れ換える shuffleframes
- 2つの連続したフィールドを1つのフレームで出力する weave
- 特定の映像フレームや音声サンプルを出力する select, aselect
目次
基本コマンド
単純なプログレッシブ化
ffmpeg -i input -vf fieldhint=hint.txt:relative output
ffmpeg -i input -vf fieldhint=hint.txt:1 output
ffplay -i input -vf fieldhint=hint.txt:1
ntsc 29.976 フレームレートの動画をtrim
フィルタを併用して5フレーム中2フレーム目を間引く例(n は 0 スタート)。trim
フィルタで間引く場合はfps
フィルタで正しいフレームレートを指定しないと再び重複フレームが作られる
ffmpeg -i input -vf fieldhint=hint.txt:relative,select='mod(n-1,5)',fps=24000/1001 output
ffmpeg – remove sequentially duplicate frames – Stack Overflowよりtrim
フィルタを使わずにmpdecimate, decimate
フィルタを代わりに使う。
ffmpeg -i input -vf decimate output
ffmpeg -i input -vf mpdecimate,setpts=N/FRAME_RATE/TB output
公式ドキュメント:FFmpeg Filters Documentation : fieldhint
オプション
- hint[string]
フィールド指定ファイルを指定する。.txtや.csvファイルを使う
既定値はないので必ず指定する - mode[int]
フィールド指定ファイルのフレーム番号の指定方法 - 0, absolute:絶対フレーム番号指定。既定値
hintファイルの指定値:現在フレーム番号から前後1フレーム - 1, relative:相対フレーム番号指定
hintファイルの指定値:-1, 0, 1 - 2, pattern:相対フレーム番号指定で最終行まで進むと冒頭に戻ってループする。2022年3月15日に追加
hintファイルの指定値:-1, 0, 1
hintファイルの書き方
出力フレーム数が hintファイルのフレーム数に収まっていないとエラーになるので余裕を持って記入しておく。2つの数字を指定した後に+,–を指定することで+ならインターレス、–ならプログレッシブのフラグを立てられるがつけなくてもよい。2つの数字でトップフィールドファーストなら最初の数字がトップフィールド、カンマをつけて、次の数字がボトムフィールドになる。片方の数値を書かない場合は1フィールドで1フレームを出力する(用途不明)。また行頭に#,;でコメントを記入できる。
既定値はabsolute(絶対フレーム数)だが hintファイルはrelative(相対フレーム数)のほうが書きやすい。また、最初から最後まで縞が出る間隔が変わらないならpattern、途中で変わりその場所を特定できるならabsoluteが書きやすい。
relative向けの hintファイルの例。該当フィールドで0ならそのフィールドに、-1 なら1つ前のフィールドに、1なら1つ先のフィールドを出力する
pattern向けの hintファイルの例。
absolute向けの hintファイルの例
重複フレームと trim の関係
あるのかどうかは知らないが間引く最初の1フレームだけインターレースの場合は、片フィールドしかないのでフィールドをずらさずに先にカットtrim=start_frame=1
する。ffmpeg のログ出力は 0フレームスタートだが、1フレームスタートの方が感覚的にわかりやすい。映像がすでにプログレッシブで重複フレームがある場合は、間引くフレームの該当フレームを調べる。ボトムフィールドは相対値で表している。
ffmpeg で時間単位やフレーム単位でカットする方法
trim フィルタの使い方
23プルダウンや32プルダウンは以下を参照。
エンコ入門 – 第2回 プルダウン – エンコ
0フレームスタートの例。
ボトムフィールド | 縞フレーム | trimコマンド | 間引くフレーム | 備考 |
00-1-1000-1-10 | 2378 | mod(n-2,5) | 27 | 23プルダウン |
0-1-1000-1-100 | 1267 | mod(n-1,5) | 16 | 32プルダウン |
-1-1000-1-1000 | 0156 | mod(n,5) | 05 | |
-1000-1-1000-1 | 04590 | mod(n-4,5) | 49 | |
000-1-1000-1-1 | 3489 | mod(n-3,5) | 38 |
1フレームスタートの例
ボトムフィールド | 縞フレーム | trimコマンド | 間引くフレーム | 備考 |
00-1-1000-1-10 | 3489 | mod(n-2,5) | 38 | 23プルダウン |
0-1-1000-1-100 | 2378 | mod(n-1,5) | 27 | 32プルダウン |
-1-1000-1-1000 | 2367 | mod(n,5) | 16 | |
-1000-1-1000-1 | 1560 | mod(n-4,5) | 50 | |
000-1-1000-1-1 | 4590 | mod(n-3,5) | 49 |
patternモードとshuffleframesフィルタの関係
23プルダウンで2番目の重複フレームを間引く。
fieldhint | 0,0 0,0 0,-1 0,-1 0,0 |
0,0 0,-1 0,-1 0,0 0,0 |
0,-1 0,-1 0,0 0,0 0,0 |
0,-1 0,0 0,0 0,0 0,-1 |
shuffleframes | 0 1 -1 3 4 | 0 -1 2 3 4 | -1 1 2 3 4 | 0 1 2 3 -1 |
重複フレーム | 1, 2 | 0, 1 | 4, 0 | 3, 4 |
運用例
idet
フィルタのrepeated.current_frameでneither,neither,top,neither,bottomが来る最初のフレーム番号から1を引いた値をtrim
フィルタの開始フレームに指定する。フレーム番号はメモ帳以外のエディタでよく見られる行番号を参考にするか、lavfi.idet.repeated.neitherを参考にする。コマーシャル含めて一括でフィルタを当てると途中で縞の場所が変わってプログレッシブ化に失敗するパートがでることもある。
通常ならこのコマンドのログを見比べる。
ffprobe -v error -f lavfi -i movie=input.ts,idet -select_streams v:0 -show_entries packet=pts_time -show_entries packet_tags=lavfi.idet.repeated.current_frame,lavfi.idet.repeated.neither -of csv > output.csv ffprobe -v error -f lavfi -i movie=input.ts,idet -select_streams v:0 -show_entries packet=pts_time -show_entries packet_tags=lavfi.idet.repeated.current_frame,lavfi.idet.repeated.neither -of json > output.json
音声の開始サンプルはmediainfoの音声遅延(Delay relative to video)を調べて、例えば、48kHzで音声遅延が-362msでtrim
フィルタの開始フレームが354の30/1.001fpsの場合、
サンプルレート*(遅延の正負逆の値+trimのフレーム数/(動画のフレームレート)) 48000*(0.362+354/(30/1.001))
インターレース解除はfieldhint
フィルタで23プルダウンして、trim
フィルタで間引く。mediainfo の遅延は ffmpeg では計算方法が見つかっていない。
ffmpeg -i input.ts -vf trim=start_frame=353,setpts=PTS-STARTPTS,fieldhint=23.csv:1,select='mod(n-2,5)',fps=24000/1001 -af atrim=start_sample=584342,asetpts=PTS-STARTPTS -c:v libx264 -c:a aac -sn output.mp4
patternの利用例。pattern.txtの行をずらしながらshuffleframes
フィルタの間引くフィルタを指定するとうまく処理できる。-rで出力フレーム数を指定しないと改めて元のフレームレートで重複フレームが挿入される。
ffmpeg -i input.ts -vf "setpts=PTS-STARTPTS,fieldhint=pattern.txt:pattern,shuffleframes=-1 1 2 3 4" -r 24000/1001 -c:v hevc_nvenc -c:a aac -sn output.mp4
patternで5通りのファイルを容易に比較できるので数十秒比較してSingle frame detection Progressiveの一番大きな値のrelative.txtがおそらく正解。
ffmpeg -i input.ts -vf setpts=PTS-STARTPTS,fieldhint=pattern0.txt:pattern,idet -an -t 30 -f null - ffmpeg -i input.ts -vf setpts=PTS-STARTPTS,fieldhint=pattern1.txt:pattern,idet -an -t 30 -f null - ffmpeg -i input.ts -vf setpts=PTS-STARTPTS,fieldhint=pattern2.txt:pattern,idet -an -t 30 -f null - ffmpeg -i input.ts -vf setpts=PTS-STARTPTS,fieldhint=pattern3.txt:pattern,idet -an -t 30 -f null - ffmpeg -i input.ts -vf setpts=PTS-STARTPTS,fieldhint=pattern4.txt:pattern,idet -an -t 30 -f null -
- movie, amovie 入力の設定内容
- ffmpeg でのフレームレート設定の違い
- フレームがインターレースかどうかを調べる idet
- 連続フレームの差分をブレンドする tblend
- 複数の映像を1つの映像に合わせるinterleave
- Raspberry Pi 4 Model Bの64bit OSでインタレ解除してHWエンコードする
重複フレームをブレンドする
重複フレームをtblend
フィルタで平均して2番目のフレームを間引く。
ffmpeg -i input.ts -vf "setpts=PTS-STARTPTS,fieldhint=pattern.txt:pattern,split[1],shuffleframes=0 -1 -1 3 4[0];[1]tblend=all_mode=average,shuffleframes=-1 1 -1 -1 -1,[0]interleave" -r 24000/1001 -c:v hevc_nvenc -c:a aac -sn output.mp4
fieldhint | 0,0 0,0 0,-1 0,-1 0,0 |
0,0 0,-1 0,-1 0,0 0,0 |
0,-1 0,-1 0,0 0,0 0,0 |
0,-1 0,0 0,0 0,0 0,-1 |
shuffleframes | 0 -1 -1 3 4 | -1 -1 2 3 4 | -1 1 2 3 -1 | 0 1 2 -1 -1 |
tblend後のshuffleframes | -1 1 -1 -1 -1 | 0 -1 -1 -1 -1 | -1 -1 -1 -1 4 | -1 -1 -1 3 -1 |
重複フレーム | 1, 2 | 0, 1 | 4, 0 | 3, 4 |
AviSynthで複数の映像を使う場合。