前言¶
DSH 在安卓上常跑在 proot 容器裏:容器內 /dev/snd 不可訪問,ffplay、aplay 這類播放命令全部失靈;而部分 ROM 的 Android WebView 又拿不到中文語音包,speechSynthesis.speak() 會直接靜默。兩條常見的朗讀路徑都不成立。
唯一穩定可用的方式,是在頁面裏用 <audio> 播放一個 MP3。下面介紹的這個插件就做了這件事:在 DSH 宿主進程裏把文字合成爲 MP3,通過 DSH 自帶的 webServer 暴露同源路由,頁面把 src 指過去即可。它由 flyinghouse-ma 維護。
這是什麼¶
dsha-tts-bridge 是宿主側的語音合成橋,只做一件事:文字 → MP3,然後由頁面負責播放。
它不依賴 API Key、不依賴賬號,走的是微軟 Edge 朗讀的 WebSocket 協議(api.msedgeservices.com,舊版端點是 speech.platform.bing.com),並非官方 Azure TTS SDK。插件自行實現了 WebSocket 客戶端(lib/websocket.js),因此零 npm 依賴。
核心功能¶
- 在宿主進程內合成語音,結果以 MP3 返回,頁面用
<audio>就能播。 - 通過 DSH 自帶的 webServer 暴露同源路由,WebView 內可直接引用,不存在跨域問題。
- 內存中對最近 40 條合成結果做 LRU 緩存,同一句話反覆播報不會重複請求。
- 單次合成 15 秒超時,失敗即返回錯誤,不會卡住頁面。
- 成功返回
audio/mpeg;失敗返回502加純文本原因。
安裝與啓用¶
插件通過 DSH 的 profile 機制安裝:
dsh plugin --profile web add @flyinghouse-ma/dsha-tts-bridge
裝完需要重啓 dsh web,因爲它是宿主側模塊,熱加載不生效。
典型用法¶
裝好之後,任何頁面(含 WebView)都可以直接用 <audio> 播報:
<audio src="/dsh-tts/say.mp3?text=需要你確認一下" autoplay></audio>
需要控制音量或複用音頻時,可以用 fetch 取回 Blob 再播放:
const r = await fetch('/dsh-tts/say.mp3?text=' + encodeURIComponent('你好'));
const url = URL.createObjectURL(await r.blob());
new Audio(url).play();
服務端參數如下:
| 參數 | 說明 |
|---|---|
text |
要念的文字,上限 200 字 |
voice |
可選音色,默認 zh-CN-XiaoxiaoNeural(曉曉,中文女聲) |
200 字上限是按“提醒播報”場景設定的,目的是防止該路由被當成通用 TTS 代理濫用。
適用場景與注意¶
適合以下情況:DSH 運行在安卓 proot 容器中、需要短語音播報(審批提醒、狀態播報)的開發者;或者 WebView 語音不可用、需要穩定朗讀路徑的場景。
幾點需要注意:
- 需要能訪問微軟的語音服務端點,網絡不通時會返回 502,這是已知限制。
- 插件只負責合成,播放控制(音量、打斷、隊列)由頁面自行決定。
- 插件以當前
dsh進程的權限運行,安裝前應先閱讀源碼、確認許可證(MIT),再決定是否引入。 - 長文朗讀不適用於此插件(單條 200 字上限)。
結尾¶
dsha-tts-bridge 解決的是一個很窄但確實存在的問題:容器裏沒有音頻設備、WebView 又念不出中文時,用一個同源 MP3 路由把播報恢復可用。它不追求通用 TTS 能力,接口和限制都寫得很明確。
目錄頁:https://www.skillhub.cn/plugins/flyinghouse-ma/dsha-tts-bridge
源代碼:https://github.com/flyinghouse-ma/dsha-tts-bridge