字幕をテキストに変換 — SRT・VTT・SBV・ASS

SRT、VTT、SBV、ASS の字幕を整った書き起こしに変換します。タイムコードを取り除き、切れた文をつなぎ、自動字幕の重複を取り除きます。

字幕をテキストに変換する:タイムコードを外すのは簡単なほうの半分

字幕の形式はどれも同じものを符号化しています。タイムコードに留められた短い発話の断片です。それを読める文章に戻すのは五行のスクリプトで済みそうに見えます。数字を消し、矢印を消し、残りをつなぐだけです。実際の字幕ファイルにそのスクリプトをかけると、「ほぼ正しい」ものが出てきます。これは明らかに間違っているより厄介です。読まないと気づけないからです。

壊れる原因は二つあります。字幕は文を終えるためではなく画面に収めるために改行されているので、素直につなぐと数語ごとに刻まれた文章になります。もうひとつ、自動生成の字幕は流れるように出るため同じ語句が複数のキューにまたがって重複し、連結するとすべての文が二度も三度も現れます。このツールは両方を扱います。上でファイルをアップロードするか貼り付ければ、結果はこのブラウザタブの中ですぐに出ます。

流れる重複という問題

ここで多くの人がつまずきます。YouTube をはじめとする多くのライブ字幕は、区切られたテキストのかたまりを出しているのではありません。出しているのは動く窓で、視聴者には語が積み上がって見えます。ファイルの中ではこうなります。

  • キュー 1:井の中の蛙
  • キュー 2:井の中の蛙大海を
  • キュー 3:大海を知らず

何も考えずにつなぐと「井の中の蛙井の中の蛙大海を大海を知らず」——十九文字になりますが、実際に話されたのは十一文字です。一時間の講演ならおおよそ三倍の長さになり、読むにも検索するにも要約するにも使えない文字起こしができあがります。

対処は、各キューが新しく足した分だけを残すことです。新しいキューごとに、これまでのテキストの末尾であると同時に新しいキューの先頭でもある最長の並びを探し、それを落とします。上の例に当てはめれば「井の中の蛙大海を知らず」がちょうど一度だけ復元されます。比較は文字起こし全体ではなく直近の限られた窓に対して行うので、三時間のファイルでも速く、二十分後に正当に繰り返された言い回しを消してしまうこともありません。

文をつなぎ直す

字幕の一行は画面に合わせた寸法です。おおよそ四十文字、一度に二行、テキストが端に届いたところで折り返されます。ひとつの文が三つ四つのキューにまたがるのは日常茶飯事です。一キュー一行のままにすると、技術的には確かに文字起こしだが実際には読めない文書ができます。

段落モードはキューを溜めていき、二つの条件が揃ったところで区切ります。段落として十分な量が溜まっていること、そして現在のキューが文末の句読点で終わっていること。こうすれば区切りが考えの途中に落ちることはありません。加えて上限で強制的に区切ります。句点をなかなか打たない話し手は実在しますし、切れ目のない文字の壁もまた別の意味で読めないからです。話し手が変わったところでは必ず段落を改めます。インタビューやパネルではこれが効きます。

四つの形式、ひとつの考え方

形式は拡張子ではなくファイルの中身から判定します。字幕ファイルは頻繁に名前を変えられますし、SubRip のデータが入った .txt はよくあるからです。

  • SubRip(.srt)——通し番号、小数点にカンマを使うタイムコードの範囲、そしてテキスト。最も多く作られていて、最も単純な形式です。
  • WebVTT(.vtt)——ブラウザの標準。小数点はカンマではなくピリオドで、加えて発話ではない NOTESTYLEREGION のブロックを置けます。これらは解析前に取り除きます。VTT はインラインの記法も許します。<v Speaker> は誰が話しているかを示し、<c.classname> はスタイルを当て、キュー内の裸のタイムスタンプはカラオケ風の語単位のハイライトを駆動します。いずれも展開し、voice タグは話者ラベルになります。
  • YouTube(.sbv)——カンマ区切りのタイムコード二つが一行にあり、その下がテキスト。通し番号も記法もありません。
  • Advanced SubStation(.ass と .ssa)——列の順序を宣言したイベントの一覧です。パーサーは位置を決め打ちせず、その Format: 行を読みます。Text フィールドが最後に置かれているのは、まさにそこにカンマを含められるようにするためです。波括弧のオーバーライドブロックはスタイル指定なので取り除き、\N の改行は空白にします。Name 列に値があれば、それが話者です。

話者、効果音、そして何を残すか

話者の情報は形式によって三通りの経路で届きます。ASS では専用のフィールド、VTT では voice タグ、そして SRT では行頭に 名前: と書くだけの慣習です。SRT には話者のフィールドがそもそも存在しません。三つとも認識し、同じ出力に揃えます。三つめの判定規則はわざと狭く取ってあります。行頭に名前らしい短い並びがあり、そのあとにコロンが続く場合だけです。ここを緩めると、コロンを含む普通の文まで拾って文字起こしを寸断してしまいます。

[MUSIC](laughter)[APPLAUSE] のような角括弧の音声キューは既定で残し、スイッチで外せます。どちらが正しいかは用途しだいです。検索できるアーカイブやアクセシビリティの記録としては内容の一部ですし、講演をモデルに要約させるならノイズです。

三つの出力の形

プリセットは実際に求められるものを押さえています。クリーンな文字起こしはタイムコードのない流れる段落で、読む・引用する・モデルに渡すのに向きます。タイムスタンプ付きは段落を保ったまま各段落に開始時刻を付けます。文字起こしが動画のある瞬間へ戻るための手段であるときに欲しいのはこれです。キャプション行は一キュー一行にタイムコードを付け、重複除去を行いません。元のファイルにいちばん近い形で、内容を通読するのではなく字幕そのものを点検したいときに役立ちます。

出力の横で、ツールは判定した形式、キュー数、語数、カバーしている時間、そして除去した重複の数を報告します。最後の数字がいちばん正直です。それが大きければ元が自動生成の流れる字幕だったということで、生のファイルのどれだけが繰り返しだったかがそのまま見えます。

ブラウザの外には出ない

字幕ファイルは常に公開のものとは限りません。インタビューの録音、社内の全社会議、法廷の記録、診察の記録、未公開の素材——どれも字幕を生みます。解析はこのタブの JavaScript が行うので、ファイルはローカルで読まれ、アップロードされることはありません。変換が一瞬で終わるのも、オプションを変えると往復せずにその場で描き直されるのも、同じ理由です。