ストリーミングディクテーション

Parakeet-EOU-120Mは、Apple SiliconのNeural Engine上でリアルタイムディクテーションのために構築された、明示的な発話終端(EOU)ヘッドを備えた小型のRNN-TストリーミングASRモデルです。このガイドでは、ハンズフリーでどこにでもペーストできるディクテーションのために、ストリーミングモデルとSilero VADを結び付けたmacOSメニューバーリファレンスアプリのDictateDemoも説明します。

概要

アーキテクチャ

音声チャンクごとにパイプライン化された3つのCoreMLモデル:

コンポーネント説明
エンコーダーキャッシュ対応Conformer。64フレームのmelチャンク(640 ms)と6つの状態テンソル(アテンションKVキャッシュ、深さ方向convキャッシュ、チャンク境界を越えてFFTが連続信号を見られるように最近の過去の音声を前置するpre_cache mel ループバック)を取ります。
デコーダーシングルステップLSTM予測ネットワーク。前の非ブランクトークンを消費し、埋め込みと更新された(h, c)状態を出力します。
Joint + EOUヘッドエンコーダーとデコーダーの出力をvocab + blank + EOUに対するロジットに融合します。EOUクラスは、発話が終了したというモデルのハードシグナルです。

なぜ別のEOUトークンが必要か

通常のRNNTは無音中にブランクを出力し、デコーダーは「発話終了」のシグナルなしに喜んで吸収します。専用のEOUヘッドにより、モデルは部分結果を最終結果にコミットし、句読点/大文字小文字の状態をリセットし、アプリへのペーストのような下流アクションをトリガーするためのハードカットを行うことができます。

EOUは現実世界でノイズが多い

「無音」の休止中のキーボードクリック、マウスの動き、部屋のトーンが、Jointに時折非ブランクトークンを出力させ、EOUデバウンスタイマーをリセットしてコミットを停止させることがあります。本番パイプラインでは、Joint EOUを外部VAD駆動のforceEndOfUtterance()バックストップと組み合わせます — 下記のDictateDemoを参照してください。

モデル

モデルサイズHuggingFace
Parakeet-EOU-120M (CoreML INT8)約120 MBaufklarer/Parakeet-EOU-120M-CoreML-INT8

パフォーマンス

指標
ウェイトメモリ約120 MB (INT8)
ピーク推論メモリ約200 MB
チャンクレイテンシー (Mシリーズ)約30 msの計算 / 640 msの音声 (RTF 約0.056)
エンドツーエンドの部分結果レイテンシー約340 ms (1チャンク)
コミットレイテンシー (VADパス)音声停止後約1秒
計算ターゲットNeural Engine (CoreML)

クイックスタート — バッチ文字起こし

ストリーミングモデルはSpeechRecognitionModelにも準拠しているため、汎用STTモデルを受け取る任意のコードでドロップインとして動作します:

import ParakeetStreamingASR

let model = try await ParakeetStreamingASRModel.fromPretrained()
let text = try model.transcribeAudio(audioSamples, sampleRate: 16000)

クイックスタート — 非同期ストリーミング

for await partial in model.transcribeStream(audio: samples, sampleRate: 16000) {
    if partial.isFinal { print("FINAL: \(partial.text)") }
    else               { print("... \(partial.text)") }
}

PartialTranscriptは、textisFinalconfidenceeouDetected(Jointが発火したか強制確定されたか)、および単調増加するsegmentIndexを持ちます。

長寿命セッションAPI(マイク入力)

ライブディクテーションの場合、セッションを一度作成して、マイクから到着するチャンクを供給します。セッションは内部でバッファリングし、十分なサンプルが蓄積されるとエンコーダーを実行するため、任意のチャンクサイズをプッシュできます:

let session = try model.createSession()

// 各マイクチャンク:
let partials = try session.pushAudio(float32Chunk16kHz)
for p in partials {
    if p.isFinal { commit(p.text) }
    else          { showPartial(p.text) }
}

// ストリームが終了したとき:
let trailing = try session.finalize()

VAD強制確定パターン

パイプライン内でSilero VADがすでに実行されている場合、背景ノイズがEOUデバウンスタイマーを停止できないように、フォールバックコミットを駆動するためにそれを使用します:

if hasPendingUtterance && !vadSpeechActive && vadSilentChunks >= 30 {
    // Sileroあたり約960 msの持続した無音
    if let forced = session.forceEndOfUtterance() {
        commit(forced.text)
    }
    hasPendingUtterance = false
}

// ガードレール:JointがすでにEOUを発火した場合は二重コミットしない
if partials.contains(where: { $0.isFinal }) {
    hasPendingUtterance = false
}

DictateDemo — macOSメニューバーリファレンスアプリ

DictateDemoは、ストリーミングセッションの上に構築された完全なmacOSメニューバーagentです。バックグラウンドアプリとして実行され、ライブ部分結果でマイクから文字起こしし、EOUまたはVAD無音で発話を自動コミットし、結果を最前面のアプリにペーストします。

cd Examples/DictateDemo
swift build
.build/debug/DictateDemo

完全な実装はExamples/DictateDemo/DictateDemo/DictateViewModel.swiftにあります:ロック保護されたバッファを備えたメイン外の音声シンク、それを排出する300 msタイマーティック、残余サンプルキャリーオーバー付きSilero VAD、および保護付き強制確定。Examples/DictateDemo/Tests/DictateDemoTests.swiftの対応する回帰テストは、マルチ発話、スタックEOU、ノイズのある無音シナリオをカバーします。

ストリーミング vs バッチParakeet

Parakeet-EOU-120M (ストリーミング)Parakeet TDT 0.6B (バッチ)
ユースケースライブディクテーション、リアルタイムキャプションファイル文字起こし、オフラインジョブ
デコーダーRNN-T + EOUヘッドToken-and-Duration Transducer
チャンクサイズ640 ms ストリーミングファイル全体バッチ
ウェイトメモリ約120 MB500 MB
スループット約18倍リアルタイム約32倍リアルタイム
レイテンシー約340 msの部分結果ファイル終了時のみ
ストリーミングモデルを選ぶ条件…

…ユーザーが話し終わる前に部分結果が必要な場合。音声ファイルのバッチ文字起こしでは、大きなParakeet TDT 0.6Bの方がエンドツーエンドで高速で、より正確です。2つのモデルは同じSentencePiece語彙を共有しているため、トークン化を変更せずに交換できます。