9 : 19 ASS: 縁ワイプと縦カラオケ

← 9‒18 p↑ もくじ i 9‒20 n →

字幕と音声のずらし方: 理論と実際 Ver. 1.1

2006年 6月 9日
記事ID d60609

字幕は、実際の声の出だしより0.1~0.2秒早く表示開始するのが良い。 カラオケの色変化は、歌より0.2~0.3秒早めに進行するのが良い。

きちんと同期させず「ずらす」ことで、かえって快適になるのはなぜか。 ずらす量が一般の字幕とカラオケで異なっているのはなぜか。 「0.2~0.3秒」のように幅があるのは、状況によって加減することを意味するが、 「状況」とは具体的にどのようなことか。

導入

字幕作成では、基本的には音声の立ち上がり・立ち下がりと字幕のオン・オフを同期させるわけだが、 実際には、字幕と音声のタイミングを少しずらす方が良い。 もちろん、でたらめにずらして良いのでなく、うまくずらす。 ジャズでいうスイングに似ている。 スイングとは、即物的に言うと、本来のリズムより4分の1拍くらい早く音を鳴らし始めること、 前の小節の拍の裏などから、長い音符にタイをかけることだ(伝統和声学では「跛行はこうリズム」ともいう)。

字幕のスタートが音声より少し早めがいいことは基本的で、タイミング入門でも取り上げている。 それは実際に字幕をいじればすぐ実感できる。 しかし、なぜ早めで良いのだろうか。

人間の反応速度とスイング幅

カラオケ以外の一般の字幕

観客が、せりふの開始(人物がしゃべり始めること)と同時に字幕の表示開始を見た場合、 何が起きるだろうか。

(1) 音声については「理解できない外国語」として、言語として解析しようとはしていない。 たまたま聞き取れる単語があるかもしれないが、特別、意識して聞いてはいない。 声の種類や調子だけ聞き流す。たいして頭を使うことはない。

(2) 字幕については、それが目に入った後、文字を読んで、言語として理解し、 文脈に照らして発話の意図を考える、といったかなり複雑な作業を行っている。

明らかに (1) より (2) の方が頭を使い、処理時間がかかる。 (1) は単に音が耳に入ってくるというだけだが、 (2) は文字認識・言語処理だからだ。 だから (1) と (2) を同時に開始すると、処理完了するのは (1) が先で (2) が遅れる。 「理解できない外国語が耳に入ってきたが、まだ字幕は理解できていない」ことになる。 この状態は潜在的にストレスとなり、観客を不安にする。

そうならないために、字幕が少し早めに出た方が良い。 声が始まる0.2秒ほど前に字幕が出れば、文字認識・言語解析が終わったちょうどそのころ、 音声がスタートし、あたかもその外国語の意味が分かっているような安心した気持ちになれるだろう。 ずらした方が快適に感じる理由はそこにあり、 100~200msという時間の正体は、(1) と (2) の処理時間差と考えられる。

ストーリーに没入している観客は、 心のなかでせりふを音声化している。 「オリジナル言語の声で、字幕言語の台詞を読んだらどうなるか」という脳内アフレコを行っている。 アフレコすべき「せりふ」を認識するより前に声が既に始まっていたら脳内アフレコがやりづらい。

カラオケ字幕

カラオケ字幕については、 色変化を目で見て楽しむカラオケもどき(アイキャンディー)と、 実際に歌うための実用カラオケでアプローチが違う。

アイキャンディーでは、人間は、視覚で色変化を認識しつつ、聴覚で歌の進行を認識する。 単にそれだけで、事実上、多少ずれていようがいまいが、どうでもいい。

実用カラオケでは「色変化」を素早く認識し、 それに合わせて文字を読み上げ、正しい音程とリズムで声を出す、という複雑な動作が行われる。 アイキャンディーでは歌う必要がないのだから、文字をちゃんと読む必要すらないが、 歌う場合、色変化を認識したときには既に歌がそこに達しているのでは、声を出すのが間に合わない。 よって、実際の音声の立ち上がりより字幕の色変化が「前のめり」に先行する文字ごとのスイングが必要になる。 実用カラオケで、色変化は実際に歌っている場所より、約200~300ms先行する。 視覚刺激をキューに発声を行うのに必要な、人間の反応時間のディレイ(プラス多少の余裕)に相当する。

一般の字幕の行タイミングのスイング幅と、 カラオケの文字ごとのスイング幅で、適量に差があるのは、 「色変化刺激を引き金に、文字を読んで、声を出す」というカラオケ動作より、 単に聞こえている音の意味を黙読で理解すればいい一般字幕の方が、処理が速いからだ。

カラオケの場合、文字ごとのスイング幅とは別に、 行タイミングのスイング(リードイン)がある。 概念的には一応区別するが、実際には、行頭トークン(事実上、すべての「まとも」なカラオケではヌルトークン)のスイングが行全体のスイングに含まれることに注意。行スイングは行頭のヌルトークンのスイングとして実装される、 と言い換えても良い。(詳しくは、カラオケ字幕の基礎)

カラオケの行リードイン(=行頭スイング)は、 文字ごとのスイング幅以上であることが望ましい。 行が変わったとたんにもう色変化しているのでは歌詞を読む暇がなく、 まして歌えないからだ。 たいていの人は、歌う準備をしながら同時に行全体に目を走らせるので、 リードインは文字ごとのスイング幅より必ずしも大である必要はなく、イコールでも良い。 しかし、リードインが文字ごとのスイング幅未満では、結局、その行の出だしの部分のスイング幅が圧縮されてしまうことになり、 歌いにくい。よって、実用カラオケでは、リードインは、最低でも約200ms、できれば500ms程度が望ましい。 実際に歌うわけではないアイキャンディーでは、より短い100ms程度のリードインでも良い。

行エンドタイムは?

以上のように、人間は、黙読にせよ、歌うにせよ、 音声に対して、字幕を先読みする。 声のせりふが終わらないうちに、字幕は最後まで読み終えていることは、珍しくない。

そのため、字幕のスタートタイムは音声の立ち上がりより早くて良い一方、 字幕のエンドタイムは、音声の立ち下がりより早くても、あまり気にならない。 既に読み終わっているものが消えても、別に困らないからだ。

大原則としては、音声が終わるのと同時に字幕を消す。 しかし、この原則にはプラスとマイナス両方向の考慮事項がある。

プラスのディレイ: たまたまよそ見していたり、まばたきをしたりしていて、 字幕の開始を見逃すことがあるから、 その意味では、少し遅れて読み始めても最後まで字幕を読めるように、 エンドタイムはゆっくりの方が良い。 これはプラスのディレイを意味する(声が終わってもすぐ字幕は消えずちょっと待つ)。

マイナスのディレイ(行末圧縮): 実際には、 エンドタイムをルーズにすると、映像タイミングとの矛盾が生じやすい。 人物の口は既に閉じているのに、いつまでも字幕が残っているのは、 必ずしも理想的とは言えない。 スタートにスイング感があるのに、エンドがあまりぐずつくのは、字幕全体のリズムを悪くする。 特に、せりふが何行かに分かれて字幕が切り替わるとき、 スタートがスイングすることと、前の行のエンドがディレイすることとは、両立しない。

実際、フレームタイミング(特にシーンチェンジ)との関連で必要なら、 エンドタイムは約200msまでは安全に前倒しできる。 200~400msは必ずしも望ましくないが、可能である(中級編参照)。 必要ないのに無意味にエンドタイムを早めてはいけないが、 エンドタイムの頃には実際にはもうほとんど誰も字幕を読んでいないという事実を認識することは、 重要だ。

エンドタイムを前倒ししても、スタートタイムがスイングしているのだから、 字幕の表示時間はトータルでは整合がとれている。もし、エンドを前倒しすることで表示時間が短くなり過ぎるようなら、 スタートのスイングを増加させれば良い。(目安として、最短でも800msは表示する。)

カラオケでの行末タイミングの圧縮

