VapourSynth の基本

VapourSynth について
公式サイト: http://www.vapoursynth.com/

スクリプトを記述することで動画を処理します。
Linux で動画エンコードを行いたい場合、現状ではこれを使うのが一番適していると思います。

AviSynth の後継である AviSynth+ も、現在は Linux に対応していますが、Linux 上での動作においては VapourSynth の方が相性が良いので、こちらを使います。

VapourSynth は、スクリプト言語として Python3 を使用するのが特徴です。

ここでは、Linux 上で、VapourSynth を使って動画エンコードを行うための手順を解説しています。
VapourSynth のインストール
Arch Linux では、公式リポジトリの方で vapoursynth パッケージがあります。

Ubuntu など、公式リポジトリにパッケージがない場合は、VapourSynth のサイトにインストールの手順が書かれているので、そちらを参考にしてください。
音声の処理について
VapourSynth は現在音声のサポートも行っていますが、映像と音声はあくまで別々に扱う形となっているため、AviSynth のように、映像のフレームに合わせて同じ範囲の音声を切り出すといった処理は、デフォルトではできません。
(Damb プラグインを使えば擬似的に可能ではあります)

音声を読み込んだ後、内蔵の関数で音声を切り取りたい場合は、オーディオのサンプル単位で位置を指定する必要があるため、映像のフレーム単位で切り取る場合、自分でフレーム位置→サンプル位置の変換計算を行う必要があります。

ただ、映像のフレームレートさえわかっていれば、フレーム位置→サンプル位置の計算は行えるので、わざわざ VapourSynth 上で音声を処理しなくても、音声単体で切り取りを行うことができます。
プラグインについて
VapourSynth のプラグインは、Linux 上においては共有ライブラリ (*.so) となります。
プラグインの読み込み方法
プラグインは、以下のいずれかの方法で読み込めます。

  1. VapourSynth のプラグイン用ディレクトリにファイルを置いて、自動で読み込ませる。
  2. スクリプト内で LoadPlugin() を記述して、手動でプラグインを読み込む。

VapourSynth 指定のディレクトリにプラグインを置いておくと、そのディレクトリ上のすべてのプラグインが、スクリプト実行時に自動で読み込まれます。

常に使用するようなプラグインは、このディレクトリに置いておくと良いでしょう。
逆に、たまにしか使わないようなプラグインは、手動で読み込んだ方が良いです。
プラグインのディレクトリ
VapourSynth のプラグインのディレクトリは、「システム用」と「ユーザー用」の2つのディレクトリに分かれています。

システム用パッケージからインストールしたプラグインなどはここに置かれます。
VapourSynth を /usr にインストールした場合は、デフォルトで /usr/lib/vapoursynth
ユーザー用ユーザーが自分で用意したプラグインを置く場所です。
デフォルトで空なので、ユーザーが自分で指定する必要があります。

プラグインのディレクトリを指定したい場合は、VapourSynth の設定ファイルを作成します。
~/.config/vapoursynth ディレクトリを作成し、その中に vapoursynth.conf というテキストファイルを作って、以下の内容を記述します。

UserPluginDir=<ユーザー用のディレクトリパス>
SystemPluginDir=<システム用のディレクトリパス>

システム用のディレクトリを変更したくない場合は、SystemPluginDir の行は記述しないでください。
User → System の順でファイルが検索され、プラグインが読み込まれます。
必要なプラグインの用意
必要なプラグインはあらかじめ、パッケージからインストール、または、ソースコードからビルドしておきます。
公式サイトにプラグインの一覧があるので、それを参考にしてください。
動画の読み込みプラグイン
まず最初に、動画ファイルを読み込むためのプラグインが必要になります。

FFMS2
https://github.com/FFMS/ffms2

FFMS2 プラグインは、ffmpeg の libavformat などのライブラリを使って動画を読み込むため、大抵のファイルは読み込めます。
Arch Linux の場合は、公式リポジトリで ffms2 パッケージがあるので、それをインストールしてください。

savfsource
https://gitlab.com/azelpg/savfsource

FFMS2 (ver 2.40 時点) で WebM (VP9) の映像が正しく読み込めなかったので、自分で作りました。
FFMS2 と同じように ffmpeg のライブラリを使うため、大抵のファイルは読み込めますが、YUV の入力しか対応していない・画像のフォーマット変換を行わないなど、いくつか制約もあります。
H.264 なども含めて大体読み込めるとは思いますが、FFMS2 でうまく読み込めない動画がある場合に使ってみてください。
音声対応 (Damb)
https://github.com/dubhater/vapoursynth-damb

VapourSynth のスクリプト内で、映像と音声を同期させてカットしたい場合に使用できます。
ここの解説では、音声は別々に処理して切り取るので使用しませんが、スクリプト内で音声カットの処理をしたい場合は使ってください。

Arch Linux の場合、AUR に vapoursynth-plugin-damb-git があります。

ソースコードからビルドする場合は、以下のように実行します。
$ ./autogen.sh
$ ./configure
$ make

作成された libdamb.so ファイルを、プラグイン用のディレクトリにコピーしてください。
VapourSynth ビューアのインストール
スクリプトをプレビューして出力画像を確認したい場合や、カットするフレームの位置を確認したい場合は、VapourSynth スクリプトのエディタやビューアが別途必要になります。

vasviewer自作の簡易ビューア。X11
API4 のみ対応。
VapourSynth Editor 2エディタ+ビューア。Qt5
API4 に対応。
VapourSynth Editorエディタ+ビューア。Qt5
API3 を使っているので、最新の VapourSynth では画像が表示できません。

ソースコードからビルドする場合は、各ソフトの説明書を読んでください。

VapourSynth R55 から、API に ver 4 が加わりました。
VapourSynth R55 以降の環境で、API 3.x を使っているソフトを使用すると、正しく動作しない場合があります。
動作確認
動作に必要なものをインストールしたら、実際に VapourSynth が実行できる状態にあるか、確認してみます。
以下の内容を、test.vpy という名前でテキストファイルに保存してください。

import vapoursynth as vs
core = vs.core
print(core.version())

このスクリプトファイルを Python3 で実行させて、VapourSynth が正しく動作すれば、バージョン情報が表示されます。

$ python3 test.vpy

VapourSynth Video Processing Library
Copyright (c) 2012-2022 Fredrik Mellbin
Core R61
API R4.0
API R3.6
Options: -
スクリプトファイルを書く
一般的な VapourSynth スクリプトの書き方を説明します。

VapourSynth スクリプトの拡張子は、*.vpy にします。
中身は Python3 スクリプトなので、Python3 のスクリプトと同じように書いていきます。
サンプルスクリプト
映像のみ読み込んで、シーンカットとリサイズを行うスクリプトです。

#!/usr/bin/python3

import vapoursynth as vs

#core.std.LoadPlugin('/usr/local/lib/vapoursynth/libsavfsource.so')

core = vs.core
clip = core.ffms2.Source(source='src.mp4')
clip = clip[0:100] + clip[200:300] + clip[500:]
clip = core.resize.Spline36(clip,width=1280,height=720,format=vs.YUV420P8)
clip.set_output()
解説
VapourSynth のスクリプトファイルには、実行権限を付ける必要はありませんので、そのまま普通のテキストファイルとして扱ってください。
行頭 (行頭にある空白・タブは除く) が 「#」 の場合、その行はコメントとして扱われます。

> #!/usr/bin/python3

一行目は必ず Python3 コマンドのパスを記述する必要があります。
コマンドのパスが異なる場合は、変更してください。

> import vapoursynth as vs

Python3 の VapourSynth ライブラリを読み込んで、使えるようにします。
この時、使いやすいように、'vapoursynth' を 'vs' として、名前を変更しています。

> core = vs.core

VapourSynth のメイン機能である、コアオブジェクトを取得します。
※以前は "core = vs.get_core()" で取得していましたが、現在では使用できなくなりました。

> core.std.LoadPlugin('/usr/local/lib/vapoursynth/libsavfsource.so')

