avisynth小ネタ:StackHorizontal/StackVertical/LayerとMixAudio
えー、ほぼ似通ったシーン2つを、並べてつないだり、半透明にして重ねたりして、違いがはっきりわかるようにしたい、なーんてことがあっとします。…いや、あったんですってば。
avisynthでは、並べてつなぐのには、水平方向ならStackHorizontal()、垂直方向ならStackVertical()を使います。
たとえば…
StackHorizontal(clip_a, clip_b)
とか
StackVertical(clip_a, clip_b)
とします。
半透明にして重ねたいときは、Layer()を使います。
Layer()は他の重ね方もできる高機能な関数ですが、同じ大きさのビデオクリップを半透明で重ねるなら、
Layer(clip_a, clip_b,x=0,y=0,op="fast")
とするとお手軽です。
上記の3例では、clip_aとclip_bのクリップの長さが違う場合、長いほうのクリップの長さにあわせた映像になります。
…ここまではいい、ここまではいいんだ。
しかし、音声は、clip_a側の音声のみになります。
これがうれしい場合もあるでしょうが、両方の音声が聞こえないと困る場合もあると思います(今回はそうだった)
そこで、2つの音声を重ね合わせてミックスするMixAudio()を使い、ミックスした音声をAudioDub()でビデオクリップの音声として置き換えようとしてみます。
audio = MixAudio(clip_a, clip_b) AudioDub( Layer(clip_a, clip_b,x=0,y=0,op="fast"), audio)
…ここで問題発生。StackHorizontal(),StackVertical(),Layer()はすべて長さが長いほう基準で合成されたのに、MixAudio()は、なんと短いほう基準で合成されます。狙い通りの結果を得るためには、MixAudioする前に、短いほうの音声の末尾に無音区間を足して、クリップの長さを調整する必要があります。
そこで…BlankClip()関数(塗りつぶし&無音のクリップ作成)の出番です。次のようにしてみました。
clip_a2 = (FrameCount(clip_a)<FrameCount(clip_b)) ? \ (clip_a+BlankClip(length=FrameCount(clip_b)-FrameCount(clip_a)))) : (clip_a) clip_b2 = (FrameCount(clip_a)>FrameCount(clip_b)) ? \ (clip_b+BlankClip(length=FrameCount(clip_a)-FrameCount(clip_b)))) : (clip_a) audio = MixAudio(clip_a2,clip_b2,0.5,0.5) AudioDub( Layer(clip_a, clip_b,x=0,y=0,op="fast"), audio)
avisynthでは比較を三項式で行いますのでこのような形になりました。clip_aとclip_bのフレーム数を比較して、小さいほうにBlankClip()を追加、です。しかしこれではまだ×でした。
BlankClip()に映像や音声の設定をいっさいしないと、デフォルトの設定になるのですが、fps=24がデフォルトでした。今回使う映像はfps=30なのですが、誤差等もあり得るため、次のようにします。
clip_a2 = (FrameCount(clip_a)<FrameCount(clip_b)) ? \ (clip_a,clip_a+BlankClip(length=FrameCount(clip_b)-FrameCount(clip_a)))) : (clip_a) clip_b2 = (FrameCount(clip_a)>FrameCount(clip_b)) ? \ (clip_b,clip_b+BlankClip(length=FrameCount(clip_a)-FrameCount(clip_b)))) : (clip_a) audio = MixAudio(clip_a2,clip_b2,0.5,0.5) AudioDub( Layer(clip_a, clip_b,x=0,y=0,op="fast"), audio)
BlankClip()の第一引数に、設定を真似させたい動画を入れておきます。このようにすると、音声も長いほう基準で長さが決まるようになります。
これ、最後のがわからなくてかなり悩んでしまいましたので、メモを残しておきます。