行末タイミングの圧縮とは、基本的には、字幕のエンドタイムを音声の立ち下がりより早くすることだ。 もちろん必要ないのに、やってはいけない。 一方、カラオケでは「行末に近付くと少し色変化を加速すること」を含み、しばしば望ましい。

実用カラオケでは、行末のトークンは実際の音符の長さに合わせてゆっくり色変化する必要なく、 音の頭の位置だけ教えたら、もう役目は終わっている。 そこでのろのろするより、行末まで来たら、さっさと次の行の歌い出しを教えるべきだ。 行末付近、特に、最後の空でないトークンの持続時間を短縮できる。 アイキャンディーの場合でもそうした方が良い。 行が変わったとたんに色変化するのは慌ただしく、「アイキャンディー」としての優雅さに欠ける。

音声に対する字幕のディレイ量の目安

この項ではマイナスのディレイは「字幕が音声イベントより先行」することを、 プラスのディレイはその逆を意味する。

注意: カラオケでは「もうすぐ色変化する」ことを示す何らかのエフェクトがある場合、 それ自体が一種のスイングなので、色変化のスイング幅を小さくとることができる可能性がある。 例えば、カラオケトークンがZ方向に上下するエフェクトで、 「色変化の少し前(アクティブになる少し前)に文字が上昇する」場合(色変化の「予兆」がある場合)と、 「アクティブになったとき文字が上昇する(上昇が始まるのと色変化が始まるのが同時)」とでは、 色変化のスイング幅に対する感じ方が異なる。

ディレイ幅における考慮事項

例えば200~300msと言うのは、状況によって200だったり250だったり300だったりするということだが、 「状況」とはどんな要素か。

一般の感覚を理解することの大切さ

カラオケ字幕は本来、初見またはそれに近い(歌詞に慣れていない)人を対象とするものであり、 歌を完全に覚えているなら字幕を見る必要はなく、字幕は必要ない。 ということは、歌を覚えているカラオケアーは、カラオケ字幕を本来のあるべき視点で眺められない。

「自分は熟練したカラオケアーだから自分の感覚の方が正しい」と思わないこと。 確かにカラオケアーは42msを当たり前に見切るが、素人は0.2秒くらいずれていても気付かない。 しかし、熟練したカラオケアーの感じ方は、一般の人と異なっているという意味で、間違っている。 「素人の目にはこれがどう見えているのか」を理解できてこそ真の「プロ」だ。

カラオケアーは、カラオケ字幕があると、映像も歌詞も無視して、カラオケ効果だけに全神経を研ぎ澄ますという悲しいさがあるが、 これは明らかに一般人の視点とずれている。

同様に、一般の字幕でも、オリジナル音声がまったく理解できない人がどういうふうに字幕を見ているのか、 それを考える必要がある。

機会があるごとに、いろいろな人(特に字幕の技術的なことを知らない人)にコメントを求めよう。 返ってきた感想が自分の感覚とずれているときには、「素人だから分からないのだ」と無視したり、 腹を立てたりせず、なぜ相手はそう感じたのか掘り下げて考えてみることが大切だ。 確かに個人の感覚の違いもあるが、基本的には「見ていて気になる」ことを避け、 字幕の流れが変に意識されないということが最も良い。

更新履歴

2006年6月9日 Ver. 1
初版。
2006年6月14日 Ver. 1.1
ディレイ幅の目安について修正・加筆。

この記事のURL

パブリックドメイン


[ASS] 通常カラオケから「縁ワイプ」への素早い変換

2007年12月20日
記事ID d71220

\koの輪郭ハイライトは小文字の\kに対応するスタッカーティシモだが、 大文字の\Kに対応するレガート変化でやりたいという、いわゆる「縁ワイプ」への要望があるだろう。


文字単位で良いなら\Kを\koに変え下敷きレイヤーに乗せるだけだが、 滑らかな曲にはフィットしない。


ピクセル単位で連続変化させるには別のアプローチが必要。効果は似ているがもはやKカラオケでない。

t-clipを使えば簡単に実現できるが、この記事の目的では\tと\clipについての理解は必要ない。 Kカラオケからt-clipには以下のツールで自動変換でき、しくみは知らなくても動作させられる。

もともとa3rで可能だったが、 バージョン0.0.9.41-test1で多状態カラオケの生成を大幅に高速化したので、 この機会にt-clipの一例として、変換方法を簡単に説明しておく。 (高速化というより今までが遅過ぎただけだが。) これはテストバージョンで実際には少しまだ速くなる。 0.0.9.17から0.0.9.40は、多状態カラオケの「クイック・プレビュー」は壊れていて動作しないが、 それも直した。

下準備

変換元の通常カラオケを用意する。 このとき、文字の輪郭は「色変化後の太い輪郭」にしておく(全部の文字に対して。つまり普通にスタイル指定で)。 縁ワイプ専用のアルゴリズムでなく長方形のt-clipの流用のため、 変換結果において、 文字間が狭いと、前の文字の輪郭が全部太くなった副作用で変化待ちの次の文字の輪郭がフライングで出てしまう。 よって変換前のこの時点で、適宜\fspで文字間を広めにしておくと良い。 (タグの知識がなくても、スタイル定義のSpacingフィールドを変えるのでOK。) 隣の文字の輪郭とあまり重なり過ぎるのは良くない。

変換

a3rを起動してoを押して変換元ASSをロードする。ビデオはロードしてもしなくてもいい(この変換自体には必要ない)。 [Shift]+[M] にて多状態カラオケの設定を出す。縁ワイプの代用にする場合、 Waiting/Active/Visitedを全部1にして、Pure Tokenlessをチェック、Cell Widthを画面の横ピクセルにする(640x480なら640)。 このセル幅設定は本来は必要ないが、今のところ必要。 Optimizeは当然チェック。 Fast Modeで問題ないはず。 初期色は全透明、Activeカラーは使いたい文字色、最終色は全透明、輪郭は使いたい輪郭色(*1)。 これでレンダーする。

(*1) これは内容を理解していなくてもやりやすくするための仮の設定で、 t-clipの意味が分かっているなら、色の設定は何でもよくASSがレンダーされてからスタイルを自由に編集するので良い。

注意: これは多状態カラオケの限定的な応用で、1/1/1より状態数を増やせば、例えば、 色変化部分に、空間横方向でグラデーションをかけながらスライドさせたりできる。

色の設定は多少違っていても後からASSで直せばいいが、輪郭の太さは変換結果に影響するので、 輪郭の太さを変える場合は上記のレンダリングをやり直すこと。

色を全透過に設定したため、生成されたASSはテキスト編集をしないと意味をなさず、 そのままプレビューしても変化が見えない。

生成したASSのテキスト編集

Pure Tokenlessで1/1/1だったら変化前と変化後の2レイヤーだけ出てきそうなものだが、 設計が手抜きなのでなぜか3レイヤー生成される。(プラス、ボーダー用の1レイヤー=下敷きレイヤーに流用。) 実際に必要なのは各スタイルごとにFC000とB000の2レイヤーだけであり、後はCPUパワーの無駄なので削除して良い。 (将来のバージョンアップで、この設定でFCがなくなったら、FCをFLに読み替えてほしい。) スタイルを少しいじる。 生成されたデータではB000以外の全スタイルは輪郭が透明になっているので、これを使いたい「太い」輪郭の設定に変える。 次にB000の輪郭を変化前の「細い」輪郭の設定に変える。 さらにB000のフェイスが透明になっているので、これを使いたいフェイスに変える。

たったこれだけ。 2レイヤーなのでソフトサブでもいける。 あくまでt-clipの単純流用なので、 厳密には少しマニュアルで調整すべきことが出てきて、\tタグ\clipタグがどこで何をやっているか理解できる必要があるが、そのままでも、そこそこ実用になるとは思う。

この記事のURL

パブリックドメイン


[ASS] Avisynth/Textsub: 自動コリジョン処理がキャッシュを汚染

2008年 3月 9日
記事ID d80309

