前言¶
DeepSeek Harness(簡稱 dsh)的設計是「一切皆插件」:模型、工具、會話、UI 都可以往運行時上掛。終端裏的智能體默認還是打字進出——離開鍵盤時沒法口述一條指令,長任務跑完也只能回來盯一屏日誌。社區裏已經出現了不少視覺、瀏覽器類插件,語音這一側仍然要單獨裝。
dsh-voice 衝着這兩個日常缺口來:把口述音頻轉成用戶消息,再讓智能體把回覆讀出來。它不自己做一套音頻管線,而是疊在 dsh 已有的 ctx.shell、ctx.jobs、ctx.settings、ctx.attachments、ctx.conversationEvents 上面。本文按社區目錄頁、GitHub 倉庫 README / README.zh.md、package.json 與 cordis.patch.yml 交叉覈對後整理。需要先說明兩點:社區插件目錄是獨立站點,與 DeepSeek / 幻方沒有官方從屬關係;Harness 本身仍處於 developer preview,後續可能出現不兼容變更。GitHub 上還有其他同名 dsh-voice 倉庫,能力邊界並不相同,本文只寫 Jesse-njx 維護的這一份。
這是什麼¶
dsh-voice 是一款「工具與能力」類 DSH 插件,由 Jesse-njx 維護,許可證 MIT,主要語言 TypeScript。倉庫 package.json 中的包名是 @dsh-voice/bundle,版本號 0.1.0,要求 Node.js >=20。2026-08-18 覈實時,目錄頁與 GitHub API 均顯示 1 星;倉庫創建於 2026-08-13,社區目錄收錄日期 2026-08-14;topic 包括 deepseek-harness、dsh-plugin、stt、tts、voice。
一句話定位:語音筆記進去、朗讀答案出來。口述音頻會變成用戶消息(轉寫),智能體也可以把回覆讀出聲(合成);長任務、無界面運行還可以留下一句旁白。音頻默認是 ~/.dsh/voice/ 下的普通文件,會話日誌只保存引用和轉寫文本。
它解決的不是「對着麥克風即時聊天」。README 把 v0.1 的非目標寫得很清楚:不做即時流式對話、不做外呼語音電話、不做喚醒詞或常駐監聽,也不把原始音頻寫進會話日誌。錄音和播放都要等模型顯式調用工具,默認不會自己響。
核心功能¶
插件包註冊兩套工具、一個持久化事件、一個會話開關。Web 客戶端再補上音頻卡片。cordis.patch.yml 裏的插件 id 是 dsh-voice,name 爲 @dsh-voice/bundle。
transcribe:口述變成用戶消息¶
transcribe({ source, to? }) 做語音轉文字。source 必須二選一,不能兩個一起傳:
{ file: }:轉寫已經存在的音頻文件。{ record: { seconds? } }:從麥克風錄一段,默認 5 秒。錄音路徑要可用:ffmpeg,或 macOS 上捆綁的 swift shim。
轉寫結果插入爲用戶消息,不是工具輸出。會話裏會記一條 voice/note 事件,Web 端渲染成帶播放/暫停、時長、後端徽標和轉寫字幕的音頻卡片。工具本身返回緊湊句柄 { transcript, audioRef, backend, durationMs },方便 Code Mode 拿到結構化數據。
如果同時裝了 dsh-crosstalk,還可以帶 to:,把這條語音便籤作爲帶標籤的 peer 消息投到另一路本地會話,並附上音頻路徑。未安裝 crosstalk 時,這個參數不會出現。
speak:後臺朗讀,不阻塞當前回合¶
speak({ text, voice?, rate? }) 做文字轉語音。合成和播放走 ctx.jobs 上的後臺任務,kind 爲 voice-speak。工具立刻返回 { jobId, audioRef },不卡住當前回合;播放是異步的,失敗會注入一條通知,而不是把錯誤拋進這一輪對話。
每個後端都會先在 audioDir 寫下持久化文件,再盡力播放。因爲只是 ctx.jobs 上的普通工具,routines 和無界面(headless)運行也可以調用。README 把它同時當作長任務旁白:例如構建結束時報一句「構建完成,0 失敗」。旁白並不是另一套 API,就是在 job 上下文裏調用 speak。
/voice 與 readReplies¶
會話級開關,用來自動朗讀智能體的回覆。配置項 readReplies 默認 false;會話裏可以用命令即時改:
/voice on
/voice off
/voice status
/voice speak <text>
各條含義如下:
on:開始朗讀助手回覆。off:停止。status:查看當前開關、後端和audioDir。speak <text>:直接從輸入框朗讀一行,不必等模型調工具。
開關是當前會話生效,改完不用重裝插件。readReplies 只朗讀已有回覆,不會去錄音。
後端怎麼選¶
語音轉文字由 dsh-voice-backends 模塊負責選擇:
whisper-local:PATH 上的 whisper.cpp 二進制(也可在配置裏指定),經ctx.shell調用,完全離線。openai:走標準憑據通道訪問 OpenAI 兼容的whisper-1端點,密鑰環境變量是OPENAI_API_KEY。這是唯一會把音頻送出本機的 STT 路徑,而且只有顯式配置纔會啓用。macos:經捆綁的 swift shim 調用系統SFSpeechRecognizer,同樣走ctx.shell。不額外裝軟件,也不需要網絡配置。fake:文本到文本的測試夾具。文件內容是{"transcript": "…"},或文件名形如fixture-.m4a時,轉寫結果就是那段文本。給 CI 跑通整條工具鏈,不碰麥克風、不碰網絡。
文字轉語音:
say(默認):macOS 的say -o --file-format=m4af --data-format=aac,再用afplay播放。零安裝,寫出 Chrome / Safari 能播的 m4a。piper:本地 Piper 二進制,離線神經 TTS。edge-tts:雲端;只有寫進配置纔會用。fake:寫入固定 JSON,讓 speak 的產物能再走一遍 fake STT。
選擇規則是純函數,倉庫裏有單測:配置了哪個後端就用哪個;沒配則按離線回退,STT 是 whisper-local → macos,TTS 是 say → piper。雲端後端永遠不會被自動選中。本機既沒有 whisper.cpp / macOS 語音識別,也沒有 say / Piper 時,會給出明確報錯,告訴你該配什麼,而不是悄悄改走 OpenAI 或 edge-tts。
本地優先:文件在磁盤,日誌只留引用¶
設計中心是本地優先:
- 除非顯式設置
stt.backend: openai或tts.backend: edge-tts,音頻不出本機。 - 每個產物都是
audioDir(默認~/.dsh/voice/)下可直接查看、可rm的文件。 - 會話日誌只保存一條
voice/note:noteId、回合座標、audioRef(路徑 + mime + durationMs)、transcript、direction: 'in' | 'out'、backend。v0.1 沒有更新事件。 - 音頻文件缺了或被刪掉時,Web 卡片降級成只顯示轉寫文字。回放不需要再讀一遍音頻文件。
Web 客戶端把入站便籤(STT)畫成用戶回合,把出站 speak 畫成智能體側卡片。客戶端 bundle 由 scripts/build-client.mjs 打成 lazy-CJS,安裝到 web profile 後經 /plugins/@dsh-voice/bundle/client.js 提供。
安裝與啓用¶
社區目錄頁給出的安裝命令如下,在 DeepSeek Harness 終端中運行即可:
dsh plugin add github:Jesse-njx/dsh-voice
需要可復現安裝時,按目錄頁說明把 commit 哈希釘上:
dsh plugin add github:Jesse-njx/dsh-voice#<commit>
把 <commit> 換成倉庫裏實際的 commit SHA。
倉庫 README 另外寫了按 npm 包名、並指定 web profile 的安裝方式:
dsh plugin --profile web add @dsh-voice/bundle
截至 2026-08-18,npm registry 上查不到 @dsh-voice/bundle(返回 404),不要把這條當成當前可用的安裝方式。安裝仍以目錄頁的 GitHub 命令爲準。README 帶 --profile web,是因爲網頁音頻卡片要裝進 web 客戶端;目錄頁命令本身不帶 profile。裝完如果對話裏看不到音頻卡片,需要確認當前用的是帶 Web UI 的 profile,而不是隻裝了 host 工具。
目錄頁的安全提示仍然適用:插件以當前 dsh 進程的權限運行,安裝時可能執行代碼。裝之前請自己看源碼和許可證。package.json 的 prepare / prepublishOnly 會執行 pnpm build。裝完可用插件列表確認是否出現 dsh-voice;有的環境需要重啓 Harness 後才生效。在模型調用工具之前,錄音和播放都不會自己開始。
配置¶
所有字段都可選,寫在 profile patch 或 cordis.patch.yml 裏。README 給出的完整形狀如下:
plugins:
dsh-voice:
stt:
backend: whisper-local | openai | macos | fake
model: whisper-1
whisperLocal: { bin: whisper-cli, model: tiny }
openai: { baseUrl: https://api.openai.com/v1, apiKeyEnv: OPENAI_API_KEY }
tts:
backend: say | piper | edge-tts | fake
voice: Samantha
rate: 180
piper: { bin: piper, model: /path/to/model.onnx }
edgeTts: { voice: en-US-GuyNeural }
readReplies: false
audioDir: ~/.dsh/voice
缺省行爲:STT 自動選離線後端(whisper-local → macos),TTS 默認 say(自動回退時是 say → piper),readReplies 爲 false,音頻目錄是 ~/.dsh/voice。openai 的密鑰走標準憑據通道 OPENAI_API_KEY,並回退到啓動環境變量。倉庫自帶的 cordis.patch.yml 只插入空的 stt / tts、readReplies: false 和默認 audioDir,具體後端留給使用者自己覆蓋。
典型用法¶
倉庫沒有編造對話腳本,可復現的入口就是工具參數和 /voice 命令。
轉寫已有文件時,source 只帶 file;從麥克風錄幾秒則只帶 record:
{ "source": { "file": "/path/to/note.m4a" } }
{ "source": { "record": { "seconds": 5 } } }
讓智能體朗讀一段文本:
{ "text": "build finished, 0 failures" }
voice 和 rate 可選,不傳就用配置裏的默認音色和語速。
會話裏要自動讀回覆,直接輸入:
/voice on
看當前後端和目錄:
/voice status
推薦順序是:先確認本機有可用的離線後端(whisper.cpp 或 macOS 語音識別,以及 say 或 Piper),再用 /voice status 覈對,最後才讓模型調 transcribe / speak。不要一上來就把 stt.backend 設成 openai,除非你明確接受音頻離開本機。
適用場景與注意事項¶
比較適合這些情況:
- 暫時離開鍵盤,想口述一條指令,讓轉寫結果作爲普通用戶消息進入對話。
- 長構建、無界面任務跑完後,用
speak留一句旁白,不必盯着終端。 - 希望回覆被讀出來,但默認仍然是安靜的:用
/voice on按會話打開。 - 在意音頻落在哪:文件都在
~/.dsh/voice/,日誌裏只有引用和轉寫。
使用前建議把下面幾條當作硬限制,而不是「以後可能會好」:
- 權限與供應鏈。插件以當前 dsh 進程權限運行,能調 shell、能讀寫
audioDir、在配置了雲端後端時還能把音頻送出本機。安裝前檢查 https://github.com/Jesse-njx/dsh-voice 源碼和 MIT 許可證;需要可復現環境時固定 commit。 - 不是即時語音對話。v0.1 明確不做流式對講、喚醒詞、常駐監聽、說話人分離、外呼電話,也不把原始音頻寫入會話日誌。
- 默認後端偏 macOS。TTS 默認是系統
say;STT 自動回退鏈裏有macos。Linux 上通常要自己準備 whisper.cpp 和 Piper,否則會得到「該配什麼」的錯誤,而不會自動改走雲端。 - 錄音有前置條件。
{ record }依賴 ffmpeg,或 macOS 上的捆綁 swift shim。沒有錄音路徑時,這條分支不可用,但仍可用{ file }轉寫已有音頻。 - 雲端是顯式選擇。
openai和edge-tts只有寫進配置纔會啓用。裝完插件不等於已經把語音送到了第三方。 - 網頁卡片依賴 web profile。host 側工具和
/voice命令與 Web 音頻卡片不是同一半區。只在無 UI 的 profile 裏裝,看不到卡片是符合 README 描述的。 - 項目很新。倉庫 2026-08-13 才創建,版本
0.1.0,星標很少。README 寫測試套件有 46 個用例,覆蓋參數 schema、後端選擇、fake 端到端和卡片降級,但不要把它當成生產級語音套件。
小結¶
dsh-voice 給 DeepSeek Harness 補上了一層很薄的語音進出:transcribe 把口述變成用戶消息,speak 在後臺朗讀且不阻塞回合,/voice 按會話決定要不要自動讀回覆。音頻是磁盤上的普通文件,日誌只留引用;雲端後端不會被自動選中。它不是即時對講機器人,也不是微信語音方案;邊界寫在 README 的非目標列表裏,用的時候按「工具調用纔出聲、本地文件可刪除」來預期,會比較穩。
- 目錄頁:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-voice/
- GitHub:https://github.com/Jesse-njx/dsh-voice
- DeepSeek Harness:https://github.com/deepseek-ai/deepseek-harness