配信用の場面転換素材を作っていて、はっきりした落とし穴に当たりました。OBSの「スティンガー」画面切り替えは、APNGを受け付けません。
配信素材として広く配布されているのは透過APNGなので、「買ったのにスティンガーに設定できない」と困る人がいるはずです。理由と、正しい形式への変換方法をまとめます。
OBSのソースには「画像」と「メディアソース」があり、APNGは画像として読み込まれます。前景に重ねるオーバーレイ用途ならこれで十分です。
ところが「スティンガー」はシーン切り替えの機能で、切り替えの進行に合わせて特定のフレームまで再生し、そこで裏のシーンを差し替えるという制御をします。この「◯ミリ秒地点で切り替える」という指定ができるのは動画ファイルだけで、画像として扱われるAPNGは選択肢に出てきません。
つまり同じ絵でも、オーバーレイならAPNG、スティンガーなら動画と、用途で形式を変える必要があります。
透過を保持できて、かつOBSが確実に読める組み合わせは限られます。
| 形式 | 透過 | 用途 |
|---|---|---|
| WebM(VP9 + アルファ) | ◯ | OBSスティンガーの本命 |
| MOV(ProRes 4444) | ◯ | 動画編集ソフト向け。ファイルが大きい |
| MP4(H.264) | ✕ | 透過を保持できない |
| APNG | ◯ | オーバーレイ用。スティンガーには不可 |
MP4は透明部分を保持できません。ここを勘違いしたまま書き出すと、透明だった部分が黒や白で塗り潰されて出てきます。「透過で書き出したのに背景が黒い」という相談の大半はこれです。
ffmpegで一発です。
ffmpeg -y -f apng -i input.png \
-c:v libvpx-vp9 -pix_fmt yuva420p \
-b:v 2M -auto-alt-ref 0 \
output.webm
要点は3つあります。
-pix_fmt yuva420p の 「a」がアルファです。これを yuv420p にすると透過が消えます。
-auto-alt-ref 0 は保険です。VP9の自動代替フレーム参照はアルファ付きエンコードと相性が悪いとされ、ffmpegのバージョンによってはこれを付けないとエンコードが失敗します。手元のffmpeg 7.1では付けなくても正常に変換でき、アルファも保持されました(透明画素42.9%を確認)が、環境差で失敗する報告があるため付けておくのが無難です。
-f apng で入力形式を明示しています。拡張子が .png のままだと静止画と誤認されて1コマ目だけが変換されることがあります。
ffmpeg -i で確認すると yuv420p と表示されます。アルファが消えたように見えますが、消えていません。
VP9のアルファは映像本体とは別のストリームに格納され、メタデータに alpha_mode : 1 が付く仕様です。表示だけを見て「失敗した」と判断すると、正しく作れているファイルを捨てることになります。
本当に透過が残っているかは、実際にデコードして数えるのが確実です。
# 1. メタデータを見る(alpha_mode: 1 があればアルファ付き)
ffmpeg -i output.webm 2>&1 | grep -i alpha
# 2. 1コマ取り出してRGBAで書き出す
# デコード側にも -c:v libvpx-vp9 を明示するのが重要
ffmpeg -c:v libvpx-vp9 -i output.webm \
-vf "select='eq(n\,9)'" -vsync 0 -pix_fmt rgba probe.png
書き出した probe.png のアルファ値を調べて、最小値が0・最大値が255なら透過は保持されています。手元で作った素材で実測したところ、完全に透明な画素が全体の42.9%ありました。表示上は yuv420p と出ていたファイルです。
「画面切り替え」の「+」から「スティンガー」を選び、WebMを指定します。
設定項目の「切り替えポイント」は、画面が完全に覆われる瞬間に合わせます。ここがずれると、裏で切り替わる瞬間が見えてしまいます。素材の長さの中央あたり(0.8秒の素材なら400ms前後)から始めて、実際に切り替えて微調整するのが早いです。
ついでに、待機画面のようなループ素材を作るときの話も書いておきます。
「継ぎ目がないか」を確かめるとき、最終コマと1コマ目の差分を測るだけでは判断できません。完全なループでも、最終コマと1コマ目のあいだには「1コマぶんの動き」が必ずあるからです。差分がゼロになるのは、そこで映像が止まっている場合だけです。
正しくは、「通常の1コマ間の差分」と「継ぎ目の差分」を比べて、比が1.0前後かを見ます。
| 素材 | 通常1コマ | 継ぎ目 | 比 |
|---|---|---|---|
| キラキラ | 3.50 | 3.57 | 1.02 |
| 桜 | 6.76 | 6.80 | 1.01 |
| 雪 | 1.46 | 1.54 | 1.05 |
| 星空 | 0.12 | 0.31 | 2.53 |
星空だけ2.53倍で、一見すると失敗に見えます。ですがこれは不具合ではありません。星空はほとんど動かないので分母(通常1コマの差分)が0.12と極端に小さく、比が暴れているだけです。絶対値の0.31は4つの中で最小で、知覚できるレベルではありません。差の正体は動画圧縮のキーフレームとその他フレームの誤差です。
比だけを見て機械的に判定すると、いちばん出来のいい素材を「壊れている」と誤判定します。絶対値と併せて見る必要があります。
同じ手続き生成の考え方で書いたバトルマップの自動生成とBGM・効果音の合成もあります。