Potato 2.7.1:文字起こしはもうできている
Potato 2.7.1は21種類の文字起こし・字幕形式をそのまま読み、メディアの隣にあるサイドカーファイルから読み込み、音声認識出力のフォルダをアノテーション可能なデータファイルに変える変換ツールも同梱します。
生の音声だけを持ってアノテーションツールにやってくる人は、ほとんどいません。みんな文字起こしを持ってきます。インタビューのフォルダにWhisperをかけた人。100件のカンファレンス講演から字幕を落としてきた人。2019年に終わったフィールドワークのプロジェクトからTextGridのコーパスを引き継いだ人。
そしてツールは、その人に変換スクリプトを書けと言うわけです。
Potato 2.7.1は、その手順をなくす話です。21種類の文字起こし・字幕形式をそのまま読み、すべてをデータファイルに貼り付けさせるのではなくメディアの隣に置かれたファイルから読み込み、最後にデータファイルを1つ作りたい場合のための変換ツールも入っています。
Potato 2.7.1
21種類を取り込み、1つのモデルとして出す
6種類からの増加です。全一覧は文字起こし形式のページにありますが、おおまかには、音声認識の出力が9種類(Whisper JSON、WhisperXほかの話者分離済みJSON、whisper.cpp、Whisper TSV、AWS Transcribe、Deepgram、AssemblyAI、Rev.ai、SPoRC)、字幕・キャプションが6種類(SubRip、WebVTT、SubStation Alpha、TTMLとDFXP、YouTube json3、YouTube srv1/srv2/srv3)、強制アライメント系が3種類(NIST CTM、Praat TextGrid、ELAN EAF)、そしてまったく別のところから来たデータのための汎用的な形が3種類です。
いちばん嬉しい追加はアライメント系の形式です。EAFとTextGridへのエクスポートはすでにあったので、階層アノテーションが往復できるようになりました。既存のアライメントを取り込み、Potatoで修正して、ELANやPraatに戻せます。
判定は拡張子ではなくデータの形で行われます。つまり captions.txt という名前のWebVTTファイルもWebVTTとして解析されますし、同じ文字起こしが埋め込みでもディスクからの読み込みでも、設定を変えずに機能します。
単語単位の時間とセグメントごとの信頼度は、元データにあれば保持されます。CTM、Deepgram、AssemblyAIのようにもともと単語単位の形式は、話者の交代と無音のしきい値でターンにまとめられます。
どの形式を入れても、出てくるのはこれ
サイドカーファイル
あなたの音声認識ツールは、すでに筋の通った配置でファイルを書き出しています。メディアがここにあって、文字起こしがその隣にある、という配置です。それをわざわざデータの塊に押し込ませる理由はなかったので、そのまま指し示せるようにしました。
{"id": "int_001", "conversation": {"audio": "media/int_001.mp3",
"transcript": "media/int_001.srt"}}パスは task_dir からの相対で解決され、他の設定パスと同じディレクトリトラバーサルの検証を通ります。データに本当にファイル名のように見える1行の文字起こしが入っている場合は、transcript_is_path: false でこの推定を切れます。
実務上の利点は、文字起こしがファイルのままでいられることです。差分を取り、作り直し、他の人に渡せます。JSONの配列の中に化石として埋まったコピーを持つ代わりに。
そうでない場合のための変換ツール
データファイルを1つ作りたいこともあります。potato transcripts はフォルダをglobし、各文字起こしをベース名でメディアに対応付け、ファイル名から項目IDを導き、結果を書き出します。
potato transcripts ./whisper_out --media-dir ./audio -o data/interviews.json--dry-run は何も書かずに、見つけたものを報告します。文字起こしが1つの塊として表示されてしまうときに、まず走らせるのもこれです。
Scanned 3 file(s):
interview_01.json Whisper JSON 42 turns 891.4s undiarized
interview_02.json WhisperX JSON 51 turns 1120.8s 2 speaker(s): SPEAKER_00, SPEAKER_01
interview_03.json Whisper JSON 38 turns 754.2s undiarized
3 item(s), 131 turn(s).
plain text と報告されるファイルは、ほぼ必ず .json の出力に混ざったWhisperの .txt です。.txt には時間情報がまったく含まれていませんし、モデルを再実行しないと取り戻せません。この1つの事実が、私たちのところに来る「文字起こしの表示がおかしいのはなぜか」という報告の大半を占めています。
--emit-config は、データファイルと一緒に対応する config.yaml を出力します。
4つのスキーマに共通の語彙
audio_dialogue、speech_transcript、voice_interaction、tiered_annotation は、以前はそれぞれ独自に文字起こしデータを解析し、受け付ける形式の範囲も違っていました。誰も説明できる理由なしにです。これらは同じ正規化処理を共有するようになったので、どれか1つが受け付ける形式は4つとも受け付けます。
既存の設定に影響はありません。各スキーマは以前の解析をフォールバックとして残していて、これまで動いていた文字起こしの形はどれもバイト単位でそのまま動きます。
tiered_annotation には、オプトインの文字起こしシーディングも入りました。transcript_field を文字起こしに向けるとティアがあらかじめ埋まった状態で届くので、アノテーターは音声を一から切り直すのではなく、既存のアライメントを修正することになります。
- annotation_type: tiered_annotation
name: tiers
source_field: audio_url
media_type: audio
tiers:
- name: utterance
labels:
- name: speech
color: "#7c3aed"あらかじめ入れた区間は、アノテーターが実際に編集するまで保存されません。手を触れていないシードが人の作業として誤って帰属されることはありません。
Potatoがいまもやらないこと
文字起こしはしませんし、話者分離もしません。音声認識は上流で走ります。Potatoは、あなたのパイプラインが出したものを読みます。
この話が出てくるのは、Potatoが実際にローカルのWhisperモデルを動かすからです。Think-Aloud モードで、アノテーターが作業しながら話す様子を記録するためのものです。あれはあなたのコーパスではなくアノテーターに向けた収録の機能です。同じ言葉で呼ばれる、別のものです。
単語単位の信頼度は、元データにあれば解析されてデータモデルに保持されますが、それを表示する画面はまだありません。
そしてパーサーがまったくない形式もあります。SAMI、MicroDVD、SubViewer、Transcriberの .trs、EXMARaLDA、CHAT/CHILDES、単体のRTTM、それにMontreal Forced AlignerとGentleのネイティブ出力です。これらは先に変換してください。この一覧を公開しているのは、何も除外されていない対応形式の一覧にはたいした価値がないからです。
ドキュメント
- 文字起こし形式 — 各形式とその判定ルール、正規化されたターンモデル、サイドカーの規則、設定キー、実際の症状に紐づいたトラブルシューティング
- Whisper の文字起こしをアノテーションする方法 — どの出力ファイルを残すべきか、そしてなぜ話者分離が別の判断なのか
- YouTube の字幕をアノテーションする方法 —
yt-dlpと、自動生成字幕でできること・できないこと - Transcript Format Ingestion — 6つの形式を並べた、そのまま動くデザイン
アップグレード
pip install --upgrade potato-annotation==2.7.1設定を変える必要はありません。Potatoがこれまで受け付けていた文字起こしの形は、どれもそのまま受け付けます。