一般に、字幕の自動コリジョン処理は、逆向きにシークすると上下が逆になる。 このことは Subtitler のドキュメントに既に明記されており、そこから発展した Textsub.vdf / VSFilter.dll でも同じだ。 逆向きにシークしなくても、最初のフレーム以外の場所に直接飛んだりすると、本来と違うと状態になることがある。

Dialogue: 0,0:00:01.00,0:00:05.00,Default,Line1,0000,0000,0000,,aaa
Dialogue: 0,0:00:04.00,0:00:07.00,Default,Line2,0000,0000,0000,,bbb

上の bbb は普通の再生順序では aaa とコリジョンを起こすので、aaa が消えた後、 例えば 0:06 でも aaa をよけた位置に残る。 ところがいきなり 0:06 に飛ぶと、そこではコリジョンが起きないので、bbb は通常位置になる。

ここまではいいのだが、問題は、Avisynth で処理した場合のキャッシュ。 一回この状態を発生させると、最初から再生し「 aaa をよけて bbb 」となっても、 0:06 の位置で1フレームだけ(または既に開いたフレーム数だけ) bbb の位置が腐ったキャッシュから読み込まれ、 字幕位置が一瞬ぶれる。

Avisynth 系をあまり責めることもできない。ビデオも字幕ファイルも更新されていないのに、 字幕イメージのキャッシュが古くなる、というある意味、非常識な現象だからだ。 事情を知っているユーザーから見れば、そのフレームはキャッシュを読まず、再取得してほしい。 でも Avisynth の立場で考えれば、同じビデオをまったく同じフィルターでまったく同じパラメータで処理した結果だから、 いちいち再取得せずキャッシュから読むのは当然ともいえる。 Avisynth 側でなく VSFilter 自身がキャッシュしてしまう可能性すらある。

これに似た問題は、ソフトサブでコリジョン直後のチャプターに飛ぶような場合に発生しうる。

理論上、さらに、下流に3次元NRなどのフィルターがある場合、キャッシュ汚染が残像を生み被害が前後のフレームに拡大する。

字幕があるときは、厳密には、 DirectShowSource の seekzero のように、 最初のフレームから順々にシークする以外の方法でフレームをたどってはいけない。 しかしそれではプレビューができず仕事にならないので、 もっとさかのぼって、 トラブルを回避する安全策は、自動コリジョン処理に頼り過ぎないことに尽きる。 レイヤーと MarginV で、どちらを上にどう出したいのか明示するのが最も無難だ。

分かっていても MarginV を手動で書くのは案外面倒だ。 あまりお勧めできないが、その場しのぎには次のような手もある。 不可視の行によって行の余白を自動計算。

; not recommended
Dialogue: 1,0:00:01.00,0:00:05.00,Default,Line1,0000,0000,0000,,aaa
Dialogue: 2,0:00:04.00,0:00:07.00,Default,Line2,0000,0000,0000,,bbb\N{\1a&Hff\2a&Hff\3a&Hff\4a&Hff}aaa

簡易的には \N\h でもいいかもしれない。

開いて直ちにフレーム1から順にエンコードするときには問題が出ないので心配し過ぎる必要はないが、 自動コリジョン処理に依存すると潜在的に危険があることは知っておくべきだろう。 特に時間的に長いコリジョンはレイヤーを使ってコリジョンでない書き方をするほうが良いと思われる。

最終的にエンコードするときは『AVSを開いたらうろちょろシークしない』『エンコードを始める前にはいったん全部閉じる』のが肝心だ。 それでも、Trimを使って途中から呼び出すようなことがあると、 場合によって意図しない結果になるのでご注意を…。

この記事のURL

パブリックドメイン


[ASS] 字幕のリップシンクへのブレークスルー(メモ)

2008年 6月18日
記事ID d80618

注意:
このメモは字幕に関する技術的問題を扱っています。必要ないのに問題を認識すると、物語の内容よりそれが気になって、映画を普通に楽しめなくなるので、字幕を自作する人以外、読まない方が良いかと…。

メモ1: 2008-06-18 字幕のリップシンクへのブレークスルー

a3r ver. 0.1.0.0-test22 にて「字幕とクチパクを合わせるべきか、合わせるべきでないか」客観的・効率的に判断できる方法を実装した。

以下、Time From WAV で基本のタイミングは取れているのを前提として、映像側との同期について。

字幕のリップシンクは単に最初に口が開くフレームを字幕開始時刻にするだけだが、 問題は「それでいいのか」。 実写なら普通口が開けば声が出るので、シーンチェンジとのコンフリクト以外はあまり考えることがないようだが、 声のスタートと完全に「同時」ということは、字幕としては遅過ぎる。 実写以外ではパクと声は必ずしもよく合っていないので、さらに問題が複雑になる。

