v0.3.0 — 話者分離の本格化とスマホ対応 / Real diarization + mobile support
hayamimi 早耳 v0.3.0 — 話者分離の本格化とスマホ対応
複数人の会話で「誰の発言か」を自動で付ける機能を本格化し、スマホ(Flutter)でも動くようになりました。デモ動画の字幕と話者ラベルは、実際の会議音声(AMI Meeting Corpus、CC BY 4.0)に対する実出力です。
話者分離を本格化しました
これまでの --speakers は、発話ごとに声の特徴を比べて話者を切り替える簡易方式でした。READMEにも「フルの話者分離ではない」と明記していたとおり、複数人の会議では話者の取り違えが目立ちます。
v0.3.0では、清書(二段パス)のタイミングで発話グループ全体をあらためて話者分離モデルにかけ直し、その結果をセッション全体の話者ラベルに対応付ける方式にしました。速報の字幕はこれまでどおり即座に出て、少し遅れて出る清書側で話者の境界が正確になります。
実際の会議音声(AMIコーパス、4人会議×5本・計50分)で測定したところ、話者分離誤り率(DER)は従来方式の25.7%から13.9%に下がりました。清書ではグループ内の話者交代も復元されるため、短い相槌が別の話者として正しく分かれて表示されます。
追加で必要になるモデルは話者境界検出用の約7MB(pyannote segmentation-3.0、MIT)だけです。声の特徴抽出には従来と同じモデルを使い回すため、メモリへの影響はほとんどありません。速報字幕の応答時間への影響も平均50ms未満でした。
画面に表示される話者数が実際より多くなる問題には、一度しか現れないラベルを「S3?」のような仮表示にする対応を入れました。2回目の出現で確定表示になります。
スマホで動くようになりました
Flutter製のライブラリ hayamimi_core を追加しました。マイク→VAD→音声認識→清書のパイプラインを、他のアプリにそのまま組み込めます(スマートグラスのコンパニオンアプリ等を想定)。字幕イベントの形式はデスクトップ版・OBSオーバーレイと共通です。
iPhone 15の実機で速度を測定したところ、int8モデルの処理速度はPCの約4.8倍(RTF 0.013)でした。PCのx86では「int8がfp32より遅い」逆転がありましたが、ARMのint8カーネルが効くスマホでは int8 が最小かつ最速です。この実測を根拠に、推奨構成(ja単体 約72MB / 5言語切替 約396MB)をライブラリのREADMEに記載しました。
導入の手間を減らすため、モデルの自動ダウンロード機能(進捗表示・チェックサム検証・再実行時の差分取得つき)も追加しています。
修正した不具合
- 起動時に画面が固まることがある問題を修正しました。モデル読み込み(最大396MB)が画面の描画を止めていたことが原因で、読み込みを裏側(バックグラウンドisolate)に移しています。
- OSにマイクを取り上げられた時(バックグラウンド移行や他アプリの割り込み)に、無反応のままになるのではなくエラーとして通知するようにしました。
- ボタンの二度押しなど、開始・接続・破棄の二重呼び出しで起きるメモリリークや例外を防ぐようにしました。
--speakers使用時に、終了間際の清書が出力されずに失われることがある問題を修正しました。
精度改善の実験について(正直な報告)
話者分離の精度をさらに上げるため、閾値調整・割当ロジック変更・全体再クラスタなど8方向の実験を行いましたが、すべて採用基準に届きませんでした(現在の13.9%は現構成での実測上の最適値です)。どこが限界で、なぜかの記録は、失敗した実験も含めて docs/DIARIZATION_PLAN.md に残しています。残る最大の伸びしろは同時に複数人が話す「重なり発話」(約3ポイント分)で、回収できることは試作で確認済みです。今後の課題とします。
既知の制限
- 重なり発話(同時に複数人が話す区間)はまだ扱えません。
- スマホ版で、発話ごとの認識処理は画面と同じスレッドで動くため、発話のたびに0.1〜0.5秒ほど画面が引っかかることがあります(改善予定: #24)。
English summary
Speaker labels are upgraded from simple turn-taking to real diarization: the live path still assigns S1/S2/... instantly, and the refine pass re-diarizes each utterance group with pyannote segmentation-3.0 (~7MB, MIT) and maps the result back onto the session's labels. On 5 real AMI meetings (50 minutes total), DER dropped from 25.7% to 13.9%, with short backchannels now split correctly. One-off labels are shown provisionally as "S3?" until confirmed.
Mobile support lands as hayamimi_core, an embeddable Flutter library (mic → VAD → ASR → refine, wire-compatible subtitle events) with a model auto-download helper. Measured on a real iPhone 15: int8 runs at RTF 0.013, ~4.8x faster than the same files on a desktop x86 CPU — on ARM, int8 is both the smallest and the fastest choice.
Also fixed: a startup freeze (model loading now happens off the UI isolate), silent sessions after the OS revokes the mic, double-start/dispose leaks, and lost refine output at shutdown with --speakers.
Honest note: 8 further accuracy experiments (threshold sweeps, assignment changes, global re-clustering) all failed our adoption bar — the full record, negative results included, is in docs/DIARIZATION_PLAN.md. The remaining ~3pt headroom is overlapping speech, recoverable per our prototype; deferred to future work.
The demo video's subtitles and speaker labels are actual pipeline output on real meeting audio (AMI Meeting Corpus, CC BY 4.0).
🤖 Generated with Claude Code