DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-song-id

A

dsh-song-id

Manifest valid

DSH Plugin: Given a video link (Bilibili / YouTube, etc.), use the Shazam + NetEase Cloud dual engine to identify what song is playing

hasBundlePatchMachine translated

dsh-song-id

给一条视频链接,听出里面是什么歌。(目前只测试了b站视频链接)

「这个视频的 BGM 是什么?」 「第 70 秒那段是什么歌?」 「这条降调版的曲子是谁的?」

工具 song_identify 用 yt-dlp 取音频、ffmpeg 切片,再同时问 Shazam 和网易云音乐两个识曲引擎, 返回歌名 / 歌手 / 专辑 / 流派 / 封面 / 命中时间点。串烧、混剪、DJ 串烧会把每一段扫到的歌都列出来。


目录


安装

1. 装插件

插件是一个普通的 DSH bundle(package.json 里的 dsh.bundle.patch 指向 cordis.patch.yml)。

从本地目录装(推荐,改代码立即生效):

# 在 DSH 的对话里让 agent 执行,或直接用 dsh 的插件管理。
# 把 <插件目录> 换成这个包所在的绝对路径(link: 后面跟目录,不要带引号以外的修饰):
plugin_manager install_bundle  target="link:<插件目录>"

装完会做三件事:把依赖写进 profile 的 package.json、把 dsh-song-id 追加进 dsh.profile.bundles、在 profile 的 node_modules 里建一个指向本目录的符号链接。

开发时也可以手工挂: 在 profile 的 package.json 里加

"dependencies": { "dsh-song-id": "link:<插件目录>" },
"dsh": { "profile": { "bundles": [ "...", "dsh-song-id" ] } }

装完必须重启一次 DSH。 bundle 的树是在宿主启动时组合的,热装进 profile 不会动态加载。

2. 装依赖

插件本身零 npm 依赖,但识曲依赖三个外部程序。装完一定要跑一次 node bin/doctor.mjs 确认全绿。

yt-dlp —— 解析链接、下载音频

平台命令
Windowswinget install yt-dlp.yt-dlp(或 pip install -U yt-dlp)
macOSbrew install yt-dlp
Linuxpipx install yt-dlp(或发行版包管理器)

B 站经常改接口,yt-dlp 要勤更新:yt-dlp -U(pip 装的用 pip install -U yt-dlp)。

查找顺序:DSH_YTDLP_PATH → PATH → %APPDATA%\\Python\\Python3xx\\Scripts → %LOCALAPPDATA%\\Programs\\Python\\Scripts。

ffmpeg —— 切片、转 8 kHz PCM

平台命令
Windowswinget install Gyan.FFmpeg(或 scoop install ffmpeg)
macOSbrew install ffmpeg
Linuxsudo apt install ffmpeg

只要 ffmpeg 在 PATH 上即可;装在别处就用 DSH_FFMPEG_PATH 指定到 ffmpeg.exe。

Python 3.9+ —— 跑 shazamio

平台命令
Windowswinget install Python.Python.3.12
macOSbrew install python
Linuxsudo apt install python3

