24000/1001と2997/125の違いは1フレームあたり 1000万分の1秒にも満たないにもかかわらず、字幕のフレームタイミングに影響することがある。
事実として、いわゆる24fpsには厳密には24000/1001と2997/125とがあり、 前者は 23.9760239760...fps 、後者は 23.976fps ちょうどだ。 これらの分子、分母は、AVIヘッダでは、 dwRate / dwScale として定義されている。
両者の差は、1フレームの継続時間にしてわずか 41.7ns(ナノ秒: マイクロ秒の1000分の1の単位)であり、 4時間たっても差の累積は 0.01ms のオーダーに過ぎない。
では、このようなわずかな差が、字幕のタイミングに影響することはほぼ皆無と考えて良いか。
残念ながら、必ずしもそうではない。
例えば、0から数えたフレーム25159の頭は、 24000/1001では17:29.339586、 2997/128では17:29.341008となる。 ミリ秒未満を四捨五入する VirtualDub では、 前者は 17:29.340 と表示され、 後者は 17:29.341 と表示されるだろう。
後者で作業しているとき、 フレーム25159で消失する字幕(25158まで表示されており、25159では非表示)のエンドタイムを、 SSAでは 17:29.34 と表現できる。
ところが、そうして作成したSSAデータを、全フレームが等しいがただしレートが前者になっているビデオと合わせると、 字幕が25159では消失せず、1フレーム、予定よりオーバーランする。 前者のレートでは、このフレームの頭は 17:29.33... だからだ。 前者では、フレーム25159の後でエンドタイム 17:29.34 が来る。 後者では、エンドタイム 17:29.34 の後でフレーム25159が来る。 この時間順序の違いのため、1フレームの差が生じてしまう。
字幕作成 SSA中級編(Ver.1.9)では、VirtualDub が表示するタイムスタンプのミリ秒の位(小数第三位)が 0 のとき、SSAのタイムスタンプをその10ms前に設定するように推奨している。 これは直接的には上記の問題の対応ではないが、上記の問題をある程度、軽減する働きがある。 しかし、それでもまだ上記の問題は完全にはなくならない。
具体的に、24分@24fps(34525フレーム)で、上記のような微妙な差の影響を受ける可能性のあるフレームは、 220個も存在し、全体の約0.6%に及ぶ。もし、タイムスタンプのミリ秒の位(小数第三位)が 1 のとき、 SSAのタイムスタンプを11ms前に設定するようにすれば、上記の問題は解決され、現在のSSA的には、 副作用もない。
同様に、SSAのタイムスタンプを10〜19ms前に設定すれば、上記問題は、 おおざっぱに22万フレーム、ざっと2時間半までは、回避できる。
しかし、これはあくまで「現在のSSA処理系」に依存した場合で、 将来、サブフレーム処理(ビデオのfpsより速く、1フレーム内で字幕を更新する処理)が可能なレンダラーが出現すると、別の問題が生じる。また、USFのようにタイムスタンプが1ms単位の場合も、もっと細かく制御しないと、 問題が生じる。
字幕座標系の区別――relative-to-screen(relative-to="Window")とrelative-to-frame(relative-to="Video")――は、2002年8月17日、Christophe PARISがUniversal Subtitle Format (USF) Specification DRAFT v0.02で導入した。 Gabestは初期USFをサポートしたが、現存する最古のSTS.h Revision 8(2003年5月)のSTSStyleクラスにも、relativeToメンバーがある。 しかし、MPCで座標系をユーザ設定できるようにしたのは2005年2月である。 VSFilterが常にrelative-to-frameであるのにそれまでMPCは常にrelative-to-screenであり、フルスクリーン表示にしたときソフトサブの表示位置の問題があった。
MPCの"Position subtitles relative to the video frame"オプションは2005年2月に加わった(MPC 6.4.8.4)。
このときSSAのスタイルごとに字幕座標系をユーザ側で設定できるようになったので、それをSSAデータ側から明示できるようにすることは自然な発想だろう。
ASS2形式は、ASSの拡張として、2005年11月、Gabestによって実装された(MPC 6.4.8.7、STS.cpp)。
このとき{\kt}
タグも追加された。
ASS2形式のデータを出力する例は、2005年11月のMP4Splitter.cppに見られる。
MEDIASUBTYPE_ASS2 {370689E7-B226-4f67-978D-F10BC1A9C6AE} は、2006年3月現在、/include/moreuuids.hで定義されている。 MEDIASUBTYPE_ASS2は抽象的なデータストリームで、テキストファイルとしてのASSではない。 MEDIASUBTYPE_ASS2のファイルは、ASSと同じ拡張子.assを使う(ConvertDlg.cpp)。
ASS2では、ScriptType: v4.00++、[V4++ Styles]とし、従来の
MarginV, Encoding の代わりに、MarginT, MarginB, Encoding, RelativeTo のように定義する。
イベントにもMarginが4つある。RelativeToを0にするとスクリーン座標、1にするとフレーム座標、2は未定義*1である(STS.h revision 281)。
外部ASS2ファイルを内蔵レンダラーで解釈した場合、有効になる。
VSFilterでは正しく解釈できない。
また、MPCのDSM MuxerでDSMに埋め込むことはできず、
GabestのMuxerとSubtitleSourceでMKVに埋め込むこともできなかったが、
mkvmergeでは透過的に(サポートしているわけではないのだが、結果的に)埋め込める。
外部ファイルのサンプル4KB、
ASS2_Test.7z
埋め込んだサンプル40KB、
ASS2_Test.mkv
*1 2004年12月の"Absolutely absolute" positioningでは座標の基準について「物理的スクリーン」「表示フレーム」「オリジナルのフレーム」の3種類を区別する必要があることが指摘されている。パン&スキャンやアスペクト比の変更があると「表示フレーム」と「オリジナルのフレーム」が一致しないからである。
Cost 32.8 milliseconds.