mssoftjp_obsidian-voice-input/docs/PROCESSING_FLOW.md

12 KiB
Raw Blame History

Voice Input Processing Flow / 音声入力処理フロー

This document reflects the latest implementation as of 20250816. It covers the endtoend flow: recording, queuing, transcription, cleaning with safety guards, and optional dictionary correction.

本ドキュメントは 20250816 時点の実装に基づき、録音からキュー処理、文字起こし、セーフティ付きクリーニング、辞書補正までの一連の流れを記載します。

HighLevel Overview / 全体概要

  1. 音声取得 → 連続録音(最大録音時間到達または手動停止)。
  2. 録音ごとに audioBlob を非同期キューへ投入(録音は継続可能)。
  3. OpenAI Transcription API 呼び出しja/en/zh/ko には構造化プロンプト付与)。
  4. 機械的な TRANSCRIPT ラッパー除去 → クリーニング・パイプライン(安全判定付き)。
  5. プロンプトエラー検出(プロンプトのみが返った場合は空文字へ)。
  6. 任意の辞書補正を適用し、UIへ反映。

ASCII Overview / ASCII概要

           ┌──────────────────────────┐
           │  AudioRecorder (連続録音) │
           └─────────────┬────────────┘
                         │ audioBlob
                         ▼
           ┌──────────────────────────┐
           │ Processing Queue (直列化) │
           └─────────────┬────────────┘
                         │ audioBlob
                         ▼
┌──────────────────────────────────────────────────────────────┐
│            TranscriptionService.transcribeAudio()             │
├──────────────────────────────────────────────────────────────┤
│ 1) buildTranscriptionPrompt(lang)  ──► ja/en/zh/ko で付与      │
│ 2) POST (multipart/form-data)                                  │
│ 3) text 受領                                                   │
│ 4) preStripTranscriptWrappers(text)                            │
│ 5) StandardCleaningPipeline (安全判定付き)                     │
│    ├─ PromptContaminationCleaner構造/指示/文脈/スニペット)   │
│    └─ UniversalRepetitionCleaner反復・体裁                 │
│ 6) isPromptErrorDetected(text, lang)(プロンプトエコー検出)   │
│ 7) DictionaryCorrector任意                                 │
└──────────────────────────────────────────────────────────────┘

Recording Path Details / 録音パス詳細

