AviSynthのぺーじ/関数を作る理由(1)

これは、かつて「にーやんのAviSynthのぺーじ」として公開されていたものを転載したものです。内容は古く、間違いも含まれている可能性があります。より正確で新しい情報を知りたい場合は、AviSynth 付属のヘルプや AviSynth 公式サイトを参考にすることをおすすめします。AviSynth WikiAviSynth入門なども活用してください。

スクリプトの汎用化

 関数をつくる理由の一つはスクリプトの汎用化です。

 AviSynthを繰り返し使用していると、しばしば複数のフィルタを同じ組み合わせで使用するケースに遭遇します。

 そういった時に、複数行に渡って引数を調整したりするのって、ちょっと面倒だと思いませんか?

 ダラダラと長いスクリプトも、ごちゃごちゃしていて見た目があまりよくないですよね。

 そこで、関連性のある複数のフィルタをひとまとめにして関数にしてしまおう、というのがスクリプトの汎用化です。

 一度関数化してしまえば、次からはフィルタを呼び出すのも一行、調整するのも一行、見た目もすっきりの一石三鳥です。

汎用化の一例 - FPNR関数

 たとえば、次のようなスクリプトがあります。

SeparateFields
Top = SelectEven
Bottom = SelectOdd
Top = Top.KenKunNRT(256,2,20)
Bottom = Bottom.KenKunNRT(256,2,20)
Interleave(Top, Bottom)
Weave

 これは実際に私がよく使うフィルタの組み合わせです(KenKunNRTは一例)。

 全部で7行。使用しているフィルタはSeparateFieldsSelectEvenSelectOddKenKunNRTInterleaveWeaveの6種類です。

 今回は関数の作成についての解説がメインですので、個々のフィルタについての詳しい説明は省略します(機会があればやります)が、簡単に図でまとめると下のようになります。

fpnr.png

 インターレースのビデオクリップに対して、フィールド単位で(インターレースを維持したまま)フィルタをかけるために、このように6種類ものフィルタを組み合わせて使用しています。

 何言ってるのかわからねーぞ!という人は、Tips内のインターレース・フィルタリング関連のページを参考にしてみてください。なぜ、こんな手間のかかることをするのかがわかると思います。

 それでもわからない人。あきらめないでください。

 とりあえず「何か長いスクリプトだし、まとめられるものなら、まとめた方がいいかもしれない」と思いませんか?それさえ、わかってもらえれば十分です。

 で、話を元に戻すと、このフィルタの組み合わせでは、赤で囲んだ部分(例ではKenKunNRT)は他のフィルタに置き換えることができます。

 言い換えれば、赤で囲んだ部分以外は、常に同じ組み合わせになります。

 このような時、しかもそれがよく使う組み合わせであるならば、関数にして汎用化するのに最適と言えるでしょう。

 実際に、上のスクリプトを関数にしたのが、下のFPNR関数です。

FPNR("KenKunNRT(256,2,20)")

#**** FPNR関数 ****#
function FPNR(clip clip, string "filter")
{
clip = clip.SeparateFields
Top = clip.SelectEven
Bottom = clip.SelectOdd
Top = Eval("Top." + filter)
Bottom = Eval("Bottom." + filter)
clip = Interleave(Top, Bottom)
clip = clip.Weave
return clip
}

 「ん?何だ、逆に長くなってるじゃん!」

 たしかにそうなんです・・・んが、でも、これで設定するのは一行目だけでよくなりました。

FPNR("KenKunNRT(256,2,20)")

 この一行目でFPNR関数を呼び出し、実行しています。

 外部プラグインがプラグインを呼び出して実行するのと同じような感じです。

 関数を無効にしたい時は、この行の先頭に#を付け加えるか、行ごと削除するだけでかまいませんし、カッコの中の引数を調整することで、フィルタの設定を変更することができます。

 FPNR関数の場合は、二重引用符(")で囲まれた部分(例ではKenKunNRT(256,2,20)が入っているところ)を別のフィルタに変えることができます(※)し、フィルタの引数を変更することもできます。

 関数は、まるでそのようなフィルタがあるかのように使用することができるのです。

 関数部分(functionから}まで)は基本的に固定ですので、特にいじらなくてOK。この関数を使用するしないに関わらず、ただスクリプト内の任意の位置にコピペしておけばいいんです。

 それでも関数部分が目障りだという場合は、関数部分だけをまとめて関数定義ファイルを作成し、外部からインポートすることもできます。

※ただし、すべてのフィルタが使えるわけではありません。

関数定義ファイルのインポート

 外部からインポートする関数定義ファイルは、関数部分をメモ帳に貼り付けて、適当な名前を付けて保存するだけで作成することができます。

function_avs.png

 上の図ではファイル名の拡張子が*.avsになっていますが、必ずしも*.avsである必要はありません。

 私が確認した範囲では、*.txt, *.log, *.datなどでもOKでした。

 また、*.avsiしてデフォルトのプラグインディレクトリに入れれば、オートローディング機能により自動的に読み込まれるようになります(AviSynth2.0.8/2.5.0以降)。

 外部ファイルをインポートするにはImportフィルタを使います。

 Importフィルタの書式は次の通りです。

Import(string "filename")

 string型ですので、二重引用符(")で囲む形で外部ファイル(この場合、関数定義ファイル)の名前を指定します。

 外部ファイルがメインのスクリプト(関数を呼び出しているAVSファイル)と同じフォルダにある場合は、ファイル名だけでかまいませんが、メインのスクリプトと別のフォルダにある場合は、パスを指定してください。

 たとえばCドライブのAVSフォルダ内に関数定義ファイル(function.avs)がある場合は、次のように記述します。

Import("C:\AVS\function.avs")
FPNR("KenKunNRT(256,2,20)")

 どうですか?かなりすっきりしたでしょう。

 さらに関数定義ファイルの拡張子を*.avsiにしてデフォルトのプラグインディレクトリに入れた場合は、Importフィルタも必要ありません(オートローディングされるため)。

FPNR("KenKunNRT(256,2,20)")

 これならAviSynth内蔵フィルタと同じ感覚で使うことができますね。

 これが関数をつくる理由(メリット)の一つです。

 ところで、FPNR関数のつくり方が気になる方がいるかもしれません。

 しかしFPNR関数には、まだ紹介していないフィルタがいくつも使われていたり、複雑な部分があったりするので、ここで解説するのはやめておきます。

 関数のつくり方については、次回から少しずつ解説していくつもりです。

 それを読んでいただければ、あるいはFPNR関数がどういう仕組みになっているのかもわかってくるかもしれません。また機会があれば解説したいとも考えていますので、ご理解ください。

 さて、次回は「関数をつくる理由」のその2「フィルタのカスタマイズ」です。

 お楽しみに〜♪

最終更新日 2004年7月17日

最終更新日時: 2014-03-12 (水) 23:37:14 (1835d)