查找顺序:DSH_PYTHON_PATH → PATH 里的 python.exe → PATH 里 python.cmd/python.bat (会从脚本内容里抠出真正的 .exe 路径,因为 Node 在 Windows 上没法直接 spawn .cmd)→ $DSH_HOME/venvs/*/Scripts/python.exe → %LOCALAPPDATA%\\Programs\\Python\\*\\python.exe → %APPDATA%\\Python\\*\\python.exe。

shazamio —— 不用手动装

首次识曲时会自动执行:

python -m pip install --disable-pip-version-check --upgrade --target <本包>/vendor/py shazamio

装进插件自己的 vendor/py,不污染全局 Python 环境(约 21 MB)。想提前装好:

node scripts/install-vendor.mjs          # 预装
node scripts/install-vendor.mjs --check  # 只检查

网易云引擎不需要任何额外依赖:指纹器是编译好的 wasm(vendor/afp/),接口不需要 key、不需要登录。

3. 自检

node bin/doctor.mjs

六项检查:yt-dlp / ffmpeg / python / shazamio / 网易云指纹器 / 网易云接口可达性。 任何一项 ❌ 或 ⚠️ 都会告诉你怎么修。


用法

在对话里

装好并重启后,直接说:

agent 会调用 song_identify,把结果整理成 Markdown 给你。

参数

参数默认说明
url必填B 站链接 / BV 号 / av 号 / b23.tv 短链 / 任意 yt-dlp 支持的链接
at—从第几秒开始认(给了就从这个点往后连续取,不再按比例撒点)
clips3试几段(1–5)。越多越可能中,也越慢
clipSeconds12每段多长(5–30)。前奏很长、人声很轻的视频可以调到 20
cookies—cookies.txt 路径,登录 / 会员限定的视频用(也可设 DSH_VIDEO_COOKIES)

timeoutMs 是 300 秒;工具声明为并发安全,可以同时识别多条视频。

输出长什么样

🎵 **Song Title** — Artist Name

- 专辑:Album Name
- 流派:Pop
- 发行:2019
- 厂牌:Label Name
- 封面:https://.../cover.jpg
- Shazam:https://www.shazam.com/track/00000000/...
- 引擎:Shazam(Apple Music 曲库)
- 视频:某个投稿的标题(4:28) [BVxxxxxxxxxx]
- 上传者:某 UP 主
- 命中位置:0:32(12 秒片段)

串烧 / 混剪会多一段:

- 这条视频里扫到 3 首不同的歌(像是串烧/混剪,位置不同歌就不同):
  - 0:47:Song A (Remix) — Artist A(×1.06 变调)
  - 1:39:Song B — Artist B(×1.06 变调,网易云)
  - 2:05:Song C — Artist C(网易云)

三点提示都会出现在输出里:

  • - 引擎:网易云音乐(曲库里这一版是用户上传的 DJ 版/翻唱…) —— 主答案来自网易云
  • - 存疑:只有网易云认出来,Shazam 没认到同一首… —— 只有一家认出来
  • - 变调:原速认不出,把片段升到 ×1.12 才命中 —— 这条视频应该是降调/变速版,结论可能不准,建议核对

没认出来时:❓ 没认出来,列出已经试过的位置和异常,并建议 at=75 / clipSeconds=20。

命令行直接跑(调试用)

node scripts/smoke.mjs "https://www.bilibili.com/video/BVxxxxxxxxxx" 70      # 从第 70 秒
node scripts/smoke.mjs "https://www.bilibili.com/video/BVxxxxxxxxxx" --fresh  # 忽略缓存

工作原理

总流程

链接
 │
 ├─ 归一化:BV 号 / av 号 / b23.tv / 带跟踪参数的完整 URL → 干净的网址 + 缓存键
 ├─ 查缓存(命中直接返回,标「来源:缓存」)
 ├─ yt-dlp -J:只解析不下载,拿到标题 / 时长 / 上传者 / 有没有音轨
 │    · 直播 → 直接拒;合集/播放列表 → 直接拒
 │    · 超 60 分钟且没给 at → 直接拒(默默下 200 MB 比让你给个时间点更糟)
 ├─ 采样点:默认按时长 12% / 42% / 72% 撒 3 个点,避开片头 logo 和片尾字幕
 ├─ 取音频:
 │    · ≤ 30 分钟 → yt-dlp 整段下 bestaudio(一般 10 MB 以内)
 │    · > 30 分钟 → yt-dlp --download-sections 只下需要的那几十秒
 │                    (站点不配合就回退整段下载)
 ├─ ffmpeg 切片:16 kHz 单声道 mp3(识曲只需要语音带宽,体积小到 60 KB/段)
 ├─ 识别三轮(见下)
 ├─ 结果写缓存 7 天
 └─ 渲染 Markdown

三轮识别:一轮比一轮贵,也一轮比一轮脏

轮次做什么什么时候跑为什么
1原速、3 个均匀采样点总是正常 MV 到这一步就中了,通常 5–7 秒
2原速、再补扫 7 个位置第 1 轮全灭,且有整段音频、没给 atDJ 串烧里每首歌只占几十秒,3 个点很容易全落空
3变调 ×1.06 / ×1.12,每档 5 个位置全灭,或只有网易云认出来B 站大量「降调 0.95x / 升调 / 变速」投稿,Shazam 指纹对音高变化不鲁棒

变调的实测依据:对一条标着「降调 0.95x」的投稿,Shazam 原速全灭、×1.0526(理论值 1/0.95)也全灭, ×1.12 才命中。对变调版只能靠多档位去猜。

第 3 轮最容易误判(同一段音频换个倍率可能指向另一首歌),所以变调结果永远带 shift 标记, 渲染时明确写「可能不准,建议核对」;如果主答案不是变调来的,变调结果只并入候选、不替代主答案。

为什么保留两个引擎

两家用的是同一系指纹算法(网易云接口参数就叫 algorithmCode=shazam_v2),对变调一样不鲁棒; 但曲库完全是两回事:

Shazam网易云音乐
曲库Apple Music 正规发行版用户可上传,DJ 版 / 翻唱 / AI 版 / 伴奏遍地
元数据专辑、厂牌、流派、发行年份全歌名 + 歌手 + 封面
对 DJ 降调视频变调后常认成原唱常直接认出曲库里对应的 DJ 版
原速误配率低偏高(原速下偶尔会返回完全无关的歌)

所以每轮里两个引擎是 Promise.all 并行的(一个挂掉不影响另一个),合并规则:

  1. 同一片段 Shazam 有结果 → 丢弃该位置的网易云候选(网易云的撞库噪声太多);
  2. Shazam 没有 → 取网易云前 2 条作为候选;
  3. 主答案优先 Shazam;只有网易云能认出来时标「存疑」;
  4. 所有位置的命中汇总去重成候选列表(歌名去掉括号里的版本说明后比较),最多 8 条 —— 串烧视频只报第一首等于骗人。

两个引擎各自怎么调

  • Shazam:vendor/py 里的 Python 库 shazamio 逆向实现了 Shazam 的免费接口,不需要 key。src/pipeline/recognize.py 用 asyncio 并发(最多 4 路,单段 25 秒超时), 逐段识别、命中即停,结果用 <<<SONGID>>>{json} 一行回传给 Node。
  • 网易云:网页版识曲是纯前端的 —— 3 秒 8 kHz 单声道 PCM → 本地 wasm 算指纹 → POST interface.music.163.com/api/music/audio/match?algorithmCode=shazam_v2&rawdata=<指纹>。 指纹器在 vendor/afp/(来自 mos9527/ncm-afp,以 NeteaseCloudMusicApi 的 demo 形式分发)。每个 12 秒片段取 0 秒和 6 秒两个 3 秒窗口各问一次 —— 实测 3 秒的偏移就足够让指纹落到另一首歌上,多问一个窗口几乎不花时间(一次查询约 200 ms)。

缓存

$DSH_HOME/storages/song-id/cache.json,按「视频 + 采样参数」为键,TTL 7 天,最多 500 条。 命中过缓存的输出会多一行「来源:缓存(7 天内问过同一条视频)」。删掉这个文件即清空。 没认出来的不缓存 —— 下次换个时间点可能就中了。

临时切片放在 $DSH_HOME/storages/song-id/tmp/run-XXXX/,每次调用结束就删。


目录结构

dsh-song-id/
├── package.json            # dsh.bundle.patch 指向 cordis.patch.yml
├── cordis.patch.yml        # 往 loader 里 insert 一个 dsh-song-id 条目
├── icon.svg  locale/{zh,en}.json
├── src/
│   ├── index.js            # 插件入口:只做 ctx.tools.register(song_identify)
│   ├── tool-spec.js        # 工具契约:参数 / 输出 schema / timeout
│   ├── format.js           # 结果 → Markdown
│   └── pipeline/
│       ├── url.js          # 链接归一化、BV 号提取、缓存键
│       ├── ytdlp.js        # 找 yt-dlp / ffmpeg、spawn、错误翻译
│       ├── media.js        # yt-dlp -J 探元信息、整段/区间下载、采样点
│       ├── clips.js        # ffmpeg 切片(原速 / 变调)
│       ├── shazam.js       # 调 recognize.py,解析 MARK 行
│       ├── recognize.py    # asyncio + shazamio,并发识别
│       ├── netease.js      # 网易云:PCM → wasm 指纹 → audio/match
│       ├── vendor.js       # 找 python、懒装 shazamio 到 vendor/py
│       ├── cache.js        # 7 天缓存
│       └── identify.js     # 主流程:三轮识别、双引擎合并
├── bin/doctor.mjs          # 依赖自检
├── scripts/
│   ├── smoke.mjs           # 命令行冒烟:node scripts/smoke.mjs <url> [at] [--fresh]
│   └── install-vendor.mjs  # 预装 shazamio
├── test/                   # 单元测试
└── vendor/
    ├── py/                 # shazamio 及其依赖(自动装,不入库)
    └── afp/                # 网易云指纹器 wasm

依赖与环境变量

环境变量作用
DSH_YTDLP_PATH指定 yt-dlp 可执行文件
DSH_FFMPEG_PATH指定 ffmpeg 可执行文件
DSH_PYTHON_PATH指定 Python 解释器
DSH_SONGID_VENDOR改 shazamio 的安装目录(默认 <本包>/vendor/py)
DSH_VIDEO_COOKIES默认 cookies.txt 路径
DSH_HOME决定缓存与临时目录位置(默认 ~/.dsh)
DSH_SONGID_DEBUG设了之后 apply 抛出的异常不再被吞,便于排查

排错

现象怎么办
工具不出现在对话里① 装完是否重启过 DSH;② node bin/doctor.mjs 看依赖;③ DSH_SONGID_DEBUG=1 重启后看日志里的 [dsh-song-id] failed to load
没认出来先 at=秒 指一个你确定有歌的位置,再把 clipSeconds 调到 20。纯音乐、现场翻唱、人声盖过伴奏的段落,两个引擎都可能认不出
认出来但不像DJ 混音 / 串烧里同一段音频在两家曲库可能对应不同的歌,输出会把候选都列出来,对照着看
长视频报「太长」用 at 指定时间点,或先用 clips/at 缩小范围
要登录的视频导出一份 cookies.txt 传给工具(cookies 参数或 DSH_VIDEO_COOKIES)
B 站解析失败 / 403yt-dlp -U 更新;仍不行多半要 cookies
shazamio 坏了删掉 vendor/py,下次识曲自动重装
网易云连不上只有 Shazam 引擎工作,结果仍可用(doctor 里会标 ⚠️)
中文歌名乱码已修:recognize.py 强制 UTF-8 输出,shazam.js 给子进程设 PYTHONIOENCODING=utf-8

隐私

识曲时片段音频会发给第三方:

  • Shazam(Apple)—— Shazam 引擎;
  • 网易云音乐 —— 上传的是 3 秒 8 kHz 的指纹数据。

这是这个能力的本质,不是实现细节上的妥协。指纹计算在本地完成,但算完的指纹本身也要上传才能查库。 不想外发就别用。

插件本身不收集任何统计、不写云端,视频标题/上传者只出现在给你的回答里。


License

MIT

Comments

Loading…

Similar plugins

dsh-song-download

by Raywh

DeepSeek Harness 歌曲下载插件:搜索(B站/YouTube)+ 下载(MP3 320k 酷狗兼容)+ LRC 歌词(站点字幕 + 网易云兜底)。DSH plugin: song search & download with lyrics.

Manifest valid

★ 0

MIT

JavaScript

Aug 31, 2026

dsh plugin --profile web add dsh-song-download

by XiaoMao-yty

网易云音乐 DSH 插件:单曲/MV/歌词/笔记/歌手/图片抓取,歌单管理,以及 AI 私人电台策展。零 npm 依赖。

Manifest valid

★ 0

MIT

JavaScript

Sep 21, 2026

dsh plugin --profile web add dsh-netease-music

by xiekai886

这是一个可以让你边对话边听歌的 DeepSeek Harness 插件:折叠/展开两种可自由拖动的悬浮窗口形态,利用 Meting API 等解析源接入网易云音乐,支持歌单导入和按歌名或歌手搜索单曲导入。Chat and listen at the same time.

Just for FunManifest valid

★ 4

MIT

JavaScript

Aug 16, 2026

dsh plugin --profile web add @dsh-external/dsh-music

by AGImentu

DSH (DeepSeek Harness) Web 插件:任务完成后播放提示音(可开关、可调音量、可上传自己的音频;内置提示音由脚本合成)

Development & InfrastructureManifest valid

★ 0

MIT

TypeScript

Sep 12, 2026

dsh plugin --profile web add dsh-turn-chime

by Raymond-Hear

一个帮你高效下载各平台视频的DeepSeek Harness 插件。贴一个链接,用本机 yt-dlp 下载视频 / 音频 / 字幕 / 封面 —— 支持 YouTube、哔哩哔哩、X、TikTok 等上千个站点。

Manifest valid

★ 0

MIT

JavaScript

Nov 5, 2026

dsh plugin --profile web add dsh-video-downloader

by Goothe13-gugu

用于Deepseek Harness的插件,让你的大模型边思考边唱歌。A plugin for Deepseek Harness (DSH) to play music or audio when your LLM is thinking.

Tools & CapabilitiesManifest valid

★ 0

MIT

JavaScript

Sep 23, 2026

dsh plugin --profile web add dsh-audio-cue