Preface¶
When implementing voice input for DSH / Agent clients, the common practice is to attach an external recording tool, export the file manually, and upload it. This involves switching windows, finding paths, and waiting for APIs. dsh-record consolidates this process into the input box: add a microphone button in the composer. Click to start recording, click again to stop. The recording is attached directly to the current prompt as a conversation attachment and sent with the normal upload queue. The output format is selected in the plugin settings page, supporting MP3 (default), WAV, and WebM.
Below is an introduction to this plugin. It is maintained by most-silence, under the MIT open-source license. The repository is https://github.com/most-silence/dsh-record, and the community directory page is https://www.skillhub.cn/plugins/most-silence/dsh-record.
What it can do¶
One-sentence positioning: A client-side plugin that adds a recording button to DSH’s composer, attaching the audio file as a conversation attachment to the current prompt after recording. It is only responsible for recording, transcoding, and mounting; it does not write disk files or perform speech recognition—if text conversion is needed, a separate speech-to-text plugin is required (README suggests dsh-stt).
Verified capabilities:
- The button is registered in the
conversation.input.rightslot, before the submit action, with no popup window, and can coexist with other composer controls. - Output formats
mp3/wav/webm, defaultmp3, selectable in Settings → Plugins → dsh-record. - Hover tooltips follow the interface language: Chinese shows “录音”, English shows “Record”. The button registers
zh/endictionaries with the host locale service; after switching languages, tooltips, aria-labels, and status notifications update accordingly. - Recording uses the browser’s
MediaRecorder, prioritizing webm/opus with fallbacks based on capability. There is a timer and filename preview during recording (rec-YYYYMMDD-HHMMSS-<n>s.mp3). - All three formats are processed in the browser: MP3 is encoded by lamejs (128 kbps CBR), WAV is a lossless re-wrap of 16-bit PCM, and WebM is the browser’s native Opus container without transcoding.
- Mounting uses the host draft-attachment channel (
conversation.createDrafts+inputActions.addAttachments), displayed as a file card in the input box with upload progress. - If transcoding fails (e.g.,
OfflineAudioContextunavailable), the original WebM is mounted directly to ensure the recording is not lost.
Installation and Enablement¶
The installation command provided in the README is to add it by file path after local building, not to pull a package from the registry:
git clone https://github.com/most-silence/dsh-record
cd dsh-record && npm install && npm run build
dsh plugin --profile <your-profile> add file:$PWD
After installation, restart the DSH host and refresh the webpage. You can rebuild using npm run build (tsdown produces lib/index.js and lib/client.js), and run npm test to execute 14 node:test cases (9 client factory contracts, 5 encoders). Tests run on Node 24 and do not require a browser.
Configuration¶
There is only one configuration field, changed in Settings → Plugins → dsh-record:
| Field | Value | Meaning |
|---|---|---|
format |
mp3 (default) · wav · webm |
Output container. MP3 / WAV are transcoded in the browser after recording stops, WebM is mounted as-is. Changes take effect on the next page load, as the browser-side configuration is only read once at startup. |
The browser reads this configuration via GET /dsh-record/config on startup; if the route is unreachable, it falls back to mp3.
Architecture and Two Pitfalls¶
The plugin follows a typical frontend + host two-part architecture:
browser half (lib/client.js) host half (lib/index.js)
├─ mic button @ conversation.input.right ├─ Config schema { format: mp3 | wav | webm }
├─ zh/en dictionaries → locale service └─ GET /dsh-record/config → serves resolved config
├─ MediaRecorder → webm/opus (same-origin guarded)
├─ decode → lamejs (mp3) / PCM wrap (wav)
└─ attach via createDrafts + addAttachments
The README specifically notes two reinforcement rules learned from real crashes, which are worth copying for similar plugins:
@breezystack/lamejsmust be bundled inline. DSH’s module table is frozen and does not contain lamejs. If treated as an external build dependency,require("@breezystack/lamejs")will fail to find the module table and cause the entire web startup to crash. The build tool tsdown usesnoExternalto force inlining.- The host’s
Configusesz.union([...])and cannot usez.enum([...]), while schemastery is keptexternal. The host’s built-in schemastery version does not have theenummethod, and the private copy of schemastery bundled with the plugin is incompatible with the host’s validator. Either of these will throw an error during the import phase, flagging this plugin asrequiredand crashing the entire profile.
Notes¶
- This plugin runs with the permissions of the current DSH process. It is recommended to read the source code before installing third-party plugins, and pay attention to its open-source license (this project is MIT).
- The attachment channel depends on the host client contract; the README verified version is dsh 0.2.1-rc.2 (
conversation.input.rightslot,createDrafts/addAttachments). It may degrade to inline error messages after changes to upstream interfaces. - Transcoding happens after recording stops, not in real-time during recording, so very long recordings will have a short encoding wait.
- Recording requires browser microphone permission, and the page must run on HTTPS or localhost.
- The output format is placed in the host profile configuration, not in the browser, so changes take effect only after refreshing the page.
Summary¶
dsh-record solves a very specific pipeline problem: record in the input box → transcode in the browser → upload as a prompt attachment, without touching disk or performing recognition. If you are already using DSH for client-side voice input, you can first install it in a test profile to try it out, confirm that the attachment channel and format meet expectations, and then consider integrating it into the formal process.
- Directory page: https://www.skillhub.cn/plugins/most-silence/dsh-record
- Code repository: https://github.com/most-silence/dsh-record