前言¶
在 DeepSeek Harness(DSH)裏做智能體對話時,長回答往往要盯着屏幕讀。社區裏也有用 SKILL 走 Edge TTS 的做法,例如 multilingual-tts-audio:每次都要 uv run --with edge-tts python …,等整段 MP3 寫完,還要主動觸發,和模型輸出節奏對不上。
下面介紹插件 lemonhall/dsh-tts-reader(維護者 lemonhall,分類爲聯網工具):常駐 DSH 進程內,監聽模型原始輸出流,逐句向 Edge TTS 拉取音頻,頁面用 Web Audio 連播;默認用小藝(zh-CN-XiaoyiNeural)朗讀,並支持重讀任意一條歷史回答。
這是什麼¶
dsh-tts-reader 是 DSH 的 Web 客戶端注入型插件(package.json 中 meta.title 爲「朗讀回答(小藝)」)。宿主側用零依賴 Edge TTS 客戶端合成 MP3,頁面側負責播放與開關;不替換 DSH 核心,通過 Cordis patch 掛載路由並監聽 agent/assistant-stream。
社區目錄頁:https://www.skillhub.cn/plugins/lemonhall/dsh-tts-reader(SkillHub 爲獨立插件廣場,與 DeepSeek / 幻方無官方從屬關係)。源碼與說明:https://github.com/lemonhall/dsh-tts-reader。當前資料中版本爲 0.1.0,許可證 MIT。
核心功能¶
兩個入口,兩條隊列¶
| 位置 | 作用 |
|---|---|
| 輸入框右側喇叭 | 整個會話的實時朗讀開關(默認開),狀態存在 localStorage |
| 每條回答下方喇叭 | 在「顯示 / 複製 / 點贊 / 用量 / 時間」一行,重讀這一條;再點停止 |
實時朗讀與「重讀某條」是獨立隊列。點重讀會臨時接管揚聲器;讀完自動把實時朗讀接回,從下一句繼續,不補播期間錯過的內容。
邊寫邊唸的數據路徑¶
模型仍在輸出時,插件已從原始流取文,比 DOM 更早:
agent/assistant-stream GET /dsh-tts/tail?session=…&since=…
(模型正在寫的原文) (base64 MP3,按句游標拉取)
│ ▲
▼ │
lib/index.js ──► lib/feed.js ──► lib/edge-tts.js
宿主半邊 逐句隊列 零依賴 Edge TTS 客戶端
│
Session.snapshotEvents() ────────────────┤
(某條歷史回答的正文) GET /dsh-tts/message?session=…&id=…&since=…
│ │
└──────────────► lib/feed.js ─────────┤
│
lib/client.js ──┘
頁面半邊:Web Audio 無縫連播 + 兩個開關
合成放在宿主側,是因爲 Edge 朗讀服務要求瀏覽器類 User-Agent 纔會 WebSocket 101 升級,而頁面側 WebSocket 無法自定義請求頭。頁面每 400 ms 用游標拉取一次;沒有聽衆的會話不會觸發合成。
重讀某條的正文來自 ctx.sessions.get(id).snapshotEvents() 裏 assistant/message 事件的 stream(可見正文,不含推理與工具調用)。被查看的會話在內存中存活時,整段可見歷史都可讀,不受插件安裝時間限制。
念給人聽的內容¶
朗讀的是口語化文本,不是屏幕上的 Markdown 原文:
- 圍欄代碼塊整塊跳過;行內代碼保留字面值
- 表格單元格用「,」連接,分隔行不念
- 鏈接只念文字,裸 URL 唸作「鏈接」
- 標題、加粗、引用、列表符號等標記去掉
- 推理過程與工具調用參數不念
安裝與啓用¶
SkillHub 目錄頁未給出單獨的 dsh plugin … 一行命令,而是讓 Harness 讀取後端安裝計劃後執行。在目錄頁使用「發送給 DeepSeek Harness 安裝」或「複製安裝提示詞」,向當前 DSH 會話說明要安裝的插件標識即可,例如:
請安裝 DSH 插件 lemonhall/dsh-tts-reader。先讀取後端安裝計劃再執行安裝。
(完整提示詞以目錄頁「複製安裝提示詞」爲準。)
安裝前建議自行閱讀 GitHub 倉庫源碼與 MIT 許可證。插件在 當前 DSH 進程權限 下運行,並會 聯網 訪問 Edge TTS 服務。
啓用後無需額外命令:輸入框右側喇叭默認開啓實時朗讀。若要在宿主側整體關閉能力,可改配置(見下);不要用 plugin_manager set_plugin 反覆關開本插件——README 實測會出現路由仍在、但 agent/assistant-stream 監聽已停、實時朗讀靜默失效的半死狀態。臨時不想聽,用輸入框喇叭即可。
配置¶
在 $DSH_HOME/profiles/desktop/cordis.patch.yml 裏找到 dsh-tts-reader 條目的 config(插件未導出 Config schema,Cordis 會把整塊 config 交給 apply):
| 鍵 | 默認 | 說明 |
|---|---|---|
enabled |
true |
宿主側總開關 |
voice |
zh-CN-XiaoyiNeural |
Edge TTS 短名,啓動時向官方聲音目錄覈對 |
rate / volume / pitch |
+0% / +0% / +0Hz |
合成參數 |
maxPerRequest |
3 |
每次拉取最多返回幾句 |
改 lib/client.js 後 刷新頁面(Ctrl+F5)即可;改 lib/index.js、lib/feed.js、lib/edge-tts.js 等宿主模塊 必須重啓應用。README 註明:plugin_manager 關開條目不能讓宿主半邊熱重載,改宿主代碼一律按需重啓預期。
典型用法¶
- 正常與助手對話:模型流式輸出時,默認逐句播放小藝語音。
- 暫時關閉:點輸入框右側喇叭;偏好會寫入
localStorage。 - 重聽某條回答:點該條下方喇叭;再點一次停止。重讀結束後實時朗讀從下一句恢復。
- 換聲音或語速:改
cordis.patch.yml中voice、rate、volume、pitch,重啓 DSH 使宿主配置生效。
維護者在倉庫內提供自測腳本(需聯網的用例需能訪問 Edge TTS):
cd E:\development\dsh-tts-reader
node test/feed.mjs # 逐句隊列(純離線)
node test/client-load.mjs # 客戶端加載(純離線)
node test/host-e2e.mjs # 宿主端到端(需聯網)
node test/smoke.mjs # 語音目錄 + 合成 + 文本清洗(需聯網)
調試宿主 WebSocket 時可設環境變量 DSH_TTS_DEBUG=1 打印幀級日誌。
適用場景與注意¶
適合:希望在 DSH Web 對話裏 hands-free 聽回答、且能接受 Edge TTS 聯網合成的開發者;需要邊生成邊聽、而不是等整段 MP3 的場景。
注意:
- 依賴 Edge 在線服務;README 記錄了
User-Agent、SSML 語音全名、二進制幀格式等協議細節,自行改lib/edge-tts.js時需對照說明,避免 403 或靜默斷連。 - 分類爲聯網工具:安裝前確認網絡策略與源碼行爲。
- 與 SKILL 方案相比,優勢在於進程內常駐、逐句流式、默認跟隨助手輸出;代價是綁定 DSH 插件與 Cordis 部署方式,而非任意 Python 腳本。
結尾¶
dsh-tts-reader 把助手回答默認用小藝朗讀,實時流與歷史重讀分開排隊,宿主合成、頁面拉取播放,適合在 DSH 裏邊寫邊聽。進一步瞭解請訪問目錄頁 skillhub.cn/plugins/lemonhall/dsh-tts-reader 與 GitHub 倉庫 github.com/lemonhall/dsh-tts-reader。