実装参照: src/core/audio/AudioRecorder.ts, src/views/VoiceInputViewActions.ts, src/views/VoiceInputViewUI.ts

  • AudioContext 初期化
    • window.AudioContextSafari は webkitAudioContext)を使用。
    • AudioWorklet が利用可能ならワークレット、不可なら ScriptProcessor へフォールバック。
    • suspended 状態の場合は startRecording()resume() を実行。
  • フィルタ/ノード構成
    • MediaStreamSource → Gain → HighPass(約80Hz) → LowPass(約7.6kHz) → Analyser
    • ビジュアライザは Analyser に接続(シンプル/通常の2種
  • 連続処理
    • ワークレット/スクリプトプロセッサで 1ch PCM を取り出し、AudioRingBuffer に蓄積。
    • マイク実データ検知で onMicrophoneStatusChange('ready') 通知。
  • 録音制御
    • 既定は VAD 無効の連続録音。maxRecordingSeconds 到達で自動停止。
    • 二重開始は AudioRecorder.isStarting で抑止。UI側のロックはエントリポイントのみで軽量化。
  • UI/操作
    • 通常クリックで開始/停止。プッシュトゥトークは長押しで開始、離して停止(UI_CONSTANTS.PUSH_TO_TALK_THRESHOLD)。

Queue & UI / キューとUI

実装参照: src/views/VoiceInputViewActions.ts

  • 停止ごとに生成された audioBlobprocessingQueue へ追加し、逐次処理。
  • ステータス表示は「録音中/処理中/待機数」を反映。キャンセルは録音を中断して音声を破棄。
  • 途中で録音を継続しながら、既存キューをバックグラウンドで順次文字起こし可能。

Transcription Path / 文字起こしパス

実装参照: src/core/transcription/TranscriptionService.ts

  1. リクエスト作成(multipart/form-data
    • file: audio.webm(Blob), model: gpt-4o(-mini)-transcribe, response_format: json, temperature: 0, language
    • 言語に応じて構造化プロンプトを付与ja/en/zh/ko
  2. API レスポンスから text を取得。
  3. cleanGPT4oResponse(text, language) を実行。
    • 先に機械的に TRANSCRIPT ラッパーを剥離(完全/不完全タグ双方に対応)。
    • クリーニング・パイプラインを実行(詳細は後述)。
  4. プロンプトエラー検出
    • 言語別の検出ルールにより、プロンプトや注釈のみが返るケースを検知。
    • 検出時は空文字に置換して早期終了(無音/極短音声で発生しやすい)。
  5. 辞書補正(有効時)
    • DictionaryCorrector により語彙の統一・置換を実施。

Cleaning Pipeline / クリーニング・パイプライン

実装参照: src/core/transcription/cleaning/StandardCleaningPipeline.ts

  • 構成

    1. PromptContaminationCleaner
      • TRANSCRIPT/TRANSCRIPTION タグ残留、指示文(完全一致/スニペット/文脈)、フォーマット行の除去。
      • 空行/空白の正規化。
    2. UniversalRepetitionCleaner
      • 文字/文/列挙/段落レベルの反復抑制、末尾ハルシネーション緩和、体裁整形。
  • セーフティ(安全判定)

    • 設定値(src/config/CleaningConfig.ts
      • singleCleanerMaxReduction: 0.3(単一クリーナーの削減率上限)
      • emergencyFallbackThreshold: 0.5(緊急ロールバック閾値)
      • warningThreshold: 0.15(警告ログ)
    • 構造的クリーナー緩和(PromptContaminationCleaner に適用)
      • singleCleanerMaxReduction → max(0.9, 0.3) = 0.9
      • emergencyFallbackThreshold → max(0.95, 0.5) = 0.95
    • 超過時の動作
      • 単一上限single超過 → skip(そのクリーナーの変更を適用しない)
      • 緊急emergency超過 → rollback(そのクリーナーの結果を破棄して元のテキストに戻す)

例(ログ):

[Voice Transcription] [StandardCleaningPipeline] Rolling back cleaner PromptContaminationCleaner {
  reason: 'Reduction ratio 1.000 exceeds emergency threshold 0.95',
  reductionRatio: 1
}

意味: 構造的クリーナーが 95% 超の削減を行おうとしたため、安全装置によりロールバックされました。上流で「実発話が少ない/無い」状態(無音、極短、プロンプトエコー等)が疑われます。


LanguagebyLanguage / 言語別の違いと共通点

                 (選択された言語: ja / en / zh / ko)
                                 │
                                 ▼
             ┌──────────────────────────────┐
             │  構造化プロンプトの内容が言語別 │  ← 違い(プロンプト文面)
             └──────────────┬───────────────┘
                            ▼
┌──────────────────────────────────────────────────────────────┐
│ preStripTranscriptWrappers機械的ラッパー除去              │  ← 共通(言語非依存)
├──────────────────────────────────────────────────────────────┤
│ StandardCleaningPipeline                                      │
│  ├─ PromptContaminationCleaner                                │
│  │    ・instructionPatterns: 多言語ja/en/zh/ko            │  ← 共通(多言語対応)
│  │    ・snippet検出: EN/ZH/KO 追加語彙 + JA レガシー保護     │  ← ほぼ共通(内部最適化)
│  └─ UniversalRepetitionCleaner                                │  ← 共通(言語非依存)
├──────────────────────────────────────────────────────────────┤
│ isPromptErrorDetected(text, lang)                              │
│   ・各言語のエコー特有フレーズで検出                          │  ← 違い(検出語句が言語別)
├──────────────────────────────────────────────────────────────┤
│ DictionaryCorrector任意                                   │  ← 共通(言語非依存)
└──────────────────────────────────────────────────────────────┘
  • 違いlanguagespecific

    • プロンプト文面(buildTranscriptionPrompt)は ja/en/zh/ko で固有。
    • プロンプトエコー検出(isPromptErrorDetected)は各言語の固定句で評価。
    • スニペット検出は EN/ZH/KO の接尾語語彙を追加し、JA にはレガシーパターンを併用。
  • 共通languageagnostic

    • pre-stripラッパー除去は構造ベースで言語に依存しない。
    • クリーニング・パイプラインの安全判定single/ emergency しきい値)は全言語共通。
    • UniversalRepetitionCleaner と辞書補正は言語非依存ロジック。
    • API パラメータmultipart、temperature=0 等は共通model は選択式)。

注意: auto は廃止。UI/設定で言語を明示し、該当言語のプロンプトと検出ロジックを適用します。


Dictionary Processing / 辞書処理

  • 有効時、言語非依存で置換を適用。
  • 例:
{ from: ["AI"], to: "artificial intelligence" }

EN: "AI system" → "artificial intelligence system"
JA: "AIシステム" → "artificial intelligenceシステム"
ZH: "AI系统" → "artificial intelligence系统"
KO: "AI시스템" → "artificial intelligence시스템"

Status & Metrics / ステータスと計測

  • ステータス: 録音準備/録音中/処理中(待機数付き)/完了/エラー。
  • メトリクス: 音声サイズ、処理時間、原文/補正後の長さ、モデル、出力長などをログ出力。

Error Handling / エラーハンドリング

  1. API エラー: 401キー不正、429クォータ超過、5xxネットワーク/サーバ)
  2. プロンプト漏洩: 言語別検出 → 空文字化で軽減
  3. 空/無音: 早期終了で空文字返却、UIに短すぎ警告
  4. クリーニング安全装置: 過剰削減を検知してスキップ/ロールバック

Notes / 補足

  • 既定は VAD 無効の連続録音。必要に応じて maxRecordingSeconds を調整してください。
  • 連打・素早い操作でも安定するよう、開始の二重実行は内部ガードで抑止しています。
  • 「開始しにくい」挙動を避けるため、UIロックは最小限に留めています。