前言¶
DeepSeek Harness(DSH)採用「一切皆插件」的理念,將各種能力以插件形式掛載到宿主上。音樂播放是高頻且耗資源的場景:如果每次都把曲庫塞進對話上下文,不僅會撐大系統提示,還會帶來額外的 token 開銷。尤其是本地音樂庫規模較大時,這種做法會明顯拖慢響應速度。
dsh-music-local 是一個本地音樂播放器插件,它的核心目標是在保持播放功能完整的前提下,做到零 token 消耗。
是什麼¶
dsh-music-local 是 DeepSeek Harness 的本地音樂播放器插件,由維護者 xiao000xue 編寫。
它把一個音樂根目錄下的每個子目錄(樹形,任意深度)當成一個播放列表,支持直接流式播放音頻文件。插件不做文件頭讀取,也不做轉存或修改,所有播放都通過瀏覽器半體 ↔ 宿主 HTTP 路由完成,與 LLM 對話上下文完全解耦。
插件要求 DSH >= 0.2.0、Node >= 20。可選依賴 ffmpeg 僅用於 dts / dsd / ape 這類需要轉碼的格式。
爲什麼是零 token¶
插件刻意不執行以下操作:
- 不註冊
music_play之類的模型工具 - 不往系統提示裏注入音樂庫清單
- 不使用
inject: ['llm', 'tools', 'systemPrompt'] - 不把曲庫內容塞進對話上下文
因此它不會出現在模型的工具列表裏,也不會撐大系統提示。音樂庫的瀏覽、搜索、播放、切歌全部發生在瀏覽器半體 ↔ 宿主 HTTP 路由之間,與 LLM 毫無關係。無論你放 38 首歌還是 3.8 萬首歌,每輪對話的 token 開銷都是 0。
安裝與啓用¶
在 profile 目錄裏把插件裝成依賴,下面三種方式任選其一。
方式 A — 直接從 GitHub 裝(推薦)
cd "$DSH_HOME/profiles/desktop"
pnpm add github:xiao000xue/dsh-music-local
方式 B — 已經有本地源碼副本
cd "$DSH_HOME/profiles/desktop"
pnpm add file:D:/dsh-plugins/dsh-music-local
方式 C — 完全不用包管理器
把本倉庫整個目錄複製到 $DSH_HOME/profiles/desktop/node_modules/dsh-music-local。插件不依賴任何第三方運行時庫,有 lib/ 與 cordis.patch.yml 就能跑。
裝好之後,在 profile 的 package.json 裏把插件掛進 bundles,然後重啓 DSH:
{
"dependencies": {
"dsh-music-local": "github:xiao000xue/dsh-music-local" // ← ① 依賴(隨安裝方式而定)
},
"dsh": {
"profile": {
"bundles": [
// ... 其它 bundle ...
"dsh-music-local" // ← ② 掛載
]
}
}
}
profile 位於 $DSH_HOME/profiles/<profile名>/package.json(桌面端通常是 desktop)。
插件自帶的 cordis.patch.yml 會被自動讀取(由 package.json 的 dsh.bundle.patch 聲明),無需手改 profile 的 patch 文件。
使用¶
重啓 DSH 後:
- 輸入框下方會出現一條播放條,支持上一首 / 播放暫停 / 下一首 / 進度 / 音量 / 打開面板。
- 點右側按鈕展開播放面板(浮層,可拖動、可縮放,位置記在
localStorage): - 左欄 = 樹形歌單:音樂根目錄下的每個子目錄(任意深度)都是一個歌單節點,支持 ▸/▾ 逐層展開收起(展開狀態記在
localStorage),歌單名右側的數字是該文件夾(含子文件夾)的曲目數。 - 右欄 = 選中歌單的曲目,支持搜索框過濾(在哪個歌單裏搜就只搜它的子樹)。
- 點一行 = 播放(再點當前這首歌 = 播放/暫停),雙擊 = 從頭播放。
- 頂部 = 設置,可改音樂根目錄、重掃。
- 面板裏右鍵 / 懸停曲目可以看到解析出的「歌手 - 歌名」。
設置的存放位置¶
| 文件 | 內容 |
|---|---|
$DSH_HOME/music-local.json |
音樂根目錄、掃描開關等 |
$DSH_HOME/music-local-prefs.json |
上次播放曲目、播放模式、音量 |
$DSH_HOME 即 DSH 的數據目錄(桌面端由機器級環境變量 DSH_HOME 指定)。
格式支持¶
分成兩條路:
① 瀏覽器原生可播(直接給出 206 Partial Content + Range,秒開、可任意拖動)
mp3 m4a m4b m4r aac flac wav ogg oga opus webm
aif aiff aifc alac mp4 caf 3gp
② 需要 ffmpeg 實時轉碼(dts / dsd / ape 這類瀏覽器不認的格式)
dts dff dsf ape wma asf wv tta mpc tak ofr
ac3 eac3 amr au snd mid midi spx m4p
mkv avi mov flv rm rmvb wmv mpg mpeg ts vob
轉碼走管道,不落盤:ffmpeg -i <文件> -f s16le -,邊解邊送。
已探到時長時會在上方拼一個定長 WAV 頭,於是 Range 請求能換算成 -ss 秒數,拖動進度條可用;探不到時長則回退爲流式 WAV(能播,但不能精確拖動)。
ffmpeg 自動挑選¶
機器上可能裝了好幾份 ffmpeg.exe,其中不少是精簡版(--disable-everything,只認識 mp4/mp3/flv),拿它轉 dts 會直接 Invalid data found when processing input。
插件啓動後會在常見位置搜 ffmpeg 並打分:
-muxers裏有E s16le→ +4(能輸出裸 PCM,轉碼纔可用)-demuxers裏有dts/dsf/dff/ape/asf/avi→ 每項 +1
得分最高的那份纔會被用來轉碼,且會被真實解碼驗證。找不到或只有精簡版時,面板「設置」裏會明確標註是 完整版 / 精簡版 / 未找到 ffmpeg,第 ① 類格式依舊正常播放。
性能¶
- 掃描:只解析文件名,不讀文件頭。3.8 萬個文件約 3 秒。
- 緩存:掃描結果常駐內存,只做一次;之後所有請求都是內存命中(
/manifest、/tracks從 ~3.2 s 降到個位數毫秒)。 - 列表渲染:15k 行用原生 DOM + 分頁(默認 300 條一頁),不走 React 重渲染,滾動不掉幀。
- 曲名解析:文件名裏
歌名-歌手與歌手-歌名混着來。用「配對對象去重計數」判定 —— 歌名只會配對到一個歌手,歌手會配對到很多歌名。比純詞頻穩,能扛住「車載合輯裏大量重名文件」這種髒數據。
HTTP 路由一覽¶
宿主半體註冊在前綴 /dsh-music-local 下:
| 方法 | 路徑 | 說明 |
|---|---|---|
| GET | /config |
根目錄、曲庫統計、ffmpeg 探測狀態 |
| POST | /config |
改根目錄並重掃 |
| GET | /manifest |
播放列表 + 曲目清單(緊湊編碼) |
| POST | /rescan |
強制重掃 |
| GET | /tracks |
分頁取曲目(?ids=1 取 id 列表,?q= 過濾) |
| GET | /track |
單曲詳情 |
| GET | /browse |
瀏覽目錄(用於設置裏選根目錄) |
| GET | /probe |
探測時長 |
| GET | /stream/<id> |
音頻流(支持 Range;轉碼軌用 ?t=<秒>&d=<時長>) |
| GET/POST | /prefs |
播放偏好讀寫 |
已知限制¶
- 轉碼軌的精確拖動依賴「能探到時長」,個別損壞文件的時長探測會失敗,此時該曲不能精確 seek。
- 精簡版 ffmpeg 只能轉 mp4/mp3 類,第 ② 類格式會播不了 —— 面板會提示,放一份完整版 ffmpeg 到常見路徑即可。
- 播放器不使用音頻可視化(
createMediaElementSource在 DSH 裏會導致靜音),這是有意的取捨。
適用場景與注意¶
適合在本地有較大音樂庫、希望保持對話上下文輕量、同時享受流式播放與樹形歌單體驗的場景。
插件以當前 DSH 進程權限運行。安裝前應檢查源碼與許可證,確保符合你的使用環境。
短結尾¶
dsh-music-local 通過解耦 LLM 上下文與播放邏輯,實現零 token 消耗的本地音樂播放。它把目錄結構轉化爲樹形歌單,支持常見音頻格式,並提供流式播放與進度拖拽。目錄頁與源碼倉庫見下:
- https://www.skillhub.cn/plugins/xiao000xue/dsh-music-local
- https://github.com/xiao000xue/dsh-music-local