前言¶
給 DSH / 智能體客戶端做語音輸入時,常見做法是外掛一個錄音工具,錄完導出文件再手動傳上去,中途要切窗口、找路徑、等接口。dsh-record 把這條鏈路收進輸入框:在 composer 里加一個麥克風按鈕,點擊開始錄、再點一次停止,錄音會作爲對話附件直接掛在當前 prompt 上,跟着正常上傳隊列一起發出去。輸出格式在插件設置頁選,支持 MP3(默認)、WAV、WebM。
下面介紹這個插件。它由 most-silence 維護,開源協議 MIT,倉庫 https://github.com/most-silence/dsh-record ,社區目錄頁是 https://www.skillhub.cn/plugins/most-silence/dsh-record 。
能做什麼¶
一句話定位:一個客戶端插件,給 DSH 的 composer 加錄音按鈕,錄完把音頻文件作爲 conversation 附件附到當前 prompt 上。它只負責錄製、轉碼、掛載這三步,不寫磁盤文件、不做語音識別——需要轉文字的話要另配一個 speech-to-text 插件(README 建議 dsh-stt)。
已經覈實的能力:
- 按鈕註冊在
conversation.input.right槽位、提交動作之前,沒有懸浮窗,可以和其他 composer 控件共存。 - 輸出格式
mp3/wav/webm,默認mp3,在 Settings → Plugins → dsh-record 裏選。 - 懸停提示跟隨界面語言:中文顯示「錄音」,英文顯示「Record」。按鈕向宿主 locale 服務註冊了
zh/en字典,切換語言後提示、aria-label、狀態通知會跟着更新。 - 錄音走瀏覽器
MediaRecorder,優先 webm/opus,按能力回退;錄音中有計時器和文件名預覽(rec-YYYYMMDD-HHMMSS-<n>s.mp3)。 - 三個格式都在瀏覽器內完成:MP3 由 lamejs 編碼(128 kbps CBR),WAV 是 16-bit PCM 無損重封裝,WebM 就是瀏覽器原生 Opus 容器不轉碼。
- 掛載走宿主 draft-attachment 通道(
conversation.createDrafts+inputActions.addAttachments),輸入框裏顯示爲文件卡片並帶上傳進度。 - 轉碼失敗時(比如
OfflineAudioContext不可用)直接掛原始 WebM,保證錄音不丟。
安裝與啓用¶
README 給的安裝命令是本地構建後按文件路徑添加,不是從 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
安裝完重啓 dsh 宿主,再刷新網頁。可以用 npm run build 重新構建(tsdown 產出 lib/index.js 和 lib/client.js),npm test 跑 14 個 node:test 用例(客戶端工廠契約 9 個、編碼器 5 個),測試在 Node 24 上跑,不需要瀏覽器。
配置¶
配置只有一個字段,在 Settings → Plugins → dsh-record 裏改:
| 字段 | 取值 | 含義 |
|---|---|---|
format |
mp3(默認)· wav · webm |
輸出容器。MP3 / WAV 在停止錄音後於瀏覽器內轉碼,WebM 原樣掛載。改動在下次頁面加載時生效,因爲瀏覽器那半邊只在啓動時讀一次配置。 |
瀏覽器端啓動時通過 GET /dsh-record/config 讀取這個配置,路由不可達就回退到 mp3。
架構與兩個坑¶
插件是典型的前端 + 宿主兩段式:
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
README 裏特別記了兩條從真實崩潰裏學到的加固規則,做同類插件值得抄:
@breezystack/lamejs要內聯打包。DSH 的模塊表是凍結的,裏面沒有 lamejs,如果把它當構建外置依賴,require("@breezystack/lamejs")會查不到模塊表並導致整個 web 啓動中斷。構建工具 tsdown 用noExternal強制內聯。- 宿主端的
Config用z.union([...]),不能用z.enum([...]),並且 schemastery 保持external。宿主自帶的 schemastery 版本沒有enum方法,用打包進來的私有副本構造的 schema 又和宿主校驗器不兼容,任一種都會在 import 階段拋錯,把這行插件判成required從而拖垮整個 profile。
注意點¶
- 這個插件以當前 dsh 進程的權限運行,安裝第三方插件前建議先讀一遍源碼,也注意它的開源協議(本項目是 MIT)。
- 附件通道依賴宿主客戶端契約,README 驗證版本是 dsh 0.2.1-rc.2(
conversation.input.right槽位、createDrafts/addAttachments)。上游接口變動後可能退化爲行內錯誤提示。 - 轉碼發生在停止錄音之後,不是邊錄邊轉,所以很長的錄音會有一小段編碼等待。
- 錄音需要瀏覽器麥克風授權,頁面必須走 HTTPS 或 localhost。
- 輸出格式放在宿主 profile 配置裏而不是瀏覽器裏,所以每次改完要刷新頁面才生效。
小結¶
dsh-record 解決的是一個很具體的鏈路問題:輸入框裏錄音 → 瀏覽器內轉碼 → 作爲 prompt 附件上傳,不碰磁盤、不做識別。如果你已經在用 DSH 做客戶端語音輸入,可以先在測試 profile 裏裝上試一輪,確認附件通道和格式符合預期,再考慮接到正式流程裏。
- 目錄頁:https://www.skillhub.cn/plugins/most-silence/dsh-record
- 代碼倉庫:https://github.com/most-silence/dsh-record