dsha-tts-bridge: Moving DSH's speech synthesis to the host side

Introduction

DSH often runs within a proot container on Android. The /dev/snd device is inaccessible inside the container, so commands like ffplay and aplay fail entirely. Furthermore, the Android WebView on some ROMs lacks the Chinese voice pack, causing speechSynthesis.speak() to go silent. Consequently, both common paths for text-to-speech are non-functional.

The only stable and usable method is to play an MP3 using <audio> within the page. The plugin introduced below does exactly this: it synthesizes text into an MP3 in the DSH host process, exposes a same-origin route via the built-in DSH webServer, and the page simply points src to it. It is maintained by flyinghouse-ma.

What is it

dsha-tts-bridge is the host-side Text-to-Speech (TTS) bridge. It does one thing: Text → MP3, and then the page is responsible for playing it.

It does not rely on API keys or accounts; it uses the Microsoft Edge TTS WebSocket protocol (api.msedgeservices.com, with the legacy endpoint speech.platform.bing.com), rather than the official Azure TTS SDK. The plugin implements a WebSocket client (lib/websocket.js) on its own, resulting in zero npm dependencies.

Core Features

  1. Synthesizes speech within the host process and returns the result as MP3, which the page can play using <audio>.
  2. Exposes same-origin routes via the built-in DSH webServer, allowing direct references within the WebView without CORS issues.
  3. Implements an LRU cache for the last 40 synthesis results in memory; repeating the same sentence will not trigger repeated requests.
  4. Enforces a 15-second timeout per synthesis; it returns an error on failure without blocking the page.
  5. Returns audio/mpeg on success; returns 502 on failure along with a plain text reason.

Installation and Activation

The plugin is installed via DSH’s profile mechanism:

dsh plugin --profile web add @flyinghouse-ma/dsha-tts-bridge

After installation, you need to restart dsh web because it is a host-side module, and hot reload does not apply.

Typical Usage

After installation, any page (including WebView) can directly use <audio> for playback:

<audio src="/dsh-tts/say.mp3?text=需要你确认一下" autoplay></audio>

If you need to control volume or reuse the audio, you can use fetch to retrieve the Blob and play it:

const r = await fetch('/dsh-tts/say.mp3?text=' + encodeURIComponent('你好'));
const url = URL.createObjectURL(await r.blob());
new Audio(url).play();

Server parameters are as follows:

Parameter Description
text The text to speak, maximum 200 characters
voice Optional voice, default is zh-CN-XiaoxiaoNeural (Xiaoxiao, female Chinese voice)

The 200-character limit is set for “reminder” scenarios to prevent this route from being abused as a general-purpose TTS proxy.

Suitable Scenarios and Notes

Suitable for the following situations: developers running DSH in an Android proot container who need short voice announcements (approval reminders, status updates); or scenarios where WebView voice is unavailable and a stable reading path is required.

Points to note:

  1. Requires access to Microsoft’s speech service endpoints. Returns 502 if the network is unreachable; this is a known limitation.
  2. The plugin is only responsible for synthesis; playback control (volume, interruption, queue) is decided by the page itself.
  3. The plugin runs with the permissions of the current dsh process. You should read the source code and verify the license (MIT) before deciding to install it.
  4. Not suitable for reading long texts (200-character limit per request).

Conclusion

dsha-tts-bridge solves a narrow but real problem: when there is no audio device in the container and the WebView cannot pronounce Chinese, using a same-origin MP3 route restores the broadcast functionality. It does not aim for general TTS capabilities; the interface and limitations are clearly defined.

Directory page: https://www.skillhub.cn/plugins/flyinghouse-ma/dsha-tts-bridge

Source code: https://github.com/flyinghouse-ma/dsha-tts-bridge

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye