• Alliance for Open Media Video 1を試した

    2018年03月17日 22時35分
    AppleがAlliance for Open Mediaに加入したよという記事(CNET Japan)を見てAV1を知り、
    色々調べたのでまとめておこうと思います。


    AV1の概要についてはWikipediaあたりが丁度いいと思います。

    個人的に注目したのはGoogle・Microsoft・ Mozilla・Appleがメンバーに入っているため、
    多くのブラウザで対応されることが期待できそうというところです。
    (SafariがVP9に対応してくれればそれでいいのですが・・・)

    既に実装も進んでおり、Firefox Nightlyでは再生もサポートされているということだったので
    エンコードと再生を試してみました。


    エンコードにはリファレンスのエンコーダを使用します。
    AV1のGitはこちら。

    https://aomedia.googlesource.com/aom

    AV1は現在も絶賛開発中となっており
    仕様の確定が2017年末予定 → 2018年初め予定 → 現在も未確定という状況のようです。

    よって、デコーダのバージョンとエンコーダのバージョンを合わせておかないと「再生出来ねぇ!」という状況になります。
    そこでまずはFirefox Nightlyで使用されているデコーダのバージョンを調べます。


    Firefoxに使用されているデコーダのバージョンの確認方法は以下のページにあります。

    DASH playback of AV1 video in Firefox - Mozilla Hacks - the Web developer blog

    「av1.experimental.<aomのコミットハッシュ>」をMediaSource.isTypeSupportedに入れて通ったらそのバージョンということです。
    MediaSource.isTypeSupported('av1.experimental.e87fb2378f01103d5d6e477a4ef6892dc714e614');

    aomのlogからコミットハッシュのリストを取ってきて一致するか調べて行けばどれかが当たります。


    デコーダのバージョンが分かったら同じバージョンのソースを取得しビルドします。

    ビルドの方法はREADMEに丁寧に書いてあるので基本はその通りにやればよいです。
    補足として私がWindows上でビルドした時のメモも記載しておきます。

    • Visual Studio 2017
      • C++開発を追加する
    • CMake version 3.5 or higher.
      • CMakeは手動で叩くのでPATHを通すとかは必要ではない
    • Git
      • Makeの中でチェックしてるっぽいけど必須かはわからない
      • ソースも落とせるのでとりあえず入れておけばよいだろう
      • Gitクライアントなら何でも良さそうだがGit for windowsで動作を確認
    • Perl
      • Active Perlで大丈夫
      • 特に追加のPPMとかは要らない
    • Yasm
      • Visual Studioと連携出来るっぽいvsyasmというのもあるけど普通のyasmの方でよい
      • Make中に参照されているのでPATHを通しておく必要がある
      • VSの再頒布可能パッケージが必要(どのバージョンかは忘れた)

    CMakeのオプションが重要です。
    cmake -G "Visual Studio 15 2017 Win64" -DCONFIG_CDEF_SINGLEPASS=1 -DCONFIG_UNIT_TESTS=0 path/to/aom


    Visual Studio 2017用のファイルを作成するオプション。
    -G "Visual Studio 15 2017 Win64"

    「Win64」は64bitアプリをビルドする設定。
    エンコーダはかなりメモリを食って普通に2GBを突破したりするので64bitで作るべきです。

    Firefoxが追加しているオプション。
    -DCONFIG_CDEF_SINGLEPASS=1

    デフォルトはOFFですがFirefoxがONでビルドしているので合わせてONにします。
    この設定は最新のバージョンには存在しません。(OFF時の実装が削除され、標準でONの動作となる)

    テストを省略するオプション。
    -DCONFIG_UNIT_TESTS=0

    ちょっと使ってみるだけなので外しました。
    ONにするとPythonを要求されて面倒なので・・・。

    Makeが済むとVisual Studio用のファイルが生成されるので、ソリューションファイルを開けばビルドできます。
    特に何も無ければビルドが成功してライブラリや実行ファイルが出力されるはずです。
    エンコーダは aomenc.exe です。

    割と作るのが面倒なのでビルドしたエンコーダも置いておきます。
    私がビルドしたバイナリを信用できる人はお使いください。
    あとこれを使って何が起きても私は知らん。

    aomenc (for Firefox Nightly 61.0a1)


    エンコーダが準備できたので今回は以下のようにエンコードしました。
    aomenc.exe ^
    --verbose ^
    --psnr ^
    --cpu-used=8 ^
    --threads=4 ^
    --tile-columns=2 ^
    --passes=2 ^
    --input-bit-depth=8 ^
    --webm ^
    --codec=av1 ^
    --profile=0 ^
    --end-usage=cq ^
    --cq-level=32 ^
    --target-bitrate=2048 ^
    --bit-depth=8 ^
    --color-space=bt709 ^
    --output=output.webm ^
    input.y4m

    オプションについては別にまとめたので細かいことが知りたければ参照してください。
    (ただし最新バージョンのオプションを元に書いたのでe87fb2378f01103d5d6e477a4ef6892dc714e614とは微妙に使えるオプションが違います)


    ソースの映像はカスタムオーダーメイド3D2をキャプチャしてきて、
    データ的には i420 960 * 540 30fps 総フレーム数4916となっています。

    これをCore i7 3770でエンコードしたところ丁度5時間かかりました。
    ただ、CPUを使い切ってくれないのでマルチスレッドがイマイチのようです。
    VP9のソースと比較してみましたが、そもそもVP9もあまりマルチスレッド化をしていないようなので
    処理内容的に向かなくて出来ないのかもしれません。


    エンコードもアレですが、デコードもかなり遅いです。

    最初は i444 1920 * 1080 60fps でエンコードしていたのですが、
    再生してみるとデコード処理が間に合わないので
    解像度とかFPSとかビットレートとかを下げて行って上記の内容になりました。

    Core i7 3770ではデコード出来ていますがCPUによってはデコード出来ないかもしれません。
    Firefoxはデコードが間に合わない場合次にデコードが間に合うフレームまで映像がストップするようです。


    エンコードが遅いのは時間をかければなんとかならなくもないですが、
    デコードが間に合わないとなると実用は無理ではないかと思います。

    Gitのlogを見ているとSIMDで頑張って最適化しているようですが
    SIMDとマルチスレッドでガリガリにチューニングしてどこまで行けるか。

    さすがにハードウェアでのサポートが必須と言えるレベルではないかと思います。
    ただ、ここから仕様を固めてハードウェアを設計してとなるとだいぶ未来の話になりそうです。


    エンコードしたものはこちらになります。(45,290,322 Byte)


    バージョンの合うデコーダでCPUパワーがあれば再生出来ます。
    (あと、about:configでmedia.av1.enabledをtrueにする必要があります。)


    あと音声をmuxしようとするとffmpegでもmkvtoolnixでも
    「AV1とかWebmの仕様にはない!」とか怒られて入れられないので
    結局libwebmのサンプルを元に簡単なプログラムを書いてmuxしました。
    一応これも置いておきます。
    例によってこれを使って何が起きても私は知らない。

    webmmuxer


    WebMはMatroskaのサブセットなのでMatroskaとして作って
    拡張子をwebmに変えてFirefoxに突っ込んだらそこはかとなく動いたのでそれでもいいと思います。

    この辺りの整備もまだまだこれからというところでしょうか。
  • Key sequencer 1.2.0

    2018年02月18日 23時43分
    MIDI入力の切り替えがボタンだと不便だったのでホットキーに変更した上でUIの挙動を整理した。

    Key sequencer
  • Key sequencer 1.1.0

    2017年11月24日 20時45分
    実際に使い始めると気になるところが出てきたので機能を追加。

    • MIDI入力機器(MIDIキーボードなど)に対応。MIDI入力機器からの入力をキーボード入力に変換する。
    • ファイルをドロップして起動に対応。
    • デフォルトのキーバインドを修正。

    Key sequencer
  • Key sequencer 1.0.0

    2017年11月21日 20時11分
    キーボード(MIDIではなくパソコンの)で楽器演奏するソフトがありまして、
    ちょっとマクロで入力したろかいと思ったわけですよ。

    ただそうすると「四分音符だからここは0.4秒ウェイトして・・・」とか書くことになるわけでスマートでない。
    どうせなら楽譜を読み込んでその通りに実行して欲しい。

    そういうことで久しぶりにプログラムを書いたのですが、
    久しぶりだったせいで途中から楽しくなってきて予定よりきちんとしたものが出来ました。
    せっかくなので公開しておこうと思います。

    Key sequencer

    楽譜(MIDI)を読み込んでキーボード(MIDIではない)の入力を行うソフト。

    楽譜は書式が決まってるからデジタルのフォーマットがあると思っていたのですが
    全然そういうことはなくて結局扱いやすいMIDIを採用しました。

    だいたいの楽譜作成ソフトはMIDI出力が付いているので大丈夫だと思いたい。
    とりあえずMuseScore 2で作って試したら良い感じでした。
  • FFmpegでVP9エンコード

    2017年09月21日 20時25分
    時々ゲームプレイを録画して残していまして、
    CODECをh.264、色空間はYUV420にしていました。

    ただ、ゲーム画面だと隣り合うピクセルの色が全然違ったり彩度の高いピクセルが多かったりで
    YUV420にすると全体的に色が薄く見えるのが不満でした。

    これを解決すべく色空間をYUV444に変更し
    ついでにCODECも高圧縮なVP9に変更しようというのが今回の話の始まり。


    今時高圧縮なCODECというとh.265かVP9で迷います。

    h.265はハードウェアエンコード対応が多く
    VP9はだいたいのブラウザで再生できるのがそれぞれの利点でしょうか。

    画質と圧縮率はだいたい同じくらいのようで
    私には良し悪しが判断出来ません。

    今回は大量にエンコードするわけではないので再生環境が多いVP9を採用することにしました。


    VP9のエンコーダというと、最初はlibvpxに付いているvpxencを使おうと思ったのですが
    録画したaviファイルをy4mに変換する必要があり
    y4mの変換にffmpegを使うことになったので、それならもう全部ffmpegでいいかとffmpegを採用。


    それでいざffmpegでエンコードしようとすると
    オプション大量すぎてわけわからんで苦労したので調べた情報を書いておこうと思います。


    私はffmpegについて詳しいわけではないので
    不確かなことを書くのもどうかとは思ったのですが
    あまりに情報が少なかったので全く無いよりはいいかと書いておくことにしました。

    調べる時のとっかかり程度の情報と思って見ていただきたい。


    参考情報




    CODEC


    動画CODECにVP9を指定。
    -c:v libvpx-vp9


    WebMの音声CODECはOpusまたはVorbisになりますが、後発のOpusを使えばいいと思います。(性能もいいらしい)
    音声CODECにOpusを指定。
    -c:a libopus


    コンテナは出力ファイルの拡張子から判断してくれるようですが、一応指定しておけば確実かなと思います。
    -f webm



    RGB → YUV444変換


    エンコーダに渡すピクセルの色空間指定はpix_fmtで行います。
    -pix_fmt yuv444p


    カラーマトリクスは全然別のオプションでこうです。
    -vf "scale=out_color_matrix=bt709:out_range=full"


    ffmpegのログを見ると、-vfでscaleを指定しない場合auto_scalerというのが挿入され、こいつが色空間の変換処理をしているようです。
    「-vf "scale=out_color_matrix=bt709:out_range=full"」のように明示的に指定してやるとauto_scalerが自動挿入されなくなり、指定したscalerが入ります。


    ビットレート


    VP9にはビットレートのモードが4つ。

    • Constant Quantizer (Q)
    • Constrained Quality (CQ)
    • Variable Bitrate (VBR)
    • Constant Bitrate (CBR)

    ストリーミングで配信するわけでもなく
    自分用にアーカイブするのが主な目的なので
    品質固定のConstant Quantizer (Q)を採用しました。

    Constant Quantizer (Q)の指定。
    -crf 30 -b:v 0


    crfは0-63の範囲で指定し、0に近づくほど画質がよくなりデータサイズが大きくなるので
    結果のファイルサイズと画質のバランスで決めることになると思います。

    思ったより数字を大きくしても画質は良いと感じました。
    目安としていくらか試した感じだと1080p 30fpsで30-35あたりが良いのではないかと。

    「-b:v 0」は必須です。というかこの指定がConstant Quantizer (Q)の意味。


    Opusのビットレートの指定は簡単。
    -b:a 160k

    Youtubeが160kでエンコードしているらしいのでその辺りが良さそうです。


    エンコード品質と速度


    -speed 1


    0-4の間で指定し、0に近い程エンコード速度が遅くなり画質が良くなる。
    基本的には0を指定したいところですが、ただでさえ遅いVP9のエンコードがさらに遅くなるので
    エンコード時間を考慮して決めることになります。


    カラーマトリクス


    YUVからRGBに戻す時のカラーマトリクスを指定します。
    RGB → YUVの変換で指定したものを指定すればいいと思うのですが
    なぜ3個もあるのかよくわかりません。

    ffmpegのログを見ると3つとも同じにしておけばひとまとめにして認識してくれているようなのでこれで合っている気がします。
    -colorspace bt709 -color_primaries bt709 -color_trc bt709



    デコード用オプション


    公式のエンコードガイドに、画面を分割して並列デコードできるようになるみたいなオプションがエンコード例に記載してあります。
    -tile-columns 6 -frame-parallel 1


    効果はイマイチわかりませんが今のところ特に害はないです。


    FFmpegでVP9エンコード 補足