在本机拆解歌曲的速度调性与能量走势
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/22 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ALittleLov/dsh-soundcheck该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · other
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 13 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 56 处,展示前 22 条)
- 读取本地文件lib/index.js:22
return existsSync(d) && readdirSync(d).some(f => f.endsWith('.onnx')) - 读取本地文件lib/index.js:22
return existsSync(d) && readdirSync(d).some(f => f.endsWith('.onnx')) - 读取本地文件lib/index.js:39
?? candidates.find(p => existsSync(p)) - 执行外部命令来自配置/变量lib/index.js:68
child = spawn(python, args, { - 发起网络请求lib/index.js:156
const res = await fetch(url, { redirect: 'follow' }) - 写入本地文件lib/index.js:167
mkdirSync(dirname(dest), { recursive: true }) - 写入本地文件lib/index.js:168
writeFileSync(dest, buf) - 发起网络请求lib/index.js:188
const res = await fetch(url, { redirect: 'follow' }) - 写入本地文件lib/index.js:199
mkdirSync(dirname(dest), { recursive: true }) - 写入本地文件lib/index.js:200
writeFileSync(dest, buf) - 读取本地文件lib/index.js:222
if (existsSync(dest)) continue - 发起网络请求lib/index.js:225
const res = await fetch(`${base}/${f.name}`, { redirect: 'follow' }) - 写入本地文件lib/index.js:235
mkdirSync(dir, { recursive: true }) - 写入本地文件lib/index.js:236
writeFileSync(dest, buf) - 发起网络请求lib/index.js:266
const res = await fetch(url, { redirect: 'follow' }) - 读取本地文件lib/index.js:463
if (!existsSync(audio)) return `ERROR: file not found: ${audio}` - 读取本地文件lib/index.js:464
if (!existsSync(paths.python) || !existsSync(paths.script)) { - 删除本地文件lib/index.js:528
unlinkSync(probe) - 删除本地文件lib/index.js:593
unlinkSync(join(paths.env.TEMP, '.probe')) - 发起网络请求client.js:145
fetch('/dsh-soundcheck/api/overview', { headers: { accept: 'application/json' }, cache: 'no-store' }) - 发起网络请求client.js:155
fetch('/dsh-soundcheck/api/job?id=' + encodeURIComponent(id), { cache: 'no-store' }) - 发起网络请求client.js:170
fetch('/dsh-soundcheck/api/action?kind=' + encodeURIComponent(kind), { method: 'POST' })
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
让文本模型读懂一首歌:本地音乐分析插件,把音频拆成能量、速度、调性、密度,音频不出本机。
README
由 DeepSeek 最新模型翻译生成音频分析 · 现状与结论
给 DSH 加本地音乐理解能力的实验项目。
目标:让文本大模型能回答关于音乐的问题,不是做 FL 参数推荐器,不是播放器。
更新:2026-10-19
这份是开发说明,不是安装指南。 只想装上用,看同目录的《安装说明.md》。
⚡ 交接速览(新会话先看这段)
现在有什么:一个 DSH 插件,注册了三个工具 + 两个命令
| 工具 | 作用 |
| audio_analyze | 分析整首音频,返回文本或 JSON(可 brief 压缩) |
| audio_section | 只分析一段 [start, end],回答「2:40 那里怎么回事」 |
| audio_provision | 装引擎(建 venv / 装依赖 / 下 YAMNet);已有 .provisioned 标记时直接返回「已装」 |
| 命令 | 作用 |
| /audio-status | 看引擎状态(Python 环境 / 脚本 / 模型 / 安装标记) |
| /audio-install | 一键装引擎,返回装了什么、走了哪个镜像 |
安装策略:分析时不会偷偷装依赖(用户得先知道要下 470 MB)。引擎缺失时工具返回 ENGINE_NOT_INSTALLED,让用户跑 /audio-install,或者明确让助手代装。
展开完整文档(README 剩余 1 节)
音频分析 · 现状与结论 给 DSH 加本地音乐理解能力的实验项目。 目标:让文本大模型能回答关于音乐的问题,不是做 FL 参数推荐器,不是播放器。 更新:2026-10-19 这份是开发说明,不是安装指南。 只想装上用,看同目录的《安装说明.md》。 ⚡ 交接速览(新会话先看这段) 现在有什么:一个 DSH 插件,注册了三个工具 + 两个命令 | 工具 | 作用 | | audio_analyze | 分析整首音频,返回文本或 JSON(可 brief 压缩) | | audio_section | 只分析一段 [start, end],回答「2:40 那里怎么回事」 | | audio_provision | 装引擎(建 venv / 装依赖 / 下 YAMNet);已有 .provisioned 标记时直接返回「已装」 | | 命令 | 作用 | | /audio-status | 看引擎状态(Python 环境 / 脚本 / 模型 / 安装标记) | | /audio-install | 一键装引擎,返回装了什么、走了哪个镜像 | 安装策略:分析时不会偷偷装依赖(用户得先知道要下 470 MB)。引擎缺失时工具返回 ENGINE_NOT_INSTALLED,让用户跑 /audio-install,或者明确让助手代装。 插件位置:dsh-soundcheck-plugin\(已 dsh plugin add 到 desktop profile) 引擎位置:开发机用项目根目录(venv + analyze.py);分发包用插件自带的 engine\ 分发包:dsh-soundcheck-0.5.1.zip(16.5 MB),由 pack.py 生成 GitHub:ALittleLov/dsh-soundcheck —— 旧账号 dalekotsvet 已被封(2026-10-20),仓库已迁移过去,本地 remote 已切,旧下载链接全部失效 性能:4 分钟 mp3 整首约 11 秒(此前 66 秒)。两处白干的活已去掉: chroma 原本为调性和和弦各算一遍 CQT;YAMNet 原本把 mp3 再解码一遍。 输出长什么样(文本模式,默认只给判断): [SCOPE] 只有片段分析时才出现:分析了哪一段 [判断] 一段人能直接读的结论:时长/速度层级/调性/母带/结构重心/最大反差/收尾 [依据] 判断背后的那几个数字(峰值、RMS、起音、调性、拍速) [可信] beat / 调性 / 根音 的适用性分数(0-1) [听不到] 这类分析死也听不出来的东西 --detail(或工具参数 detail: true)才输出完整明细: [FIT] 适用性自评 | [META][BPM][KEY][DYN] | [ACT] 活动度 | [FORM] 能量走势 [CHORD] 根音骨架 | [SEG] 段落边界 | [SRC] 声源 | [说人话] 旧版散文式总结 关键设计:默认先给结论,数字只在 [依据] 里。定性来自「别给用户甩一堆数据」这条反馈。 不给流派判断 —— 流派是听出来的,不是测出来的;要的话给「方向 + 置信」,并标成推断。 当前瓶颈:说不出「音乐内容」(乐器、人声、语言、氛围)。光靠 DSP 补不上——见文末「9 个维度」,9 格里有 2 硬、5 半、2 空。 MusicNN(50 类)只覆盖西方音乐大类,不含中国民乐。 未发版的改动(2026-10-20 晚,等用户点头才发 0.5.3): - analyze.py 术语改英文:抽空/砸回 → drop X dB / 回来;直接收掉 → hard cut; 淡出 → fade out。起因:QQ 接入的用户把「抽空了一截」读成「最满」,方向弄反了 ——事实证明形容词有歧义,数字不会 - 判断里允许单个数字锚点(如「1:36 drop 9 dB」);自检同步放宽为「一行两个以上才报」 - 这三处已在工作区生效,但 repo/engine 与 plugin/engine 尚未同步,发版时一起同步 当前待办(讨论完,未动手): 1. 按需 stem 分离(4-stem 里吉他在 other,要 6-stem;CPU 慢需后台) 2. 歌词接入(已验证:LRC 优先、ASR 仅兜底候选,见「歌词 ASR 验证」一节) 3. 从 MOSS 借能力(当 Teacher 打标 → 训小模型;不把大模型塞进插件) 4. 链接入口(取件与读件分离:下载归 ncatbot,插件仍只吃本地文件)详见文末「下一步候选」与「9 个维度」。 踩过但放弃的路: - MOSS-Music 8B(18GB + CUDA-only)→ 用户否决 - Essentia Discogs-EffNet(400 类风格,20MB)→ essentia.upf.edu 域名在本机不通,且官方 Windows Python 绑定不支持 - GTZAN 训练(2001 年老数据、10 类、无国潮) - YAMNet 1024 维 embedding 做音频检索(2026-10-20 实测)→ 探针脚本见 _archive\probe_embed.py。 用 8 首歌、音量归一化、中位数池化,按曲风分组算「同组−异组」区分度: YAMNet +0.106、MFCC 对照 +0.033。向量确有信息(为 MFCC 的 3 倍),但最高相似对是 HAYA 蒙古民乐 ↔ 枪花硬摇滚(0.795),排序不符合音乐内容。 结论:向量有微弱信号,不足以支撑「这是马头琴/那是古筝」级别的判断;要用出它的价值需要一批干净标注的参考样本,工量等于另起项目。不加入主流程。 同类线索(MusicNN 50 类标签、OpenL3 18MB 音乐嵌入)未跑,若将来有标注集再议。 - Silero VAD v5 判断人声(2026-10-20 实测)→ 模型 _archive\silero_vad.onnx(2.2 MB),探针 _archive\probe_vad.py。 四首歌的人声块占比:HAYA papillon(有人声)12.0%、枪花(有人声)6.3%、 I Saw(纯器乐)7.1%、大提琴 cover(纯器乐)1.4%。 纯器乐比有人声的还高,阈值无法区分;最长连续人声段只有 1.44 秒,抓不住整段歌声。 结论:VAD 训练针对的是「说话」,歌声(长音、颤音、伴奏掩蔽)不在分布内 —— 既漏检又误检,不能用于音乐。 它偶尔会高置信度误判(max 0.958),和 YAMNet 把唢呐报成 Choir 是同一个病根。 用户真正想要:Gemini 那种描述(「马头琴、蒙古语、草原庆典」)。已确认只能靠 Gemini API(约 ¥0.13/首),但用户不愿花钱、不愿翻墙。 目前定下的方向:不追求「像 Gemini」的措辞,而是把「能测的」合成为判断,把「测不到的」明说。 目录结构 音频分析\ ├── analyze.py 主分析脚本(结构/BPM/调性/根音候选/动态 + 可选 YAMNet) ├── yamnet_test.py YAMNet 单独测试脚本(看时间线用) ├── yamnet.onnx YAMNet 模型,16 MB ├── yamnet_class_map.csv 521 类标签,14 KB ├── dsh-soundcheck-plugin\ 插件本体(源码,不含引擎) │ ├── lib\index.js 宿主半侧,注册三个工具 │ └── cordis.patch.yml ├── README.发布.md 给用户看的说明(自述 + 安装合并版,打包时改名 README.md) ├── README.md 这份开发说明(不打包) ├── build\dsh-soundcheck\ 打包暂存区(pack.py 生成,已脱敏) ├── pack.py 打包:拼装 + 脱敏扫描 + 压 zip ├── dsh-soundcheck-0.4.0.zip 分发包,13.6 MB(不含 Python 依赖) ├── test-plugin.mjs 插件端到端测试(假 ctx 收集工具,真跑每个工具) ├── test-activity.py 活动度指标的单独测试 ├── venv\ Python 虚拟环境(librosa + onnxruntime),468 MB,不发 ├── wheels\ 离线 wheel 缓存,118 MB(重装用) ├── install-offline.sh 通用离线装包脚本(curl 下 wheel + pip --no-index) ├── download-wheels.sh 最初的 librosa 依赖批量下载 ├── fix-deps.sh 最初的迭代补包 ├── out.json 一份完整 JSON 样例 └── out.brief.json 一份 brief JSON 样例(约 530 B) 打包与分享: - 分发包 = 插件代码 + 引擎(analyze.py 54 KB + 模型 16 MB)= 13.6 MB - 用户机器的 Python 依赖(468 MB)由 audio_provision 在安装时下,不进包 - 包里的引擎在 engine/,用户解压到哪都能自己找到;开发机上 profile 里用 config.root 指回工作区 - README 分两份:README.md(这份,开发用,不打包)和 README.发布.md(用户版,打包时改名为包内 README.md) - 脱敏是硬门槛:pack.py 先复制到 build/,替换本机路径,再扫一遍禁用词(用户名、本机工作目录、歌库文件名,词表就写在 pack.py 里);扫到就中止打包,不悄悄发出去 - 改完 analyze.py 必须重跑 pack.py,否则分发包里还是旧的 发版流程(改完要更新 GitHub 时必须走) 推送前必须停下。 代码改完只在本地验证,把结果给用户看;得到明确同意后,才允许 commit / tag / push / 建 Release。禁止自行判断「这个改动是对的」就直接推。 2026-10-20 定下的规矩:当时 0.4.2 抢先推送,被纠正过一次。 本地 commit 不等于 push,攒着发。 平时随便 git commit(纯本地,零网络流量);到发版点再一次性 push(main + tag)+ 建 Release。一天 1–2 次 push 就够。 别滑回「改一下就推一下」——旧账号被封的教训之一就是节奏太密(新号 + 代理 IP + 高频操作,是典型的自动化风险画像)。 不要改动完就 git push,那是「直接改文件」。 每次改动都按版本走: 0. 本地验证 → 把结果给用户看 → 等明确同意(这步不能跳) 1. 改完、本地验证通过(analyze.py 实跑一次看输出) 2. 升版本号,两个文件必须一致:repo/dsh-soundcheck/package.json 与 dsh-plugin.json - 纯修正 → patch(0.4.0 → 0.4.1);用户可见的行为变更 → minor(0.5.0) 3. 写 repo/dsh-soundcheck/CHANGELOG.md 对应小节,写清「改了什么、为什么」 4. commit(沿用 conventional commits:fix: / feat: / docs: / chore:,正文中文) 5. 打 tag:git tag -a vX.Y.Z -m "..."(历史上从来没过 tag,从现在起必须有) 6. git push origin main && git push origin vX.Y.Z 配套动作: - 三份引擎副本要同步:analyze.py(根) → repo/dsh-soundcheck/engine/ → dsh-soundcheck-plugin/engine/。只改根目录那份,发布的包里还是旧的 - 运行版插件的 package.json / dsh-plugin.json 版本号也要跟着升,否则装的和发的不一致 - 发版后重跑 pack.py 产出新 zip 推送失败的常见原因(本机实测):github.com:443 连不上(网络层),或凭据管理器弹不出窗(非交互 shell 没有 TTY)。两者都不是代码问题,在普通终端里手动跑一次 git push 让它弹出登录窗即可。 用法 cd /d/DSH/音频分析 export PYTHONUTF8=1 # 必须!否则中文/方块字符会崩 人类可读文本(默认:一段判断 + 依据 + 可信 + 听不到) ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" 完整测量明细(旧的仪表盘:FIT/能量曲线/和弦骨架/声源) ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --detail 结构化 JSON(插件调用) ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --json 压缩 JSON:只留结论级字段,约 1/25 的体积 ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --brief 只分析一段(--start/--end 接受秒或 m:ss) ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --start 1:30 --end 2:10 ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --start 90 --end 130 --brief 分轨(可选组件;首次约 60–90 秒,之后读缓存) ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --stems ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --stems 6s 歌词听写(可选组件:先分离人声轨,再 faster-whisper;只输出候选段) ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --asr ./venv/Scripts/python.exe analyze.py "<音乐目录>\music.flac" --asr small 只跑 YAMNet 看时间线 ./venv/Scripts/python.exe yamnet_test.py "<音乐目录>\music.flac" --start 60 --dur 30 插件回归测试(用 DSH 自带的 node) /node test-plugin.mjs 打包分发包(改过 analyze.py 之后必须重跑) ./venv/Scripts/python.exe pack.py 注意: - 中文路径必须硬编码或加引号传。经 bash 变量传递会编码坏掉。 - 片段分析的时间戳是全曲绝对位置,不是片段内相对时间。 现在能做什么 | 能力 | 状态 | 说明 | | 判断式输出 [判断] | ✅ 默认形态 | 先给结论,数字只在 [依据];流派不猜 | | 结构 / 能量走势 | ✅ 可靠 | 16 秒块 RMS,0 dBFS 为满刻度 | | BPM | ✅ 可靠 | 含倍频校验 + 低频第二意见(但校验不出「检测器本身锁在双倍速」) | | 调性 | ✅ 可用 | Krumhansl 模板 + Top3 候选 + 歧义分类 | | 适用性自评 [FIT] | ✅ 最有价值的一块 | 在 --detail 与 JSON 里,决定哪些结论能信 | | 声源 / 乐器(YAMNet) | ✅ 部分可用 | 16 MB,1000× 实时,CPU;情绪/风格标签已剔除 | | 响度 / 削波 | ✅ 可靠 | 真峰值 + 整体 RMS + 贴顶点计数 | | 和弦 | ⚠ 只到根音级 | 根音候选骨架;性质/七度分不清。见结论 4 | | 片段分析 | ✅ 可用 | audio_section,时间戳为全曲绝对位置 | | 分轨(人声检测) | ✅ 新增 0.6.0 | --stems 4s/6s:各轨能量占比 + 人声判定;组件可选(约 150 MB),缓存后秒回 | | 歌词听写 | ⚠ 候选级 | --asr:4s 人声轨 + Whisper;只输出「较确定」段,不是逐字准确;见「歌词 ASR 验证」 | | 流派 / 风格 | ❌ | 听不出来;工具会明说「风格判断不了」,不编 | | 自然语言描述 | ❌ | 需要大模型(已决定不做) | 四个最重要的结论 1. [FIT] 适用性自评必须保留 它决定「这些结论能信多少」。设计它的时候,自己被它抓出了 10 个 bug。 每个维度都要区分两种失败: | 失败类型 | 表现 | 例子 | | 体系外(模板不适用) | 绝对可信度低 | 维吾尔音乐 vs 西方调性模板(key_r 0.55) | | 体系内歧义 | 绝对可信度高、差距小 | 属调混淆(0.91 vs 0.83) | 只看后者,就会把「模板不适用」误判成「可用但有歧义」 —— 这是最危险的错。 调性的判据: - key_r(绝对相关度):< 0.65 判定「模板不适用」 - gap(最佳与次佳差距):≥ 0.15 判定「调性明确」 四首实测:0.913 / 0.900 / 0.550 / 0.894 —— 三首西方体系 + 一首维吾尔,分得很干净。 2. YAMNet 的边界很清楚 | 能给 | 不能给 | | ✅ 乐器/声源(Percussion / Singing / Drum) | ❌ 情绪(Sad/Tender 是猜的) | | ✅ 地域线索(Music of Asia / Bollywood) | ❌ 风格(Christmas/Christian 是噪声) | | ✅ 相对比较(两首像不像) | ❌ 绝对判断(分数只有 0.01–0.05) | 原因:AudioSet 训练数据偏西方流行,没有「抒情/慢板」这类类别,模型找不到就跳到 Christmas/Christian 这种特征相近的类。 用时必须带上这句警告,否则会把「圣诞音乐」写进报告。 2026-10-19 补充:中文乐器这层是噪声。 实测把「唢呐」报进了两首根本没有唢呐的曲子(一首古筝领奏的器乐曲、一首民乐曲),「二胡」在各首之间到处排第一。 它报的不是乐器,是「中国民乐」的刻板标签。所以判断里已不再出现配器行,原始分数只在 --detail 存档。 同一天还试了 CLAP(零样本,文本比音频):8 首里乐器 top-1 只对 4 个,全是西方通用类(钢琴 / 电吉他 / 电子鼓);古筝、琵琶、马头琴一个都没进前四;风格则「流行」几乎霸榜。 第一版用中文提示词是无效的(CLAP 文本端是英文训练的),改英文后西方乐器变好、中文乐器仍然为零。 结论:零样本这条路对中文乐器不通,已删除实验环境(2.7 GB)。这也说明早先「Zither→古筝」命中是运气。 2026-10-21 补充:非西方打击乐同样是盲区。 《两只猫头鹰》(代青塔娜,纯吟唱剪辑版)实测,人耳明确听出的沙锤与鼓,YAMNet 全量 521 类里最高仅 0.09(Rattle)与 0.02(Drum 系),0.10 阈值下零命中;同一首只有吉他与钵/锣成立(吉他 0.52,集中在 0:01–0:26;钵 0:14、锣 3:08、钵 3:20,均为点状)。 「模型没标签」不等于「音频里没有」,这类判断只能靠测量,不能靠模型默不作声。 替代做法(实测可用,暂不入插件):librosa STFT 分频带(6–12k / 2.5–6k / 0.8–2.5k / 250–800 / 80–250 / 30–80 Hz),每带做包络差分 + scipy.signal.find_peaks 取打击点,统计间隔中位数与变异系数 cv。 判据:cv < 0.5 视为该带节律规律,可判为「节拍器层」。该曲 6–12k 带 cv=0.42、间隔 0.44s、主周期 0.89s(=67 拍),与 BPM 66 的八分音符吻合 → 沙锤;低频 30–250 Hz 占能量 35%、打击点密但 cv>1.1 → 打击铺底,不是节拍器。参考脚本 _archive/band_rhythm_probe.py。 3. BPM 会半速误判,而且旧的自校验抓不到 实证:一首自作曲,beat tracker 报 74.9,真实约 150。 为什么原来的「倍频校验」失效:beat_track 的 tempo 和「节拍间隔反推」来自同一次错误判断——它锁在「每两拍算一拍」,两个数字当然一致。等于自己给自己作证。 修法:用独立信号做第二意见 —— 30–200Hz 频段 onset 间隔的中位数。同一首歌这样算出 156.6,差 4.7%,并在文本里主动报警。 局限:kick 和 bass 抢同一频段,纯低频检测本身也有天花板(可能把 bass 音符当成 kick)。这是「第二意见」,不是「正确答案」。 补充实测(一首钢琴曲):beat tracker 98.7,低频第二意见 216.3。用 onset 自相关独立看,峰在 194–216 一带(约 2×98.7)—— 说明两个拍层级都真有能量,不是谁算错了。所以措辞已经从「很可能真速是后者」改成「两个拍层级都有能量,别把其中一个当唯一答案」。钢琴/无鼓曲目里,低音音符会伪装成底鼓,这条第二意见尤其容易误报。* 2026-10-21 补充:倍频错误是双向的,而且合成信号测不出来。 - 合成 click 轨(80/120/160)测得很准(误差 ≤2 拍)—— 但真实音乐里它锁错倍频很常见 - November Rain 官方约 80,检测器报 156.6(约两倍),低频第二意见又给 304 - 用户反馈:一首摇滚报 80,听感 160(约一半) - 所以「报 156 实际 80」和「报 80 实际 160」都会发生 —— 方向相反,同一病根 修法(已落地):新增 bpm_layers(),永远同时给两个倍频层级,不再只报一个数: - 判断里:拍速是两层:157 和 78,两个都可能,取决于你怎么数拍(有分歧时另写「低频层和瞬态层各说各的」) - [依据] 里:157 / 78 拍(两层) - JSON:bpm_layers 给两层原始值,不标注哪个是「真速」 关键补充:《月之暗面》(网易云权威值 69)检测 139.7(约两倍)——前后半段一致、三个信号自洽,说明连「节奏稳定的歌」也会锁双倍。所以不再推荐哪层是主答案:推荐错了比不推荐更糟,只把两层摆出来,由听的人按自己的数拍方式判断。 Beat This 集成(2026-10-21 晚,0.6.6 候选):BPM 检测改为可选组件——模型 dsh-soundcheck-data/models/beat_this/beat-this-final0.onnx + frontend.json (82 MB,MIT,ONNX,纯 onnxruntime,不需要 torch)。有模型用 Beat This,没有自动回退 librosa。 | 歌 | librosa | Beat This | 真值 | | 月之暗面 | 139.7 | 69.8 | 69 | | November Rain | 156.6 | 78.9 | ~80 | | 蓝色骏马 | 152.0 | 76.9 | — | 12 首对比:final0(82 MB)与 small0(导出 9.9 MB)有 10 首一致;small0 在 papillon 上翻倍、 final0 在 23 钢琴上翻倍——各有弱点,故选 final0(摇滚/电子更常见,且 BPM 是核心指标)。 实现:detect_tempo() 先试 Beat This(30 秒分块——Transformer 的 attention 对长序列 会吃大量内存),失败或模型缺失回退 librosa;[依据] 标「(Beat This)」,JSON 加 bpm_source。 small0 的导出脚本在 _archive/export_beat_this_small0.py(torch→ONNX,可复用)。 4. 和弦:不是「识别率低」,是「性质根本分辨不出来」 先纠正一个旧数字。 以前写的「未定率 71–82%」是错的 —— 那个字段算的是 1 - 变化点数 / 块数,即「和弦没变的比例」,不是识别失败率。标签撒谎。 真正的测量(一首钢琴曲,126 个 2 秒块,84 个和弦模板): | 层面 | 「最佳 − 次佳」差距的中位数 | 判读 | | 具体和弦(D#maj7 vs D# …) | 0.026 | 和噪声分不开 | | 折叠成「根音 + 大三/小三族」 | 0.036 | 仍然很紧 | | 只比根音(12 个) | 0.051 | 79% 的块有明显胜出者 | 结论:混音上的 chroma 只够猜根音,不够定和弦性质。七度、挂四、转位在混音里被所有乐器互相掩蔽,再好的匹配器也只能在噪声里挑一个。 所以降级为候选模式(已实现): - 报根音骨架:0:00 D#(M) | 0:21.8 C(m) | …,M/m 表示大三/小三 - 性质分不清就写 (?);根音也定不下来就加 ?;被过滤掉的抖动段标 ⟨12s未定⟩ - 另报候选词表(各根音占多大比例),并明说「这是候选,不是和弦进行」 - unresolved_ratio 现在是真正的未定比例(根音差距 < 0.025 的块占比) - [FIT] chords 也改为按根音差距算 —— 它评估的是「根音骨架能信多少」,不再是「和弦名对不对」 四首实测的根音未定率:钢琴曲 26% / 蒙古族乐队曲 38% / 自作曲 45%。 非西方与重混响素材明显更差,这正是 [FIT] 该反映的。 歌词 ASR 验证(2026-10-21) 问题:没有 LRC 的歌,能不能靠 Whisper 补歌词? 方法:_archive/probe_asr.py —— 4s 分轨取 vocals 轨 → faster-whisper(int8, CPU)转录 → 与 LRC 按字算 CER + 逐句对照。样本《蓝色骏马》(普通话)、《万物生(梵)》(梵语,作反例)。 结果(《蓝色骏马》,参考 141 字): | 模型 | 体积 | 段数 | 输出字数 | 按字 CER | 表现 | | tiny | ~75 MB | 17 | 120 | 79.4% | 只对副歌「好久不见」 | | base | ~145 MB | 67 | 324 | 200% | 幻觉多,编出英文段 | | small | ~461 MB | 15 | 820 | 548% | 前段最好,英语段循环失控 | | small_rep | — | 29 | 313 | 199% | 抑制重复后长度减半,循环仍在 | CER 被「输出字数爆炸」污染,看逐句更公平。small 在主歌前段确实能读出来:「霞上山坡→向上山坡」「远远带来一只蓝色骏马→远远带来一支蓝色军马」「好久不见 难得一见→好久不见 难得遇见」。但 131 秒后三档全崩。 梵语样本更说明问题:三档全部幻觉,且随模型变大「编得越来越像歌词」—— tiny 出「咛咢咢咢咢」,base 出英文 ounce my shadow,small 出「Zither Harp」「字幕 by 索兰娅」, small_rep 直接编成「我愛你,你愛我」的情歌。模型不会说「我听不懂」。 结论: - 插件内最多用 base(145 MB);small(461 MB)比 4s+6s 分轨模型总和(288 MB)还大 1.6 倍,效果仍不可靠,不划算 - ASR 只能作为「候选 + 必须标注机器听写」,不能写进判断 - 参数调优(no_repeat_ngram_size / repetition_penalty / temperature=0)只治输出长度,治不了「编不编」——这不是参数问题,是模型能力边界 - 因此歌词接入顺序不变:先 LRC(35% 覆盖),ASR 只作兜底 产物:_archive/probe_asr.py、_archive/asr_probe_report.md、_archive/asr_out/(两首 vocals wav)。 实现状态(2026-10-21 下午):analyze.py --asr [tiny|base|small] 已加,默认不跑。 输出 [听写] 段:只列「较确定」的候选段;疑幻觉段连内容都不给(JSON 里 text=null)。 梵语样本实测输出「本曲没有可用的歌词段」,是正确拒绝。 注意:候选段里仍会有错字——实测《蓝色骏马》11 段候选约一半是错的(「漫個意見」实为「难得一见」)。 所以措辞是「候选」不是「可信」;最终该不该信由调用它的模型判断——这是设计,不是缺陷。 音译规则(2026-10-21):非中文人声(梵语、藏语、自语、吟唱)不得翻成中文词义—— Whisper 强制中文会产出「我愛你」式幻觉;不强制则换成语种幻觉(《蓝色骏马》整首被听成英语「How do you feel」)。两条路都只给词、不给音。所以: - 有 LRC(含梵文/藏文):转写罗马音或音译,标来源 - 无 LRC 且听不出词:只报时间,不给文本;转述时用音译近似(shai-lu-way、om banza…),并说明「这是音,不是义」 - 永远不给中文翻译,除非确认是中文唱的词 「没有可用歌词段」≠ 纯器乐:先看 [分轨] 的人声占比;有人声却读不出,就说「有人声但词读不出,可能是外语或吟唱」,不硬编。 真人 vs AI 人声(2026-10-21 实测): | 样本 | 候选段 | 表现 | | 《起初说》(真人,有完整 LRC) | 18 段里 2 段 | 音对字错:「我诞于尘土」→「我的夜长途」、「奔向尘土」→「半想传途」;结构能看出是「…归于尘土」,字全错 | | 《蓝色骏马》(真人) | 37 段里 11 段 | 副歌能对(「好久不见」),主体错 | | AI 生成人声 | 7 段全废 | 连音都拼不成句子(「梦里欧霞」「伊莉茨」「导致山蕉的青鳳」) | 结论:真人歌上 ASR 的价值是「听出音、让你去认字」,不是直接给歌词; AI 生成人声基本读不出——合成音色、不自然的辅音与尾音不在 Whisper 训练分布里,再加上编曲覆盖,连候选段都很少。遇到「有人声但读不出」,先问是不是 AI 生成的人声。 踩过的坑(按教训价值排序) | # | 坑 | 教训 | | 1 | [FIT] 说 tonality 0.05,同一份输出 [KEY] 说 0.91 | 自相矛盾的输出是最强的 bug 探测器 | | 2 | 「块平均 RMS」冒充「峰值」 | 标签撒谎比数字错更危险 | | 3 | tonality 用熵,12 个 bin 永远算出低值 | 指标要有区分力,不能算出来都一样 | | 4 | 把「属调混淆」说成「无调性」 | 体系内的语言不能用来描述体系外的问题 | | 5 | 「疑似削波」用峰值判断 | 削波要看贴顶采样点数量,不是峰值 | | 6 | key_ambiguity 只看关系不看差距 | 0.89 的 D minor 被说成「调性不明确」 | | 7 | pip 网络请求被拦截(疑似杀软 SSL 扫描) | 用 curl 下 wheel + pip --no-index | | 8 | 脚本选到预发布版(protobuf rc) | pip 默认不装 pre-release,要过滤 | | 9 | 只认 cp312-abi3 没认 cp310-abi3 | abi3 要泛化匹配 | | 10 | 中文路径经 bash 变量传参编码坏掉 | 硬编码路径 | | 11 | chord_unresolved_ratio 用「和弦没变的比例」冒充未定率 | 指标名字和算式必须对得上,否则整份结论都建在错数字上 | | 12 | fmt_time 把 239.999 秒打成 3:60.0 | 先四舍五入到目标精度再拆分,别对原始浮点取模 | | 13 | 同一份音频被解码两遍、CQT 算两遍(4 分钟的歌 66 秒) | 先量耗时再谈优化;66s → 11s 只改了两处重复计算 | | 14 | [FIT] tonality 0.41 不可用 旁边写「中心基本明确」 | 前缀不要替调用方下结论;不可用 后面必须跟真正的理由 | | 15 | 54 秒片段测速 65.4,全曲却是 98.7 | 短片段会锁到别的拍层级;片段 BPM 不等于全曲 BPM,输出里必须警告 | 其中 8 个是被真实样本逼出来的,不是设计时想到的。(11–15 是本轮新暴露的) 关键决策记录 MOSS-Music 8B 已决定不做。 理由: - 模型 ~18 GB + ROCm + Python 3.12,无法作为可分享插件的依赖 - 定位应降为「可选增强」,而不是核心 - 用户判断:插件不能要求别人下十几 GB 当前路线:轻量(librosa + YAMNet),总依赖 < 1 GB,CPU 可跑。 外部建议:GPT 的三轮意见(2026-10-18/19) 用户当信使,把项目现状转给 GPT 咨询。这里只记结论和判断,不抄原文。 第一轮(架构) - 双分支:「音色复现」和「音乐理解」要的证据不同,别混一条流水线 - 测量 / 推断 / 建议 必须分开:「4.2kHz 有能量」是测量;「可能用了失真」是推断;「Mix 调 35%」是建议 - 不要先分离再决定分析什么 —— 分离伪影会污染音色判断 - 削波会伪装成失真(现场录音尤其) - 误差传播链:分离伪影 → 错音符 → 错和弦 → LLM 用流畅语言解释错误事实 采纳:测量/推断分离(体现在 [FIT] 和「说人话」的分工)、误差传播的警惕 未采纳:双分支(还没做音色分支) 第二轮(和弦 / BPM / 动态 / 自评) - 和弦:建议试 BTC(预训练,12.2MB 权重);Chordino 作传统基线。未做(需要 PyTorch,且要导出 ONNX) - 三态输出:可靠识别 / 候选歧义 / 证据不足;N/无和弦 和 unknown 必须分开 - BPM:建议 DeepRhythm —— 未采纳,许可证 AGPL-3.0(传染性),且要 PyTorch - 编曲动态 vs 响度动态:必须拆成两组指标 —— 已采纳并实现([ACT] 段) - 四字段自评:applicability / confidence / ambiguity / stability —— 部分采纳(目前只有单一 [FIT] 分数) - 类别缺失 ≠ 低置信度 —— 已作为原则采纳(YAMNet 没有竹笛类,不等于没有竹笛) 第三轮(风格分类) - Essentia Discogs-EffNet:400 种风格,权重约 20MB,CPU 可跑 —— 但 - 官方 Windows Python 绑定不支持 - essentia.upf.edu 在本机完全不可达(DNS 失败) - 分类头是 .pb(TensorFlow),要转 ONNX - 预处理必须严格复现,而参考实现装不上 → 无法验证 - 许可证 CC BY-NC-SA 4.0(非商业 + 相同方式共享,边界模糊) - → 判定:不做 - MAEST:345MB,模型和分类头都有 ONNX(不用转)—— 太大,不做 - 轻量 HuBERT:24MB,Apache 2.0(许可干净),但只有 GTZAN 10 类 —— 可用但覆盖窄 - CLAP 体积更正:我之前说 700MB,实际音乐专用检查点约 2.35GB - CLAP 零样本能力:GTZAN 上 Top-1 约 71%(项目自测),但没有「蒙古迪斯科」这类细分的基准 GPT 的最终判断(我认同) 只靠人工设计的 BPM / 调性 / 起音密度 / 动态 / 频谱统计,不能可靠还原文化语义。 允许用预训练模型,可以逼近其中相当一部分,但取决于模型学到了什么。 讨论中确立的六条原则 1. 先给结论,数据按需 —— 默认输出是判断,不是仪表盘;数字放 [依据],明细要 --detail 2. 敢下判断 —— 用肯定句给最可能的答案,再标置信(高/中/低),只指出「哪一层不确定」;不要每句都留退路,也不要用数据代替判断。 推断层鼓励大胆猜,但要给「反证条件」(如果是 X,你会听到 Y),让用户听一遍就能否掉 3. 对用户只谈音乐,不谈管线 —— 不提 [判断]/[FIT]、不提 YAMNet、不报置信小数;说「人声像在垫底」,不说 Choir 0.021 4. 测量与推断分离 —— 文本输出里,哪些是量的、哪些是猜的,必须能分辨 5. 不确定性显式化 —— 低分项要标(?)、空白要标(⟨51s未定⟩)、不适用的要判「不可用」 6. 类别缺失 ≠ 没有 —— 模型没有「竹笛」这个类,不等于这段没有竹笛 用户明确否决的方向 | 方向 | 否决理由 | | MOSS-Music 8B 本地跑 | 18GB,无法作为分享插件的依赖 | | Gemini / Qwen API | 要钱、要梯子、麻烦 | | 训练专用分类器(GTZAN / 民乐) | 数据老、类别不全、工作量大 | | FL Studio 参数推荐 | 用户不需要 | | 频段节律拆解 / YAMNet 521 类全量并进插件 | 使用频率低;插件保持轻量;需要时走临时脚本,方法见「YAMNet 的边界」一节(2026-10-21 拍板) | 校准样本(有标准答案的) | 样本 | 人耳确认 | 工具给的 | 结果 | | 一首古筝领奏的器乐曲 | 古筝、无人声、民族/东方融合器乐、偏配乐/国风电子 | 筝类拨弦;五声化根音 D–E–F#;慢热加码 + 4:32 塌 + 4:48 硬收尾;方向偏民族/配乐 | 筝 ✅ 调式 ✅ 结构 ✅ 方向 ✅ 人声 ❌(误报 Choir/Singing)配器 ❌(CLAP 报了唢呐,实际没有) | | 一首民乐曲 | 民乐,没有唢呐 | 声源标签里出现唢呐 | 配器 ❌ | | 一首蒙古族乐队曲 | 确实有马头琴 | CLAP 给的是 人声 / 弦乐 / 钢琴,马头琴未进前四 | 配器 ❌(真的有的东西没认出来) | | HAYA《papillon (Live)》 | 马头琴、冬不拉、钢琴/pad、电吉他、鼓,黛青塔娜女声嘶吼 | MusicNN: rock 0.24 / guitar 0.20 / female 0.16 | 风格 ✅(摇滚底+吉他+女声全中)、配器 ❌(马头琴/冬不拉/钢琴一个都没有 —— 标签集里没有) | | 《The Rebel Path (cello cover.)》 | 开头大提琴,主体是 techno 编曲 | MusicNN: techno 0.40 | ✅ 对(曾误判为「模型发疯」,实为人耳先入为主) | | 《I Saw》 | 钢琴独奏 | MusicNN: piano 0.94 / slow 0.37 / solo 0.32 | ✅ 准得吓人 | | Guns N' Roses《November Rain》 | 摇滚乐队,吉他、男声 | MusicNN: rock 0.23 / guitar 0.22 | ✅ 对 | MusicNN 四首校准结论(2026-10-20):风格/大类判断 4/4 全对;具体乐器只有标签集覆盖的能对(钢琴、电吉他),中国民乐一律无解。 所以它接在 [标签] 行,措辞是「模型标签(非识别)」,不进 [判断]。 三条教训: - 具体乐器线索即使只有 0.012 也可能对(Zither→古筝);而 Choir/Singing 这类容易被持续音、混响垫出来,不能当「有人声」。 - 工具写「线索偏 X,只能当方向」时,别在转述里升级成「像在垫底」 —— 升级是转述者干的,不是工具的错。 - 别拿未验证的印象当「已知答案」:蒙古族乐队那条写进测试表时没确认过,后来才发现预期是对的、模型是错的。 下一步候选 1. 插件骨架 ✅ 已做(三个工具) 2. 压缩 JSON --brief ✅ 已做(约 530 B,约 130 token) 3. 局部分析 audio_section(path, start, end) ✅ 已做 4. 和弦降级为候选 ✅ 已做(根音骨架) 5. 音色分支(GPT 第一轮建议)—— 现在所有结论来自混音;要看「失真/削波/高频亮度」得单开一条 6. [FIT] 四字段化 —— applicability / confidence / ambiguity / stability 拆开(现在挤在一个分数里) 7. 缓存 —— 同一文件连问两段会重复解码;按 文件+修改时间 缓存 chroma/能量曲线 8. UI 卡片 —— 现在只有文本;DSH client 半侧能画能量条/骨架,尚未做 9. 按需 stem 分离 ✅ 已做(0.6.0)—— --stems 4s/6s,基于 demucs-onnx(纯 onnxruntime,不依赖 PyTorch)。实测 4-stem:纯器乐 vocals 约 1e-6、有人声约 25–38%,判得很干净。 模型可选安装(4s 约 150 MB fp16,6s 再加 150 MB),结果按文件缓存、重复问秒回。 仍是同步等待(短歌 60–90 秒);长歌超时提示分段。 10. 歌词接入的可行性验证 ✅ 2026-10-21 已验(见「歌词 ASR 验证」一节)——结论:LRC 优先(23/66 = 35% 覆盖),ASR 只作兜底候选且必须标「机器听写」; tiny/base 不可靠,small 体积不划算,暂不接入插件。 LRC 是人工做的,版本可能对不上,对不上时要能发现并报出来,不能硬解释 11. 从 MOSS 借东西 —— 蒸馏不可行(18 GB + CUDA,教师跑不起来)。可借:它的标签体系(它认为音乐该有哪些属性)、它的评测方法/基准、预处理细节。借来的是「该测什么」的知识,不是模型能力本身。先读论文/文档,不跑模型 已经定过的原则(新会话别重开) 2026-10-20 讨论的沉淀,每一条都是踩坑换来的: 1. 大模型是 Teacher,不是产品 —— MOSS / SongFormer 只在开发侧跑(打标、验证),用户永远不碰;进插件的必须是蒸馏/量化后的小模型(<100 MB)。 一度想把 MOSS 跑进插件,被用户纠正:那已经不是插件了,是另一个项目 2. 搜索与先验补不了「听」 —— 联网查歌手、用模型知识猜风格,都不能替代音频测量。 它只能补「这是谁」,补不了「这首听起来像什么」。 反例:知道是「cello cover」就断定它该报大提琴,结果中段是鼓 + 电音 3. 先盲测后查证 —— 先只用音频出结论,再去查资料;两栏输出,永不合并 4. 术语用英文 —— drop / breakdown / fade out / hard cut,不硬翻成「抽空/砸回」 5. 判断里允许单个数字锚点 —— 防误读;但一行两个以上就变成甩数据 6. 取件与读件分离 —— 下载音频(可能联网)和本地分析是两件事。 插件只负责「读」:「纯本地」约束的是分析,不是音频来源 7. 测量与资料永不合并 —— 输出里测的、模型标的、查到的、推的,必须能分清 音乐理解的 9 个维度(借用 MOSS-Music 的 caption 评测框架) 拿它当尺子量自己,空缺一目了然。这 9 维来自 MOSS-Music 评测 caption 时用的维度集合: | 维度 | 我们的状态 | | 速度 / 节奏感 | ✅ 硬(BPM + 双层检测) | | 结构与段落变化 | ✅ 硬(但是能量层面,不是音乐学上的 verse/chorus) | | 配器 / 音色 | ⚠️ MusicNN,只认标签集内的;中文民乐全无 | | 人声相关 | ⚠️ 弱,分不清唱还是念 | | 旋律 / 和声 | ⚠️ 只有根音候选 | | 制作 / 声学质感 | ⚠️ 响度、削波、贴顶平台,仅此 | | 风格 / 流派 | ⚠️ MusicNN 50 类,风格大类准 | | 情绪 / 氛围 | ❌ 空 | | 场景 / 用途 / 语义联想 | ❌ 空 | 9 个里 2 个硬、5 个半、2 个空。 这不是问题清单,是地图 —— 下一步该补哪格,一目了然。 已知限制(用之前必须知道) - 片段 BPM 不可当全曲速度:54 秒片段在一首钢琴曲上报 65.4,全曲是 98.7。输出会警告,但读的人仍可能忽略 - 片段统计更抖:同样的 2 秒块,整首有 126 块、片段只有 28 块,[FIT] 分数会波动 - 声源标签只到「像什么」:YAMNet 给的是 AudioSet 类别,不是乐器识别;「Bowed string instrument」不等于「马头琴」。 它能给方向(像拨弦类/偏东方),但给不了名字;中文乐器误报率高(实测把唢呐报进没有唢呐的曲子),所以判断里不写配器行,只在对话里按「推断」说 - 没有旋律、歌词、语言:音符级的内容是本地信号分析的天花板,不是 bug - 乐器/风格没有可靠的分类方案:YAMNet(521 类事件)和 CLAP(零样本)都试过,中文乐器都是零;参考库(音频对音频)是唯一没试过的路,但需要干净的乐器样本,且混音干扰仍在。 在找到可靠方案前,这两项只给「方向 + 置信」,不给结论
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
ALittleLov/dsh-soundcheck
在本机拆解歌曲的速度调性与能量走势
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,269已汉化DSH
70.8
这是你的仓库?认领条目