# dsh-voice-chat
δΈζ | English
A Doubao-style voice chat plugin for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Web GUI: click π€ and talk β the AI's reply is read back to you aloud. > π Full user manual: [MANUAL.md](MANUAL.md) (install / usage / configuration / FAQ / internals). ## Features - **Voice input**: click π€ to start listening (ding) β speak β auto-stops after 2.5s of silence (dong) β transcribed and sent; - **Voice output**: AI replies are synthesized with TTS and read aloud at +10% speed; a **condensed reading** option (off by default) can rewrite longer replies into a short spoken summary before speaking β **the rewrite follows the LLM actually selected in the current conversation**; - **ASR engines**: supports **SiliconFlow** (SenseVoice, free tier), **Groq** (Whisper), **Xiaomi MiMo** (chat/completions protocol), and **custom OpenAI-compatible** endpoints β switchable in settings; - **TTS engines**: supports **Edge TTS** (Microsoft, free), **Xiaomi MiMo TTS** (chat/completions protocol with built-in Chinese voices), and **custom TTS** (OpenAI-compatible API); - **Isolated engine configs**: every ASR/TTS engine stores its own Base URL / model / API key / voice, so switching engines never overwrites another one (legacy single-slot configs migrate automatically); - **Single-channel playback**: a new reply preempts the previous one; interrupt anytime via hotkey or button β only one voice at a time; - **No duplicate playback**: which replies were already spoken is remembered per session, so re-entering a session does not replay them; - **Mute toggle** π: while playing, click to mute immediately; click again to resume; - **Settings UI**: all settings live inside **DSH's built-in settings dialog** (gear icon β "voice chat" section), applied immediately β no restart needed; - **Hotkeys**: `Ctrl+Shift+Space` toggles the mic (alternates `Ctrl+M` / `Ctrl+Shift+M`). ## Requirements - **DeepSeek Harness (dsh)**: installed and running the Web GUI (`dsh web`); - **Node.js β₯ 22** (host and browser half; the edge-tts client runs on `ws`, no extra runtime needed); - **Browser**: Chrome / Edge (recording needs `MediaRecorder` support); - **ASR key**: required for speech-to-text (SiliconFlow offers a free tier; MiMo charges per usage). ## Install ```bash # Option 1 (recommended β published to npm): dsh plugin --profile web add dsh-voice-chat # Then restart dsh web ``` > Note: the plugin ships an inline edge-tts client (Microsoft Edge's free read-aloud service) β **no TTS API key is needed for Edge TTS**; MiMo TTS / custom TTS require their own keys. ## Configuration ### βοΈ Settings panel (recommended, highest priority) Open DSH's settings dialog (gear icon, bottom-left) β "**voice chat**" on the left β edit: **π€ Voice Recognition Settings** - ASR engine (SiliconFlow / Groq / MiMo / custom) - Base URL / model name / API key - Auto-send after transcription - Silence auto-stop duration (seconds) **π Readout Settings** - TTS engine (Edge TTS / MiMo TTS / custom TTS) - Per-engine Base URL / model name / API key / voice - Condensed reading toggle (off by default) > π **Per-engine isolation**: each of the 4 ASR engines and 3 TTS engines keeps its own > Base URL / model / API key / voice. Switching engines only switches which slot you are > looking at β they never overwrite each other, and saving only writes the slot being > edited. Legacy (β€0.3.x) single-slot configs are migrated automatically on first start > (MiMo voice β MiMo TTS, custom URL/key β custom TTS). Saving writes to `settings.local.json` and takes effect immediately. ### π Config file (lower priority) Override `config` by id in the profile's `~/.dsh/profiles/web/cordis.patch.yml` (all keys optional; defaults apply when absent): ```yaml - id: dsh-voice-chat name: 'dsh-voice-chat' config: asrEngine: siliconflow # siliconflow | groq | mimo | custom asrApiKey: sk-xxxx # ASR key (legacy single slot: applies to the active engine; or env var DSH_VOICE_ASR_KEY) asrBaseUrl: https://api.siliconflow.cn/v1 asrModel: FunAudioLLM/SenseVoiceSmall asr: # per-engine ASR config (takes precedence) custom: { baseUrl: http://127.0.0.1:8000/v1, model: whisper-v3, apiKey: sk-xxxx } llmModel: deepseek-v4-flash # rewrite model (fallback, follows current conversation) silenceMs: 2500 rewrite: false # condensed reading (default off; toggle in settings) ttsEngine: edge # edge | mimo | custom voice: zh-CN-XiaoxiaoNeural # Edge voice (same as tts.edge.voice) ttsBaseUrl: https://api.openai.com/v1 # legacy single slot: applies to the active engine ttsModel: tts-1 ttsApiKey: sk-xxxx tts: # per-engine TTS config (takes precedence) mimo: { baseUrl: https://api.xiaomimimo.com/v1, model: mimo-v2.5-tts, apiKey: sk-xxxx, voice: ε°η³ } custom: { baseUrl: https://api.openai.com/v1, model: tts-1, apiKey: sk-xxxx, voice: alloy } rate: '+10%' shortTextChars: 50 ``` Restart `dsh web` after editing. Priority: **settings panel > cordis.patch.yml (`asr.