普通の人には役に立たないと思われる豆知識の紹介
タイトルだけでは何を言ってるかわかりにくいと思います。ということで図を用意しました
IIPPPのトップフィールドファースト(TFF)のソースです。DoubleWeave()した後はSelectEveryやPulldownを使って1、3 or 4、6、8 or 9の4フレームを選択すれば24pにできますよね
このときフレーム1はボトムフィールドにはソースのaのボトムフィールド、トップフィールドにはソースのbのトップフィールドが使われています。ボトムフィールドがトップフィールドより前のフレームのものを使っていることになるので、ボトムフィールドファースト(BFF)になるのです
3,5,7,9も同様にBFFということになります。2つのフレームからフィールドを選択してフレームを作る場合は、そのフレームのフィールドオーダーは元の逆になるのです
1 2 3 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) nnedi3(field=-1) |
こんなスクリプトがあったとします。クリップをAssumeTFF()を使ってTFFと定義しましたが、DoubleWeave().SelectEvery(10, 1, 4, 6, 8)の後は先頭の1がBFFなので、nnedi3にはBFFとして認識されてしまいます
3行目のnnedi3はfield=-1(自動選択/TFFなら1、BFFなら0になる)が指定されていますが、一度AssumeTFF()を使ったにも関わらず0として全フレーム動作してしまうのです
1 2 3 4 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) AssumeTFF() nnedi3(field=-1) |
このようにAssumeTFF()をしなおせばnnedi3のfieldは1として全フレーム動作します。逆テレシネの後にフィールドオーダーを読んで処理させる場合、おまじないのようにAssumeTFF()やBFF()をするのはこのためです
Pulldown()で考えるなら、(0,2)や(0,3)や(2,4)を実行した後はフィールドオーダーは変わらず、(1,3)や(1,4)の後はフィールドオーダーが逆転してしまう、となります
さて、逆転することがあるということと、逆転する原因はわかりました。では次にフィールドオーダーはクリップごとに保存されているのか、フレームごとに保存されているのかを考えてみます。まずこうやってみました
1 2 3 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) Subtitle(string(GetParity())) |
GetParity()はTFFならtrue、BFFならfalseを返します。こうしてみたところ、全フレームでfalseが表示されました。ということは全フレームBFFになっているからクリップごとに保存かな?と思えます
次にこうやってみました
1 2 3 4 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) ScriptClip(last, " Subtitle(string(fo)) ") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
0フレーム目では普通にGetParity()をした結果を表示する、1フレーム目では先頭0フレーム目を削除してからGetParity()をした結果を表示する、2フレーム目では先頭の0,1の2フレームを削除してからGetParity()をした結果を表示する・・・ということをしています
するとなんと、0フレーム目はfalse、1~3フレーム目はtrue、4フレーム目はfalse・・・が表示されたのです
次に
1 2 3 4 5 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) AssumeTFF() ScriptClip(last, " Subtitle(string(fo)) ") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
こうしてAssumeTFF()を間に挟んでみました。そうすると全フレームでtrueが表示されました
つまり
- フィールドオーダーを読んで処理できるもの(GetParityやnnedi3など)の一部はクリップの先頭のフレームのフィールドオーダーしか見ていないものがある
- フィールドオーダーはフレームごとに保存されている
- DoubleWeave()後の10フレームのうち、1,3,5,7,9番目の5フレームはフィールドオーダーが逆転する
- AssumeTFF()/BFF()は全フレームのフィールドオーダーを書き換える
こういうことになります。ちなみにSeparateFields()は毎フレームTFFかBFFか見て処理しているようです
また、
1 2 |
ConditionalFilter(last, hoge(), last, "fo", "=", "false") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
こんな風に書けば、2つのフレームからフィールドを取って作ったフレーム(DoubleWeave().SelectEvery(10,・・・)なら奇数を指定したフレーム)に対してのみhoge()が実行できる、ということにもなります
はい、役に立たない知識かもしれません。しかし、無理やり使おうと思えば使えなくもないかもしれません。2つのフレームからフィールドを選択して作ったフレームの特徴として
- 海外映画やドラマなどで、逆テレシネ前に字幕の縞がなかったソースの場合は、そのフレームにのみ字幕に縞が出る可能性がある
- そのフレームがシーンチェンジ直後か直前だったら画質の劣化が激しい
こういうことがあげられます
と、いうことで次のようなケースを考えてみました
1 2 3 4 5 6 7 8 9 |
v1 = Trim(0,5214).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v2 = Trim(5215,30774).AssumeTFF().DoubleWeave().SelectEvery(10,1,4,6,8) v3 = Trim(30779,43003).AssumeTFF().DoubleWeave().SelectEvery(10,0,2,4,7) v4 = Trim(43006,43905).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v1++v2++v3++v4 ConditionalFilter(last, AssumeTFF().CombReduce(last), last, "fo", "=", "false") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
CombReduce()は以前コメント欄で教えていただいた、字幕に縞が出た場合それだけ消す関数です。こう書けば、ソース次第では、縞が出る可能性のあるフレームにだけ関数を実行できて、結果は変わらないのに速度が稼げてしまう!
次に画質劣化に対処するケースを考えてみましょう
1 2 3 4 5 6 7 8 9 |
v1 = Trim(0,5214).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v2 = Trim(5215,30774).AssumeTFF().DoubleWeave().SelectEvery(10,1,4,6,8) v3 = Trim(30779,43003).AssumeTFF().DoubleWeave().SelectEvery(10,0,2,4,7) v4 = Trim(43006,43905).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v1++v2++v3++v4 ConditionalFilter(last, AssumeTFF().DecombUCF(last), last, "fo", "=", "false") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
DecombUCFはちょっとだけさんの、ノイズ量を計算して破綻したフレームの画質を修復するスクリプトです。このスクリプトでノイジーなフレームと判定されるのは大抵2フレームからフィールドを取って作ったフレームです(絶対にそうなるというわけではありませんが、全フレームそうなる場合もあります)
なのでこのようにしてしまえば結果は変わらない可能性も結構あるのに速度が稼げてしまう!
どちらも関数を適応するフレームを最大1/4まで減らせます!
と、無理やり考えれば活用できなくもないかもしれません
コメント
CombReduce関数について検索しても出てこなかったので某掲示板で聞いてしまったんですが、よろしければCombReduce関数を公開していただけませんか?
こんばんは。関数は紹介記事があったのですが、使ったSSがあまり良くなかったのでお蔵入りにしてしまってそのまま放置しちゃってました
いずれちゃんとした紹介記事を復活させたいですが、ひとまずこちらに書いておきます
オリジナルは私ではなく別の方で、私の方でかなり変えてしまってます
逆テレシネした後にに出る縞々な字幕を潰す関数です
必要なプラグインはmasktools2, combmask, nnedi3です(mode=1)
<使用例1>
# 逆テレシネ後に実行するだけ
# 縞判定をして、縞と判定されたら縞の部分を消そうとします
AssumeTFF().DoubleWeave().SelevtEvery(10, 1, 4, 6, 8)
CombReduce()
<使用例2>
# 縞なフレームのリストがすでにある場合
# 縞判定をスキップします
AssumeTFF().DoubleWeave().SelevtEvery(10, 1, 4, 6, 8)
ConditionalFilter( last, makeCombReduce( mode=1, mmode=2 ), last, “combed”, “=”, “true” )
ConditionalReader ( “xxxx.log”, “combed”, false)
——————————————————————————————-
https://quintrokk.subness.net/misc/combreduce.avsi
片フィールドの字幕を処理するためにTFMを使用していましたが、たまに字幕の切れ端が点々と残ったり、残像のように残ったりがあり、他に良い方法はないかと悩んでいました。
以前より検索でcombreduce.avsiが引っ掛かってはいましたが、リンクが切れており入手できずでしたが、気になっていました。
ふとドメイン変更したら良いことに気づき、無事見られて試したところ、上に書いたようなことが今のところ見られません。
boolcheckerとの組み合わせでリスト作成も容易です。
とても感動したので、このままリンクも切れたまま埋もれてしまって世の中に出ていないのが非常に勿体ないと思い、コメントさせていただきました。
7年前に記事にされようとしてそのままとなっているかと思いますが、是非改めて記事にしていただければと思います。
ご検討をお願いします。
コメントありがとうございます。ドメイン変更時にリンクを更新するプラグインを使って書き換えたつもりだったのですが、コメント欄には適用されなかったようです。助かりました
ひとまずリンクは更新しておきました。著作権的に問題なく、かつわかりやすい画像の素材の用意が難しいと思っていたので記事化は見送っていたのですが、今でも需要があるならちょっとがんばってみようかな…
リンク修正と返信ありがとうございます。
ドメイン変更されたのは2018年かと思いますが、それ以降、恐らく同様に入手できず仕舞いの人が多数いるかと思います。
これから再訪してコメント欄のURLが更新されたことに気付く人は恐らく少ないでしょうから、簡単な内容でも新しい記事としてアップしていただけると幸いです。
(前にこの記事のコメント欄でこんなスクリプトを紹介したけどリンク切れてたから修正したよ程度でも)
私的には、せっかくの良いスクリプトなので、別の内容の記事のおまけではなく、単体で紹介していただければと思います。