プラグインを手動で読み込みます。
プラグインファイル (*.so) のパスを、絶対パスまたは相対パスで指定してください。
VapourSynth 指定のプラグインディレクトリに置いてあるファイルは、自動で読み込まれます。

ここでは例として扱っているだけなので、"#" でコメント化しています。実際には実行されません。

> clip = core.ffms2.Source(source='src.mp4')

FFMS2 プラグインで、動画ファイルから映像を読み込み、clip という名前の変数に格納します。
以降は、読み込んだ映像を編集する場合、この clip 変数を使います。
なお、ここで読み込まれるのは映像だけで、音声データは読み込まれません。

FFMS2 で動画が読み込まれると、動画ファイルと同じディレクトリに、キャッシュファイル (*.ffindex) が作成されます。
キャッシュファイルは、各フレーム位置の情報などを記述したものです。
キャッシュファイルが必要なくなった場合は、手動で削除してください。

> clip = clip[0:100] + clip[200:300] + clip[500:]

フレーム単位でのシーンカットを行います。
フレーム位置は、0が先頭となります。
切り取る部分の範囲ではなく、残したい部分の範囲を指定します。複数の範囲がある場合は、+ で連結させます。

clip[0:100]clip から [ 0 〜 99 ] のフレームを取得
clip[200:300][ 200 〜 299 ] のフレームを取得
clip[500:][ 500 〜 終端 ] のフレームを取得

最終的に、カットを行った映像を、clip に再セットしています。

[○:○] で範囲を指定する場合、左側は「取り出す先頭のフレーム位置」、右側は「取り出す終端のフレーム位置 + 1」です。
右側の位置は、実際に含まれる終端のフレーム位置に 1 を足した値であることに注意してください。
これは、Python3 におけるスライス指定がそうなっているからです。

なので、0〜99 の範囲のフレームを取り出したいなら、[0:100] と記述します。
右側の値を省略した場合は、映像全体の終端までとなります。

> clip = core.resize.Spline36(clip,width=1280,height=720,format=vs.YUV420P8)

画像のリサイズやフォーマット変換を行います。
拡大縮小の方法は、Point, Bilinear, Bicubic, Lanczos, Spline16, Spline36 があります。
リサイズは Spline36 が一番綺麗なのでそちらを使いますが、画像のフォーマット変換だけしたい場合は、Point を使います。

width, height で、リサイズ後の幅と高さを指定。省略で元のままになります。
format で、出力する画像のフォーマットを指定します。
エンコーダに映像を渡す場合、通常は YUV420 8bit を使うので、vs.YUV420P8 にします。

> clip.set_output()

最後に、clip の映像データを出力します。
映像の確認
実際にエンコードする前に、処理後の画像を確認したい場合や、カットするフレーム位置の確認をしたい場合は、VapourSynth のエディタやビューアを使います。
vspipe を使ってエンコード
エンコード用のスクリプトが出来たら、実際に映像をエンコードしていきます。

VapourSynth に含まれている vspipe コマンドを使うと、スクリプトを処理して、出力された映像 (または音声) を、ファイルや標準出力に出力できます。
基本的には、パイプでつないで、エンコーダに渡すことになります。
x264 コマンドでエンコード
$ vspipe -c y4m enc.vpy - | x264 --demuxer y4m --sar 1:1 ... - -o out.mp4

-c y4m オプションにより、無圧縮の y4m 形式で映像を出力します。
出力ファイル名に "-" を指定することで、標準出力に出力できます。

x264 コマンドでは、入力ファイルに "-" を指定することで、標準入力から映像データを受け取ります。
--demuxer y4m で、入力が y4m フォーマットであることを指定します。

なお、デフォルトでは、ピクセルのアスペクト比 (SAR) が 0:0 (unknown) になってしまうので、x264 の --sar オプションで、アスペクト比を指定してください。
Next
ここまでは、VapourSynth の基本情報を紹介しました。
次からは、実際に、映像と音声をエンコードする手順を紹介していきます。