以前のリップシンクの取り方は、

  1. 口が最初に開くフレームに移動し[Home]で「選択スタート」。(VD互換、AviUtlと逆)
  2. プレビューしてそのスタートタイムで良ければ、[ キーで[Home] を押したキーに戻る。(VD互換、AviUtlと逆)
  3. [F3] キーでそのフレームのタイムスタンプをコピー。
  4. その時刻をASSに貼り付ける。

ドキュメントを作っていないので機能の意味どころか新機能の存在自体が分かりにくいが、 2008年5月に少し合理化を図り(v0.1.0.0-test 9 / v0.0.9.55)、

  1. 口が最初に開くフレームに移動し[Home]で「開始設定」。
  2. プレビューしてそのスタートタイムで良ければ、Ctrl+[ にて「開始時刻コピー」。
  3. その時刻をASSに貼り付ける。

「開始時刻コピー」というコマンドを作って1ステップ減らした。またキーバインドも、[Home]の代わりに[Num7]、 Ctrl+[ の代わりにCtrl+Num7でいい、というように、少しでも手の動きを少なくすることを考えていた。

しかしこれらの方法には、基本的な欠陥があった。 「プレビューしてそのスタートタイムで良ければ」という判断が勘に頼っていて、品質管理の基準がないことだ。 「良ければ」といっても、何が良くて何が良くないのか。 シーンチェンジとクチパクがコンフリクトするときの扱いは前にメモしたが、もっと一般的に。 シーンチェンジと字幕の同期の問題では何フレーム、オーバーラン、アンダーランしているか、とか声との前後関係とか、判断の基準があり、それをアプリで分析できるのに引き換え、リップシンクは「勘を働かせる」のを助けているに過ぎなかった。

次の方法がこの問題のブレークスルーとなった。Sub Station Alpha の [D] キー([!] ボタン)と同種のアイデアだ。

  1. 口が最初に開くフレームに移動し[F]で「そこから0.5秒再生」。
  2. それで良ければ、[F]を押したフレームの時刻は既にクリップボードにコピーされているから貼り付けるだけ。ちなみに0.5秒再生すると自動的にちゃんともとのフレームに巻き戻る。

ステップが大幅に効率化しただけでない。0.5秒という定量的なパラメータが入っている。 [F]で「そこから0.5秒再生」したとき、0.5秒待ってもまだ声が始まらないなら、クチパクが早すぎるので合わせるのはどうかという場合だし、[F]で「そこから0.5秒再生」したとき、再生したとたんに声が既に始まっているとしたら、クチパクが遅すぎるので合わせるのはまずいことが分かる。勘に頼らず品質管理ができる。 同様に、[A] キーでは「0.5秒前からそこまで再生」になり、開始時刻の前に声が出ていないかのチェックに使える。 また、[F]と[A]を逆に使えば、終了時刻(口が閉じる時刻)と同期するかどうかの判断にも使える。 (ただし、最後の音が mmm などのときは口が閉じてもまだ声があって正常なので、そのへんは臨機応変に。)

0.5秒が絶対的な限界値という意味ではないが、0.5秒だけプレビューすれば耳分量でどのくらいずれているか判断できるはずだ(例えば0.5秒の半分以下とか、3/4程度とか)。そこから自分の基準でやればいい。

0.5秒だけ動画を再生する、というだけで、 音声タイミングツールだとありがちなような気もするが、 この [F] / [A] の機能はリップシンクに限らず、いろいろな同期の確認で思った以上に便利だ。 確定のショートカットキーでASSファイルを直接書き換えればもっといいのだが、 それはまだv0.1のヘルパーツールなので…。目視で合わせていた昔に比べれば(シーンチェンジとのずれを見切るのがせいいっぱいで、クチパクどころでなかった)これでもずいぶんな進化だ。

メモ2: 2008-05-24 字幕のスタートタイムとシーンチェンジとリップシンク(クチパク)

字幕のスタート、エンドとシーンチェンジの接近には4通りのパターンがある。 この4パターンの処理については、中級編などで何度か書いたが、 このメモでは「字幕のスタートがシーンチェンジ直後になる場合」つまりa3rの「SECTION 3: Start Overruns」について、 さらに「閉→開」のクチパク(リックプシンク)が絡んできたときの扱いを考えてみたい。

基本を振り返ると、 対音声で適切に(=少し早めに)同期した字幕のスタートタイムが、 対映像でシーンチェンジの直後、約200 ms以内のときは、 基本的には、字幕をさらに少し早めに出してシーンチェンジ(以下SCと略)に同期させた方が良い。 24000/1001 fpsでは具体的にSC+1フレーム~SC+4フレームの4つのフレームが該当する。 +5フレーム(209 ms)も可能だが、あまり必要ない。

このようなシーンチェンジの直後にキャラが口を開くときは、どうしたらいいか。 例えば、対音声のみならず、リップシンクも「SC+3フレーム」に字幕開始を示唆しているときも、 上記の基本通り「SC+0フレーム」まで3フレームずらすか。

字幕のリップシンクは確かに魅力的だ。特に音声とパクが合っている新作の場合、重要な考慮事項だ。 ところが、上記のシチュエーションでは、音声もリップシンクも両方「SC+3」を指しているときでも、 スタートタイムはやはり「SC+0」に戻した方が良いことが多い。 特に前の字幕のエンドが「SC+0」のとき、3フレームだけ字幕を消すのは、 多くの場合、ちらついて汚い。

  1. 音声に合っているパクに字幕を合わせるのは良い(推奨)
  2. しかしパクとシーンチェンジが4フレーム以内で競合したときは原則、パクよりシーンチェンジを優先

一般にシーンチェンジの明度変化の方がクチパクのモーションより大きいので、 字幕もそれに従う。 具体的に、シーンチェンジから3~4フレーム以内では画面上での小さなクチパクに字幕開始を同期させない方がいい。

例外として、シーンチェンジでなくパク側に合わせる可能性があるのは、

「可能」「文脈」「意図」は主観的な判断で結局好みの問題となる。

いずれも、「SECTION 5: Inter-Sub Over/Underruns」で200 msの警告が出ない範囲を目安とする。 字幕なし状態は、なるべく一瞬でなく、5フレーム以上連続になるようにする。 ただし、4フレームだけ消えるのは、理由があれば良い。 3フレームだけ消えるのも、特に理由があれば良い。 1または2フレームだけ消えるのは、特別な場合以外、避ける(前の字幕のエンドを1~2フレーム遅らせるか、 次の字幕のスタートを1~2フレーム早めてギャップをなくすか、または、逆にギャップを十分に拡大する)。

注意: 時間的に前後の字幕の間で1~2フレームだけ字幕なし状態になるのも、 カラオケなどで「歯切れの良い視覚効果」を狙う場合や、 映像タイミングの関係で必要な場合は、ありうる。 普通の字幕の場合も必ずしも間違いではないが、分かっていてやるのでなければ考えずに機械的に避けて良い。

新作でもすべてのパクが理想的に合っていないので、ケースバイケースで判断する。 クチパクより声が数フレーム遅れているのはかえって都合いいが、 クチパクより声が数フレーム早いときはリップシンクしない。 逆にあまりパクが合っていない旧作でも、たまたまパクが理想的になっている場所では字幕側からもそのタイミングを利用して良い。

一般的注意: 「LAMEタグで24 msずれる問題」は絶対に回避する。 「MP3自体のエンコードで約23 msずれる問題」もWAV側で冒頭無音を23msほど削れば回避できる。 理論は分からないが経験上48000 Hzは約23 ms、1105サンプル遅れる。 両方放置するとタイミングが47 msつまり1フレーム以上狂い正常にフレームタイミングできなくなるので注意。 この問題は既に何度も書いたが、デフォルト設定でこうなってしまいフレームタイミングに影響する落とし穴だから、 注意喚起のため繰り返しておく。 動画の場合、VBRタグがないのが一番良いが、あいにくVBRタグが存在してしまっているときは、 それを解釈しないでデコードしないとDirectShowと合わない(つまりこの用途では変換にfoobar2000を使ってはいけない)。 さらに「Time From WAV」は必ずヘッドフォンで行う。スピーカーが3メートル離れていると音速の関係で10 ms({\K1})音ズレするので注意。 逆のずれ方(再生時にスピーカーの位置により音側が微妙に遅めになる)はあまり気にならないが、 カラオケで字幕側の色変化が音より遅れるのはほんのわずかでも心地悪い。

この記事のURL

パブリックドメイン


[ASS] 縦カラオケ

2008年 7月15日
記事ID d80715

縦のカラオケは横より読みにくく、必ずしも好ましいものではないが、 アイキャンディーとしてたまには作ってみたいという要望はあるだろう。

縦カラオケの生成は自動化可能だが、とりあえず手動でやってみた。 自動的にやる方法は次のセクションで説明するが、繊細な微調整には原理の理解が必要であり、一度は手動でやってみるといいだろう。

カラオケではない普通の縦書き字幕regular [non-karaoke] vertical subs)については、別記事参照。

手動でやる方法


サンプル画像(640x480)
作例ASSスクリプトとサンプル動画 (3.9 MiB)

恋するオンライン
作詞:クラムチャウダー・シベリア・アタック
作曲:秋山浩司
曲のライセンスがcc by-nc-saのため、自動的に上のサンプルも同じライセンス。 カラオケの説明用に使えるパブリックドメインのいいサンプルがないすかねぇ。。

画像を90度回転させた絵に@フォントで普通にカラオケしたら簡単なのでは? という気もするが、 ここではRTLにも適用できる一般的方法で。いずれは自動化されるべきだが、 それにはアルゴリズムを検討する必要がある。 手順としては、

  1. 普通のカラオケ作成後、トークンの時間リストを作る
  2. @フォントを指定し90度回転
  3. トークン境界のY座標を調べt-clip化
  4. レイヤー処理と必要なら微調整
  5. ルビ処理

トークンの時間リストはプログラム的に容易に自動化できるものだし、 Y座標を調べて個々にt-clip化しなくても、そのリストにY座標の要素を新たに追加して一括変換した方が効率的だろう。 しかしまずは勉強のため、全部手動でやってみた。

注意1: ルビなしでいいなら4ステップで完成する手順にしてある。 実際には、Y座標調べの前にルビ配置まで決定しておくほうがいい。 それですべてのルビハング(後述)が解決するわけではないが、 見通しは良くなる。

注意2: すべてのt-clipは、 最終結果のピクセル位置、場合によってはサブピクセル位置に依存し、 したがって物理フォントと、論理フォントと、レンダラーに依存する。 (1) 本例は @DHPGothic-EB (@DHP特太ゴシック体)を使っているので、フォントがないと位置が合わない。 (2) Windows XP は太字がない物理フォントの太字を論理フォントではエミュレートしてくる(品位は落ちる)ので、 太字がないフォントで太字を使うと、Windows 2000と位置が合わない。 (3) レンダラーはVSFilter2008年6月版で確認。

1: 普通にカラオケを作って、次のようにトークンをリスト化する。
Dialogue: 10,0:01:23.12,0:01:43.22,tatekara,,0000,0000,0000,,
{\K30}{\K115}世界の{\K50}終{\K80}わ{\K60}{\K80}りを{\K80} {\K70}待ち
{\K120}草臥{\K100}れた{\K135}僕らは

;世界の 300,1450
;終 1450,1950
;わ 1950,2750
;りを 3350,4150
;待ち 4950,5650
;草臥 5650,6850
;れた 6850,7850
;僕らは 7850,9200

簡単のため、トークンは大ざっぱに切り、タイミングも雑に50 ms単位。 適宜改行を入れている(以下同じ)。 リストは単純なもので、「世界の」の色変化開始がt=300、変化終了がt=1450といった意味。 「終」以下も同じ。Kの引数を足していった数値の10倍を書いているだけだからその気になれば、すぐ自動化できる。

2: @フォントを指定し90度回転させる

Style: tatekaraBg,@MS UI Gothic,
27,&H00ffffff,&H01ffff00,&H00000000,&H80000000,0,0,0,0,100,100,0,-90,1,1,1,7,600,0,30,128

太字が重要な場所で、@フォントは何でもいいが、上では例としてOSの付属品を書いている。 a3rのフォントビュアー([Ctrl]+[F])では、Ignore Symbol/Vertical/Rasterのチェックを外さないと縦フォントがリストされないので注意。 位置7で左余白をたくさんとって-90度回転させることで、右上からの縦書きを実現している。 回転前には字幕のほとんどがフレームの右端を飛び越えたオフスクリーン領域にはみ出していてそれを回転させることで正しい位置に呼び出しているわけだが、 オフスクリーン領域にはみ出しそうになると一般にワードラップがかかってしまう。それを無効にするために
WrapStyle: 2
とするか、あるいは各行に {\q2} を指定する。前者は1回指定で済むが、 一般の Dialogue と共存できなくなるので、 普通は {\q2} を使うと良い。

3: t-clipの理解と実践

縁ワイプのときはt-clipの意味までは理解しなくてもツールがやってくれたが、 縦カラはツール化してないので、t-clipを自分で書く必要がある。 作業のかなりの部分はやれば簡単に自動化できそうだが、まあ手動でやっても、 ほかの複雑なエフェクトと比べて特にしんどいものではない。 実際このサンプルは気まぐれに突然作り始めて、1時間ほどで完成した。

t-clip とは「長方形クリップ範囲を連続変化させることによる、カラオケと似た効果」のこと。 簡単にしくみを説明すると、

今「世界の」という語句が、左上隅(567,220)、右下隅(640,106) という長方形の範囲にあるとする。 このとき、{\clip(567,22,640,106)} というASSコマンドは、この領域だけを描画し、領域外を(本来ならそこに字幕の文字があったとしても無視して)描画しない、 という意味になる(グローバルな設定ではなく、そのコマンドがついているDialogueに対する指定)。ここでもし、ボトムY座標の106を例えば56に減少させて、 {\clip(567,22,640,56)}と書けば、56ピクセルまでしか字幕が出ないことになる。 さらに、ボトムY座標をトップY座標22と等しく{\clip(567,22,640,22)}と書いてしまえば、選択範囲は高さ0で、 要するに何も描画されない。この「何も描画されない状態」から「世界の」だけが描画される状態へと連続変化させれば、 「世界の」が端からだんだん見えてくることになる。その変化の時間タイミングは、既に調べたように
;世界の 300,1450
であるから、
{\clip(567,22,640,22)}{\t(300,1450,\clip(567,22,640,106)}世界の終わりを 待ち草臥れた僕らは
と書けば、高さ0の何も描画しない状態で初期化してから、(567,22,640,106)へ描画範囲を空間的に移行させる意味になる。 この空間的移行は時間的にt=300で開始されt=1450で終了する(\t コマンドになじみがないかたはass-specs.doc参照)。 空間軸と時間軸の両方をコントロールすることに注意。

これによって「世界の」のカラオケ変化をt-clipに置き換えることができた。 詳しく言えば「カラオケ変化後の色」をt-clipに置き換えたわけで、 「変化前の色」については別のレイヤーで処理する。変化前については、原理的には変化後と逆に動くt-clipで処理すればいいわけだが、 簡単には単にスタティックに出しっぱなしにして、「変化後」のレイヤーが上に出現することで結果的に隠されるようにしてしまえばいい。 本例ではそのアプローチを使う。 ただし、アルファチャンネルがからむときは、例えば半透明の文字が上に乗っても下が隠れてくれないので、 このアプローチは使えない。 アルファチャンネルを使うときは下のレイヤーも逆に動作するt-clipにてダイナミックにする必要がある。 典型的にはシャドーはアルファ0x80になっているので、注意を要する。

上の数値例では、長方形の右辺は必要以上に大きめにとってある。これは後からルビをまとめて面倒見るため。

;世界の 300,1450
;終 1450,1950
;わ 1950,2750
;りを 3350,4150
;待ち 4950,5650
;草臥 5650,6850
;れた 6850,7850
;僕らは 7850,9200

以下同様に「終」「わ」「りを」などもt-clipで書き換えていくわけだが、この場合、長方形の左、右、上は一定で、 下が伸びていくだけだ。変化しない場所はコピペで済まそう。 {\t(,,\clip(567,22,640,)} をトークンの数だけコピペする。

{\clip(567,22,640,22)}{\t(300,1450,\clip(567,22,640,106)}
{\t(,,\clip(567,22,640,)}
{\t(,,\clip(567,22,640,)}
{\t(,,\clip(567,22,640,)}
{\t(,,\clip(567,22,640,)}
{\t(,,\clip(567,22,640,)}
{\t(,,\clip(567,22,640,)}
{\t(,,\clip(567,22,640,)}

あとは、時間の引数二つとclipの第4引数だけを埋めればいい。 時間の引数はリストにあるt値をそのまま書くだけだ。問題は各トークンの下の端のY座標の取得だ。 多状態カラオケと同じアルゴリズムで自動でスキャンできるはずだが、今は手動でやる必要がある。 a3rで拡大鏡を見ながら、トークンの境界を調べよう。 文字間に余裕があるときは、空白部分のどこでもいいのだが、文字がくっついているとき、 1ピクセルでも足りないと色が変化しきらないし、1ピクセルでも超えると次のトークンまで色がはみ出るので、 慎重に。a3rで\posを取得するのは[Alt]+ClickまたはMiddleClickだが、[Tab]+Clickで裸のx yが取れるので、 これを貼り付けてから前半のxを消すと良い。 (v0.1-test32以降(v0.0.9.58 = test32+ を含む) でテストとして [Ctrl]+[Alt]+[Shift]+右クリック でY座標だけクリップボードに送るようにしてみた。)

追記: test38以降では、Options | Mouse Click メニューから選択することで修飾キーなしのクリックだけで、 「左クリック=X座標取得、右クリック=Y座標取得」にできる。

参考: t-clipと似て非なるものにt-rがある。どちらも華やかなカラオケで使われるが、 t-rは時間位置の指定だけででき、Kカラオケから容易に生成できるのに対して、 t-clipは文字の空間位置を指定する必要があるので、一般に難易度が高い。 t-rは時間軸のエフェクト、t-clipは空間軸のエフェクト。 t-rは文字単位のエフェクト、t-clipは1文字をさらに分割できるエフェクトだ。

4: レイヤー処理とハング関係の微調整

「見えない状態からだんだん見えてくる」各行が用意できたら、XYの位置はまったく同じ場所のZ方向の下にまったく同じ文字で「最初から見えているレイヤー」を用意する。

まったく同じ文字なので、基本的には下のレイヤーは上のレイヤーに隠されて見えない。 ところが上のレイヤーは最初不可視で、だんだん出現してくるので、結果として下のレイヤーのスタイルから上のレイヤーのスタイルに徐々に切り替わるように見え、カラオケ効果が実現する。

最初から見えているレイヤーがカラオケの色変化前の状態、だんだん見えてくるレイヤーが色変化後の状態で、変化後には、 上のレイヤーが見えるようになったせいで下のレイヤーが見えなくなって、下の色が上の色で上書きされる。 2行目のクリップ領域右辺も、必要以上に大きめにしておく。 理由は同じクリップを使いまわしてルビも処理するため。というか、レイヤーを分離しているので、 全部のクリップで左辺は0、右辺はPlayResX(例えば640)にしても問題ないはず。 ここでは簡単のため上のレイヤーは影を落とさないで(全透過)影は全部下で出す。 言葉での説明は限界があるので、詳しくは実際のサンプルスクリプトと実例ビデオを参照。 前述のようにアルファがからむと一般に少し複雑になる。 本例では単純にするため、Z方向で重なる場所は完全不透明か完全透明かのどちらかにしている。

作例のフォントでは「オンライン」という文字の「ン」と「ラ」が接近しすぎていてオーバーハング気味になっている。 ちょうどトークン境界なので、「ン」の変化完了の副作用で「ラ」の頭がちょっと変化するか、 または副作用を避けるために「ン」が完全に変化しきれないか、ということになりかねない。 それを回避するため、
オン{\fsp1}ラ{\fsp0}イン
として1ピクセル水増ししてある。 「草臥れた」の漢字部分もルビ「くたび」が後からアンダーハング、オーバーハングしそうなので、 それを見越して微妙に字間をあけておいてもいいだろう(この作例ではその処理は省略)。

5: ルビつけ

ここまでくれば後はルビだけ。ルビは難しくない。

いろんなやり方があるだろうが、このようなt-clipの場合、いちばん簡単なのは(手抜きともいう)、 ルビを1行で記述して、同じt-clipをコピペして済ましてしまうことだ。上記のようにアンダーハング、オーバーハングがあるとルビ部分の色変化が微妙に整合しなくなる。よってルビ部分のt-clipは微調整してベースの漢字と独立のタイミングで動かすのが本来だが、 今は単に縦カラオケの概念説明なのでそこまではやらない。 ルビを1行で記述するのは、次のようにルビとルビの間に {\fscx???} {\fscx100} を置いて???を調整するといい。 時々 fscx を使わずにスペースを打ちまくる人がいるが、効率が悪い上にスクリプトの可読性が低下し、 おまけにスペースの整数倍でしか制御できないので繊細なポジショニングができない。 こういう場面では、小数倍が自在に使えるfscx+スペース、が定石だ。

注: トリッキーな書き方でいいなら、 {\fscx???} {\fscx} (引数なしでデフォルト復帰)でも良い。

Style: tatekaraBgRuby,@DHPGothic-EB,18,
&H00ffffff,&H01ffff00,&H00000000,&H80000000,
0,0,0,0,100,100,1,-90,1,1,0.5,7,600,0,30,128

せかい{\fscx450} {\fscx100}お{\fscx1750} {\fscx100}ま
{\fscx420} {\fscx100\fsp0.5}くたび{\fsp1}{\fscx675} {\fscx100}ぼく

このスタイル例ではデフォの文字間が1で、「くたび」はきついので文字間0.5に圧縮している。ルビも2レイヤーによって、 カラオケ効果を出す。 t-clipの左右を大きめにとったのが生きて、まったく同じt-clipのシークエンスをコピペするだけで完成する。 既に注意したように、実際には、このように使いまわすと、Y方向に色変化のハングが出やすい。 親文字に対してルビの文字数が多いと時間的に拡散しすぎるし、 漢字1文字にルビ1文字なら時間的に詰まりすぎる。 サンプルは、あくまで説明のための単純化した例で、模範的な作例というわけではない。 例えば「闇」のルビ「やみ」の「や」が大きくアンダーハングしており、 色変化が少し早すぎるのが目立つので、気をつけて見てみよう。 といっても、これはハングの問題を説明するのにもいいからと放置してあるだけで、 原因になっているt-clipのY座標パラメータを若干増減する(例えば5ピクセル変える)だけで簡単に解決する。

基本的には自動化できるとしても、細部にはいろいろと手動の微調整も必要で、 そういうときには低水準でスクリプトを直接いじれることも結局役立つだろう。 ツールは便利だし必要だが、高度に自動化されたツールに頼り切ると微妙な問題を回避できなかったり、 全般に型にはまったことしかできない結果にもなる。

補足: ルビを空間的にカラオケ制御するときのハングについて

ルビを時間的にKタグで制御するときはこの問題は発生しない。 t-clipで空間側から制御するときで、かつ親文字のt-clipを流用するときは、次の4通りの不整合が発生しうる。

正のオーバーハングとアンダーハング: ルビが長くて終端が最後の親文字の次の文字にまでかかっている(オーバーハング)と、 親の色変化でルビが変化しきらない。 同様に長いルビは始端が親文字の前の文字にまでかかるため(アンダーハング)、親文字が変化しない前に少し変化してしまう。

負のオーバーハングとアンダーハング: 短いルビ、特に漢字1文字に対するかな1文字や、 2文字以上の漢字を短いかなで読ませる場合、例えば「都会」と書いて「まち」とルビをふる場合、 ルビの始端が親文字より遅れ、終端が親文字より早過ぎる結果になる。

基本的にはルビ側t-clipの座標調整で解決できるが、極端な例では親文字側を多少ずらして位置調整を図る必要もある。 ルビとの関係で親文字側位置を微調整するのはルビレイヤーのt-clipのY座標を調整するのよりかえって面倒だが、 必要に応じて行えば、より美しい最終結果が保証される。

ルビでない本体の文字側が相互にくっつきすぎている(オーバーハング、アンダーハング)ときはYを調整することでは回避できず、 別途処理する必要がある。 本文で述べたように、fspを使うか、または細いスペース(fscx+スペース+fscx)を挿入する。

半自動の方法

2008-07-21 [ASS/Windows] 縦カラオケ生成の自動化 (1)

前回は縦カラオケを手動で生成した。 今回はこのうち「リスト」を作る部分と、「リスト」+Y座標からt-clip縦カラオケを作る部分を自動化する。 トークン位置のY座標は現時点では手動で取得するが(後述)、1行1分もかからないだろう。 全般にトリッキーな要素はなく、明快な作業だ。

必要ソフト: a3r v0.1.0.0-test33で実験的に対応(テスト不十分)。AviSynth と VSFilter 必須。

vkara1: 「リスト」作成

まずは縦にレイアウトした通常カラオケを作る(前回参照)。このままではレイアウトは縦だが色変化は横だ。 a3r の Tools | Karaoke | Vertical Karaoke (Semiauto 1) にてこのASSを読み込むと、 filename.ass に対して、filename~vkara1.ass という名で作業用ファイルが出力される。 Y座標を取り直すのは(1行1分もかからないとはいえ)できれば避けたいので、なるべく最終的な位置が決まってから行う。 トークンの切れ目で前後の文字が重ならないように最初から調整しておこう。

入力例:
...,,{\K30}{\K115}世界の{\K50}終{\K80}わ{\K60}{\K80}りを{\K80} {\K70}待ち
{\K120}草臥{\K100}れた{\K135}僕らは

出力:
;vkara; t1=  300, t2= 1450, [ 世界の ],     y1= , y2= 
;vkara; t1= 1450, t2= 1950, [ 終 ],     y2= 
;vkara; t1= 1950, t2= 2750, [ わ ],     y2= 
;vkara; t1= 3350, t2= 4150, [ りを ],     y2= 
;vkara; t1= 4150, t2= 4950, [   ],     y2= 
;vkara; t1= 4950, t2= 5650, [ 待ち ],     y2= 
;vkara; t1= 5650, t2= 6850, [ 草臥 ],     y2= 
;vkara; t1= 6850, t2= 7850, [ れた ],     y2= 
;vkara; t1= 7850, t2= 9200, [ 僕らは ],     y2= 
;vkara END;

出力のリストの意味は前回と同様だが、y座標の値(等号の後ろ)が空欄になっている。 さしあたって、ここは手動で埋める必要がある。

スキャン(手動)

リストのy2に各語句の下端のY座標を記入する。 最初のトークンだけは、上端のY座標y1も必要になる。 ASSファイルをa3r でプレビューして、該当ポイントを [Ctrl]+[Alt]+[Shift]+右クリックすると、Y座標がクリップボードに送られるので、 貼り付ける。 このステップはまだ自動化していないので手動で行う必要があるが、1行1分もかからないだろう。

X座標、つまりclipの幅はフレーム全体(左が0、右がPlayResX)に設定される。 (ASSのヘッダでPlayResXが未指定の場合は既定値640)

vkara2: 縦カラオケ生成

~vkara1.ass にリストのY座標を手動記入したら、 Tools | Karaoke | Vertical Karaoke (Semiauto 2) にてその~vkara1.ass を読み込むと、 ~vkara2.ass として t-clip による縦カラオケが生成される。ここから先は前回と同様で、 好みに合わせて下敷きレイヤーなどを自作すればいい。

要約

通常カラオケを作り、前回のように90度回転して縦配置にしたら、 半自動で効率的に縦カラオケ変換できることが分かった。手動操作の部分も、未実装だがやれば自動化可能だ。 多状態カラオケでは既に実装されており、技術的には、全自動化に特に困難はないだろう。 次回予定、縦カラオケのルビ処理。

参考: 縦の多状態カラオケ

vkara2を作るとき、vkara1のリストで最初のトークン以外でy1を指定しても無視される(多状態カラオケのFast modeと同様)。 この縦カラオケは、(単純縁ワイプと同じで)2色のトークンレスで実現されるからだ。 Kカラオケでは概念上「現在どの文字からどの文字までがアクティブ」というトークンの右境界と左境界(縦なら下境界と上境界)がある。 トークンの左境界から右境界へ、トークンごとに色変化が進む。 通常は左境界は意識されないがt-rを使えばそこにエフェクトの境目になる。

トークンレスというのは「どこまで色が変わったか」という一つの「前線」(カスプ)だけがあって、 トークン末尾側は特に処理しないという意味(要するに通常のKカラオケの見かけと同じ)。 多状態カラオケで Pure Tokenless オプションは左境界を使わないことを意味し、 逆にそのオプションを無効にすれば左境界を基準にセルを配置することもできる。

縦カラオケも実はトークン境界を入れて3色カラオケにすることはできる(アルゴリズム的にはまったく同じ手間)。 ただし逆に、3色、一般に3色以上の多状態のカラオケだからといって常にトークン境界を使っているわけではなく、 むしろトークン末を無視して単にカスプから等距離でセルを分割していくほうが一般に滑らかに見える。 t-clip ではトークン末を使うのも使わないのも、どちらも可能だ。

補足: 長方形領域を埋めていくことによるt-clipカラオケは、文字単位のKカラオケと完全にイコールではない。 特にオーバーハング、アンダーハングがあるとき差が目立つ。 文字単位のカラオケを完全にエミュレートするには、ハングについてはレイヤーを分けるしかないだろう。

2008-07-25 縦カラオケの自動化 (2)

縦カラオケのルビについて書く予定だったが、それ以前にツールにいろいろバグがあったので、 それを先に直した。 主な不具合は test33 の vkara1 で、カラオケのタグがカラオケ以外のタグを含んでいると、 おかしくなることがあったのと、小文字のkタグが時間的に正しく解釈されていなかったこと。 a3r test36で直したつもりだが、まだテスト不足。

vkara2 では下敷きレイヤー(スタティックでいい場合)を一応、自動生成。
;[Bg];Dialogue: ...
とコメントアウトされているので、使いたいときは、頭の ;[Bg]; を一括置換などで消去。ただし、 スタイルは自分で定義してください。 スタイル名は、上の乗る t-clip のレイヤーのスタイル名の末尾に Bg を付加したものになっています。例えば、入力が、 Karaoke1 というスタイルなら、Karaoke1Bg 。

縦カラオケは t-clip で実装しているので、通常のASS風カラオケも、縁ワイプも、どちらも同じ手間になる。 縁ワイプにしたいときは、例えば~Bのレイヤーのボーダーを薄くして、t-clipのボーダーを濃くそして/または太くするだけ。 縁を変えるかどうかとは別問題として、 アルファを使いたい場合は下敷きレイヤーもダイナミックにする必要があるが、それはまだ自動化してない。 ところで縦カラオケに限らず、ルビをきれいに配置するには親文字側の文字間を調整するほうがいい場合も多い(少ない漢字に長いルビが乗るような場合)。

2008-07-29 縦カラオケの自動化 (3) ルビの処理(ついでに縦の縁ワイプ)

JPEG画像
実物大画像
作例動画と使用したASSなど (7.8 MiB)

1回目は単純化して、ルビは親文字と同じt-clipを流用したが、微妙な問題があった。 今回の第2サンプルではルビをちゃんと処理しよう。

親文字・ルビとも適宜配置を決めてから、ルビはルビで別個にvkaraを適用することで、もっと柔軟に処理できる。 vkaraツールにはBOMを二重につけるバグがあったが、実用上問題なかった。Test39 で修正済み。 修飾キーなしでクリックだけで座標が取れるモード(Options | Mouse Click | L-Button for X...)や、 デフォルトより大きい拡大鏡が右側に表示されるモード(View | Compact Mode)を設定したので、 半自動t-clipはこれでだいぶやりやすくなるだろう。Compact Mode はこういう作業では地味に便利(Test 39a以降で機能)。

カラオケをゼロから作る全過程で発生したファイルを保存しておいたので(.7zに同梱)、 参考にしてください。

001-lines.txt
 歌詞のテキスト
002-timed-lines.ass
 歌詞のテキストを行ごとにタイムしたもの
 注: スタートタイムはぴったりに測る
003-tokens.txt
 歌詞をトークンにばらしたテキスト
004-timed-tokens.ass
 各トークンを1行としてタイムしたもの
 注: 一般にエンドタイムは要らない(次のスタートタイムで自動的に分かる)
005-crude-karabase.ass
 行タイミングとトークンタイミングを合成しただけのカラオケ
 注: a3rのShift+T
006-karabase-horiz.ass
 タイミングを調整・確定させ水平カラオケとしたもの
 注: 行をぴったりに測ったのでここでリードインとスイング
 アイキャンディーなのでスイング200msほど。(縦は実用向きでないが、
 実用カラオケに使うならもうちょっとスイングした方がいい)
007-karabase-vert.ass
 スタイルを変えて垂直に配置したもの
 注: 垂直にするとタイミングが分かりにくいので水平で確定させておく
008-karabase.ass
 ルビをつけてほぼ最終予定図にしたもの
009~VKara1.ass
 a3rが生成したvkara1にY座標を手動で書いたもの。
 手動といっても1行30秒くらい?
010~VKara2.ass
 a3rが生成したvkara2(一応完成)
011~VKara1.ass
 「オンライン」がつまりすぎてオーバーハングしたのでそこだけやり直し
012~VKara2.ass
 改めてvkara2
013~VKara1.ass
 Y座標の勘違いを一つ発見してその行だけやり直し
014~VKara2.ass
 改めてvkara2
015-final.ass
 仕上げ

t-clipの場合、縁ワイプもそうでないのも同じ手間なので、 今回は縁ワイプにしておいた。 1行でも2行でもほとんど同じなので、大は小を兼ねるで2行の作例を示してある。

AMV_vivian.mkv (14 MiB)

この記事のURL


[ASS] RTLカラオケ

2008年 7月31日
記事ID d80731

縦カラオケ(上から下)とRTLカラオケ(右から左)は、t-clipでは同じ手法で向きが違うだけなので、 縦カラの話が出たついでに、ここでちょっとまとめてやってしまおう。 縦カラが分かればすぐ分かることで、見本スクリプトだけあれば、説明不要と思う。 実際vkaraツールを使い回して作った。 利用価値はあまりないかもしれないが、古い軍歌か何かで、たまに右から左の横書きをやったら—例えば
本日大隊戰國愛
みたいな—面白いかもしれない。もちろん実用上は超歌いにくいだろうが、しゃれでw

今回は実用的に、普通に右から左に書くヘブライ語でやってみよう。 実用的といっても普通、ヘブライ語のタイプセットなどあまり機会がないと思うが、RTLの典型なので、 説明のための例ということで我慢してほしい。

ニクダなし
JPEG画像

ニクダつき
JPEG画像

実例とASSスクリプト: rtl_kara_(hebrew)_niqqud.7z 2.8 MiB

文字単位で考えるとニクダは難しいが最終表示形だけを考えるt-clipでは、特別なことはない。 ルビのような複雑な問題はない。 ただ慣れないとニクダの入力自体で戸惑うだろう。 EmEditorでやろうとしたらかなり駄目っぽいので、BabelPadで入力した。 普通はニクダは要らないだろうが、これは旧約の詩篇なのであった方がそれっぽい。

RTL言語の場合、エディタが対応しているとして、 左右の矢印キーの意味が変わる(→で次の文字へ行くわけだがつまり右に行く)のに注意。 それとヘブライ語の句読点、例えばピリオドは普通のASCIIピリオドでいいが、 行がピリオドで終わっている場合、そのままだとbidi境界が混乱して見かけ上、変な場所にピリオドが動いてしまう。 Unicode的にはピリオドのさらに後ろにRLMを置くという解決法がある。 論理的順序を無視して最初から表示したい位置に来るように句読点を置く(例えば「行頭」に感嘆符)という方法もある。 ヘブライ語やアラビア語とASSのタグを共存させるには、強引なようだが、場合によっては後者の方法も便利だ。 この例では両方のやり方を使っている。

この問題と2種類のアプローチについての詳細は、 「双方向アルゴリズム境界における句読点」(2003年3月)参照。

詩篇の表記はMechon-Mamreに準拠した。 ビデオはYoutubeより。 RTLカラオケの半自動化もa3rに追加する予定だ。 ヘブライ語はいいとして、アラビア語はかなりオーバーハング、アンダーハングがありそうで大変そう。 Gabestが新形式SSFに着手して、アラビア語のあたりで中断してしまったのが思い出される。 でもいつかはチャンレンジしてみたい…。

今回の話はあまり参考にならなかったと思うが、要するにt-clipのカラオケは、上下左右どっちに変化させるのも同じ手間、 ということ。 それと少ないレイヤーのt-clipは手動でもそんなに難しくないということも改めて強調したい。

この記事のURL


[ASS/SSA] MPC/VSFilterソフトサブ: 4aバグと回避

2009年 2月 7日
記事ID d90207

要約: Windows上のMKV再生で、 ソフトサブ字幕のタイミングが重なっているとき、 後から出る側の字幕の影の透過度が異常になることがある。 ハードサブは影響を受けない。

例と画像。作成時の回避法。デモ用サンプルファイル。

現象

異なるスタイルの字幕1、2が次のようにオーバーラップ(字幕2が字幕1の消える前に出て、字幕1の消えた後まで続く)するとき、 MKV埋め込みソフトサブ再生では、オーバーラップ中(AAA)に字幕2のシャドウ・アルファ(4a)が正しくないことがある。 4aはオーバーラップ解消以降(BBB)では正常に戻る。 どのような条件で発生するか正確には未詳。

時間 過去→未来
   11111
     222222
     AAABBB

TextSub呼び出しのハードサブや、 MPCで直接、外部ASSをロードしたときは、この問題は起きないから、恐らくMKVの問題。

実例

Style: style1,Verdana,50,
&H00ffeeff,&Hffffffff,&H00000000,&H80000000,
-1,0,0,0,100,100,0,0.00,1,1.00,10.00,2,20,20,20,0
Style: style2,Verdana,24,
&H0080ffff,&Hffffffff,&H80000000,&Hcc000000,
-1,0,0,0,100,100,0,0.00,1,0.75,1.50,8,2,2,8,0

Dialogue: 0,0:00:01.00,0:00:03.00,style1,,0000,0000,0000,,Ich will spielen!
Dialogue: 0,0:00:08.00,0:00:15.00,style1,,0000,0000,0000,,Ich will spielen!
Dialogue: 0,0:00:05.00,0:00:09.00,style2,,0000,0000,0000,,Los!

1秒から3秒まで、単純にIch…を表示。これが正常な状態。
PNG画像

8秒めに再び同じIch…が出るときは、5秒めから始まったLos!が表示中で、時間的にオーバーラップになる(位置が違うので空間的コリジョンはない)。 このときシャドウが濃すぎる。(輪郭(3a)も少し違うように見えるかもしれないが、輪郭を太くしてカラーピッカーで見るとRGBは一致した。)
PNG画像

9秒めにLos!が消失した瞬間、Ich…のシャドウが正常に戻る。 表示されているテキストのシャドウがここで急に変わるのが観察できる(サンプルMKV参照)。
PNG画像

この問題は、ASSファイル内での行の順序に影響され、 行の順序を変えることで、どの字幕のシャドウがおかしくなるか変更できることがある。 ASSファイル内のレイヤーには影響されない。 Subpicバッファの有効無効、 ScaledBorderAndShadowの有効無効、 スプリッターのGabest/Haaliの違いにも影響されない。 VSFilter/MPC内臓のいずれでも発生し、mplayer2, grapheditでも再現する。 レンダラーではなくMKV Muxerの不具合である可能性もある。 (Linux上で再現しないので恐らくMuxer側の問題ではない。)

透過度が不連続的に変わるのは、オーバーラップする先行字幕のエンドで、オーバーラップする後続字幕のスタートではない。 不連続的変化の前が異常で後が正しい状態。

回避方法

影響を受ける側(上の例のIch…)ではなく、トリガーとなる側(Los!)を、次のように2つのDialogueに分割することで回避できる。 分割点は、影響を受ける側のスタートタイム。 ASS内での形式上の分割で、 再生時の結果には通常まったく影響せず、実用上、ほぼ無害の回避方法と言える。 (オーバーラップができないOGMで擬似的にオーバーラップを作るとき使われた手法の応用。)

Dialogue: 0,0:00:08.00,0:00:15.00,style1,,0000,0000,0000,,Ich will spielen!
Dialogue: 0,0:00:05.00,0:00:08.00,style2,,0000,0000,0000,,Los!
Dialogue: 0,0:00:08.00,0:00:09.00,style2,,0000,0000,0000,,Los!

サンプル

VSFilter_4a_bug.7z (3 KiB)

中身
4a_bug.ass
4a_bug_quickfix.ass
bug_sample.mkv
quickfix_samplex.mkv

bug_sample.mkv で問題が再現するか見てください。 再現する場合、quickfix_samplex.mkv で問題を回避できるのか見てください。 埋め込んでいるASSも同梱してあります。 環境、mkvmerge v2.4.2; MPC 6.4.9.1 rev89; Windows XP SP2; VSFilter 2008-11-29; MatroskaSplitter 2008-12-10; Haali 2009-01-11。

追記

2009-02-08 複数のテスターにより再現性が確認された。 mplayerでは問題がないことから恐らくMPC/VSFilterの問題。 最近のバグではなく古いバージョンも影響を受ける。

2009-02-09 少し加筆(Linux上で再現しないので恐らくMuxer側の問題ではない)。

2009-03-03 a3r v0.1.1.0で、この問題の回避を支援する List Overlapped ツールと De-Overlap ツールを実験的に搭載した(Toolsメニュー)。前者は問題の原因になる可能性がある部分をリストアップする。後者は本文で説明した回避法を使ってASSを自動的に書き換え、新しいASSファイルとして保存する。オーバーラップ部分がフェイドなどを含む場合、若干の手動修正が必要になる場合がある。

この記事のURL

パブリックドメイン



メールアドレス(画像): [ http://www.faireal.net/image/2005/addr.png ]