Skip to content

TTS パイプライン

N.E.K.O. には OmniRealtimeClient の provider-native audio と、プロジェクトの external TTS runtime という2つの音声出力経路があります。本ページの queue/worker pipeline は後者であり、すべての音声セッションが使うわけではありません。

経路選択

LLMSessionManager._resolve_session_use_tts() が external runtime の使用を決定します。

状況音声経路
Text sessionExternal TTS runtime
対応 provider-native voice の audio sessionRealtime provider native audio
Custom/clone voice または指定 external provider の audio sessionExternal TTS runtime
Free realtime service の livestream routeServer-native audio
DISABLE_TTSDummy worker、音声なし

Voice routing は構造化された source/provider/reference、現在の model config、保存済み clone metadata を使います。Voice ID は provider をまたいで一意ではありません。

External runtime

text
LLM text delta
    │ provider class に応じた normalize / strip

thread-safe request Queue
    │ (speech_id, text) / control sentinel

provider worker thread
    │ provider protocol + source-rate conversion

thread-safe response Queue ──> async response handler

                                  ├─ JSON {type: "audio_chunk", speech_id}
                                  └─ following WebSocket binary PCM frame

Queue と daemon thread は LLMSessionManager ごとに所有されます。Provider protocol が異なっても worker signature は (request_queue, response_queue, api_key, voice_id) です。

Worker は大きく2種類です。

  • ws_bistream: long-lived WebSocket で text fragment と audio を双方向 streaming。Qwen、Step、CosyVoice など。Provider cadence を乱さないよう CJK whitespace normalization を省略します。
  • http_sentence: 清掃済み text を sentence 単位で synthesis request にします。OpenAI、Gemini、MiniMax、MiMo、Doubao など。

どちらも Markdown marker と括弧内 stage direction を発話対象から除外します。

Provider dispatch

main_logic/tts_client.get_tts_worker() はまず utils/tts/provider_registry.py から priority 順に special provider を選び、その後 native/core default に fallback します。

PriorityProvider選択条件
10GPT-SoVITS有効な local custom TTS
20vLLM-Omni明示 endpoint/model 選択
30MiniMaxClone metadata
40ElevenLabsClone/design voice metadata
50CosyVoiceClone metadata
60MiMoSelected preset または clone metadata
65Doubao TTSClone metadata

Special route がなければ Qwen、free service、Step、CogTTS/GLM、Gemini、OpenAI、Grok の core default を使います。Unsupported native combination は無関係な provider を呼ばず dummy worker に fallback します。

Selection と credential は同時に解決されます。Provider-specific API-key override により、別の TTS config slot の credential を誤用しません。

Streaming と完了

LLM delta は speech_id 付きです。Worker 未 ready 時は tts_pending_chunks に text を保存し、worker の __ready__ 後に順番どおり flush します。

Item意味
(speech_id, text)現在の utterance の text を合成
(None, None)現 utterance を finish/flush。worker は生存
("__interrupt__", None)現 synthesis を停止し late callback を mute
("__shutdown__", None)worker thread を終了

Done marker は readiness と pending-text flush の両方が満たされるまで遅延します。Speech-ID check により古い turn の done が新 turn を終了させません。

中断

新しいユーザー活動が現在の発話を preempt したとき、session/turn path が中断を開始します。汎用 provider on_interrupt callback に依存しません。

_clear_tts_pipeline() は response audio を drain し、live worker に __interrupt__ を送り、text normalizer/stripper を reset し、短時間 mute を待ってから late audio と pending text を再度クリアします。

Frontend には中断された speech_id を含む user activity も届き、正しい utterance の playback を停止できます。Mirror-speech が native-audio session でも external worker を保持し得るため、interruption gate は use_tts ではなく worker liveness です。

Audio contract とバックプレッシャー

Worker は response queue に入れる前に provider output を 48,000 Hz、mono、signed 16-bit little-endian PCM に変換します。多くの provider は 24 kHz ですが、GPT-SoVITS などは異なる source rate を使えるため、resampler は各 worker が所有します。

ブラウザは audio_chunk JSON header の次に raw binary audio を受けます。speech_id は header にあり PCM 内にはありません。

別系統の microphone input queue は最大300件で、満杯時に最古を捨てます。これは session input streaming 用で、TTS request/response queue とは別です。

エラー復旧

Worker は response queue から ready、reconnecting、warning、error を報告します。Runtime は credential rejection、rate limit、quota、policy block、connection failure などを分類します。

Retryable error は当初 silent retry し、繰り返し失敗後に frontend へ通知します。Non-retryable code は即時通知します。Delayed respawn は expected session/TTS mode を確認し、変更済み session の worker を復活させません。

Voice 作成と preview

Voice management は streaming synthesis と別です。

Endpoint用途
POST /api/characters/voice_cloneMultipart clone flow
POST /api/characters/voice_clone_directDirect/provider-specific clone
POST /api/characters/voice_design_previewElevenLabs design preview
POST /api/characters/voice_design_createDesigned voice の保存
GET /api/characters/voices有効な voice catalog
GET /api/characters/voice_previewProvider-aware preview

Clone endpoint は DashScope 専用ではありません。CosyVoice 国内/国際、MiniMax 国内/国際、ElevenLabs、MiMo、vLLM-Omni、Doubao TTS に対称な分岐があります。Remote voice ID を返す provider もあれば、reference audio をローカル保存して synthesis ごとに inline する provider もあります。

実装マップ

関心事File
経路選択、queue、中断、配信main_logic/core/tts_runtime.py
Provider dispatch/registrationmain_logic/tts_client/__init__.py
Provider workermain_logic/tts_client/workers/
Dispatch metadatautils/tts/provider_registry.py
Native voice routingutils/tts/native_voice_registry.py
Voice source storageutils/voice_config.py
Clone/design endpointmain_routers/characters_router/voice_cloning.py
Preview/catalogmain_routers/characters_router/voice_preview.py