DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

yousj666 /

yousj666/dsh-audio-converter

Verified

DSH 音频转换器:解密网易云 NCM / 酷我 KWM / 酷狗 KGM / QQ音乐 QMC,格式互转 + 音质增强(EBU R128 响度归一化、EQ、重采样、位深)。可打成 197MB 单文件 exe,零依赖。

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@1c4ed894

dsh-audio-converter

音频转换器:解密各平台加密音乐,常规格式互转,并提供真实的音质增强。带拖拽界面。

拖进去,出来就是能播的文件。

网易云 .ncm  ─┐
酷我   .kwm  ─┤
mp3 / flac   ─┼─→  解密 → 增强 → 转码 → 打标签 → 输出
m4a / wav    ─┤
ogg / opus   ─┘

加密格式支持情况(诚实版)

平台 扩展名 状态 说明
网易云音乐 .ncm ✅ 已支持 与已知正确结果逐字节一致(32 个断言验证)
酷我音乐 .kwm ✅ 已支持 密钥恢复 + 容器嗅探验证(15 个断言)
酷狗音乐 .kgm .kgma .vpr ✅ 已支持 v1~v4 已实现(272 字节 MEND 表 + 17/16/272 三重异或),与独立参考实现跨语言对拍
QQ音乐 v1(老格式) .tkm .bkc* ✅ 已支持 128 字节公开静态密钥;含 0x7FFF 边界规则,已跨语言对拍
QQ音乐 v2(mflac/mgg) .mflac .mgg .qmcflac ✅ 已支持 尾包内嵌 EKey 的(QTag / PcV1Legacy)直接解;已跨语言对拍
QQ音乐 v2(无内嵌密钥) STag / MusicEx 尾包 ⚠️ 需外部 EKey 尾包里只有资源元数据、没有密钥,得从客户端数据库取
QQ音乐 v3(新版) .mgg1/.mgg2/.mmp4 ❌ 离线不可能 见下
酷狗 KGG 加密版本 5 ❌ 不可能 密钥在客户端密钥库里
虾米音乐 .xm ❌ 不可能 虾米已停止服务

QMC v2 的四种尾包

QQ 音乐 v2 的密钥跟着文件走,藏在文件末尾的「尾包」里。四种形态:

尾包 有 EKey? 能不能离线解
QTag ✅ 内嵌 能 —— 直接解
PcV1Legacy ✅ 内嵌 能 —— 直接解
STag ❌ 只有资源号 + mid 需要外部 EKey
MusicEx ❌ 只有文件名 需要外部 EKey

后两种的密钥存在客户端本地数据库(安卓端 player_process_db)里,文件本身不含。 工具和界面上都有 EKey 输入框,把密钥填进去就能解。

判断「能不能解」用尾包解析结果,不是看标记名。 一开始我按 STag/QTag 标记判定,把 STag 误判成「新版无解」—— 其实它和 QTag 一样都是 v2,区别只在尾包里有没有密钥。

为什么有两项是「不可能」而不是「还没做」

QQ 音乐新版采用动态密钥分发 + 设备指纹绑定:

播放请求 → 服务端验证账号与设备合法性 → 下发密钥 → 本地解密

密钥根本不下发到本地文件里。 所以拿到 .mgg1 / .mgg2 / .mmp4 之后, 本地没有任何可用于解密的材料 —— 这不是实现难度问题,是设计上就不给。

与其假装支持然后吐一个损坏文件,不如直接说清楚。 界面和 audio_capabilities 工具都会明确告诉用户这一点,并给出可行替代方案 (用客户端重新下载为普通格式,或在客户端内导出)。


音质增强:会做什么、不会做什么

会做(真实有效的处理)

处理 效果 参数
响度归一化 让音量一致,避免忽大忽小 EBU R128,默认 -16 LUFS / -1.5 dBTP
夜间模式 压缩动态,小声也听得清 acompressor ratio 4:1
暖声 EQ 减少刺耳感 200Hz +2dB / 4kHz -2dB
明亮 EQ 提升清晰度 3kHz +3dB / 10kHz +2dB
人声突出 播客/人声向 1kHz +2dB / 300Hz -2dB
低频增强 补耳机低频 80Hz +5dB
高通 去超低频浑浊 30Hz
重采样 / 声道 匹配设备 任意采样率、单/立体声
位深 匹配设备或做后续处理 16 / 24 / 32 位(只对 flac/wav 这类无损容器有意义)

不会做

无法恢复有损编码已经丢掉的信息。 128kbps 的 mp3 转成 FLAC 不会变好听 —— 它只是把同样的信息用更大的容器装起来。 界面和工具描述里都明确写了这一点,不做「一键变无损」这种假承诺。


常规格式互转

mp3 · flac · m4a · aac · wav · ogg · opus

三档质量:体积优先 / 标准 / 质量优先。


装

dsh plugin --profile <profile> add dsh-audio-converter
# 或本地开发
dsh plugin --profile <profile> add link:/path/to/dsh-audio-converter

依赖 ffmpeg(必需)。程序会**按「能不能跑起来」**自动探测,不依赖任何固定路径:

winget install Gyan.FFmpeg        # Windows
brew install ffmpeg               # macOS
apt install ffmpeg                # Debian/Ubuntu

⚠️ 探测用的是「试跑 -version」而不是 existsSync —— 因为 WinGet 的应用执行别名(App Execution Alias)Node 的 existsSync 解析不了, 而且 winget 有时会留下「清单还在、文件已删」的幽灵安装(本机就遇到了)。 详见知识库 P-017。


用

界面上用(推荐)

会话视图多一个 「音频转换」 页签,排在 「上下文」「定时任务」 后面 (conversation.view,order 40)。

把文件拖进虚线框  →  选格式/质量/增强  →  点「开始转换」
  • 拖拽 或 选择文件
  • 任务走 job 模型,界面不卡;实时显示状态、耗时、输出体积
  • 底部有诚实的能力矩阵,哪些能解、哪些不可能,一目了然
  • 文件全程在本机处理,不上传任何服务器

让模型帮你转

「把 G:\CloudMusic\VipSongsDownload 里的 ncm 全转成 mp3」
「看一下这个 .mgg 文件到底是什么格式,能不能解」
「把这批 flac 做响度归一化,再转成 m4a」

三个工具:

工具 作用
audio_convert 转换/解密文件或整个目录,可指定格式、质量、增强预设
audio_inspect 看一个文件到底是什么(按 magic 不按后缀)、能不能解
audio_capabilities 查支持矩阵与 ffmpeg 状态,处理前先确认

设计说明

格式识别:先看 magic,再看后缀

有些人只是把 FLAC 改成了 .ncm 后缀。只看后缀会把普通文件当加密文件处理, 白白报错。所以先按文件头识别:

CTENFDAM            → NCM
7C D5 32 EB …       → KGM
05 28 BC 96 …       → VPR
fLaC / ID3 / OggS / ftyp / RIFF  → 普通音频,无需解密
STag / QTag / musicex            → QQ音乐新版

结果结构必须一致

processFile 有两条返回路径(只解密 / 解密+转码)。第一版里提前返回那条 漏了 srcInfo 和 meta —— 调用方得按分支处理,很容易漏字段。 现在两条路径返回完全相同的结构,并且有测试盯着这条约束。

解密正确性怎么验证的

不是「自己加密再自己解密」 —— 那只证明两者互逆,证明不了跟真实格式一致。

  • NCM:拿真实 .ncm 解密,跟一份已知正确的转换结果 在去掉 ID3 标签之后逐字节比对 → 完全一致
  • KWM:自造样本往返(5 轮随机内容)+ 三条密钥恢复路径 + 认不出时必须抛错

顺带一个坑:直接比整个文件的哈希会误判 —— 不同工具解密后会把封面 重新嵌进 ID3,一个 1KB 的标签能变成 795KB,但音频载荷是一样的。 详见知识库 P-018。


测试

npm test                 # 一次跑完 8 个测试文件

node test-ncm.mjs        # NCM 解密器           32 个断言
node test-kwm.mjs        # KWM 解密器           15 个断言
node test-kgm-qmc.mjs    # KGM + QMC v1         41 个断言(跨语言对拍)
node test-qmc2.mjs       # QMC v2               46 个断言(跨语言对拍)
node test-ffmpeg.mjs     # ffmpeg 封装          75 个断言
node test-pipeline.mjs   # 格式识别与管线       57 个断言
node test-host.mjs       # host 半边            60 个断言
node test-client.mjs     # 浏览器半边          34 个断言

合计 360 个断言。 不需要装进 DSH、也不需要浏览器(除 host/client 用 mock ctx)。

只需 Node ≥ 22.19,没有构建步骤。 ffmpeg 可选 —— 没装的话用到它的测试会跳过。

test-ncm.mjs 的第 4 节需要你自己的 .ncm 素材(用环境变量指定,见 CONTRIBUTING.md);没设就整节跳过,其余断言照常跑。

亮点:

  • 真实素材 + 外部锚点:真 .ncm 文件 → 与已知正确结果在去掉 ID3 之后逐字节比对
  • 跨语言对拍:黄金值由一份独立写的 Python 参考实现算出(不 import 原项目), JS 侧翻译错了就对不上。QMC 的 0x7FFF 边界、TEA 的 float32 语义、 Map/RC4 的流密码全都靠这个办法验证
  • 实测增强效果:用 ffmpeg 的 volumedetect 量处理前后的响度,确认不是空转
  • 回读产物校验:转完再探测一遍输出,比对采样率/时长/编码 —— 采样率被滤镜悄悄改掉就是这么抓到的
  • 回退路径也测:没有 ffprobe 时解析 ffmpeg -i 的 stderr,22 个断言确保结果和 ffprobe 一致
  • 安全栅栏:非回环 Host / 跨站发起一律 403;上传时的路径穿越防护
  • 诚实性断言(源码级):界面必须写明「无法恢复有损信息」「离线做不到」

已知边界

  • QMC v2 的 STag / MusicEx 尾包不含密钥 —— 需要用界面上的 EKey 输入框手动提供
  • 酷狗 KGG(加密版本 5)不支持 —— 密钥在客户端密钥库
  • QQ音乐 v3(新版)离线无解 —— 不是实现问题,是密钥不下发到本地
  • 酷狗公钥表是截断版(8 MB,覆盖 128 MB 音频)。要处理更大的文件,跑 node scripts/expand-kugou-key.mjs 生成完整表(69.77 MB)
  • 上传文件上限 512MB(拖拽走 HTTP,超大文件建议用工具传路径)
  • 批量处理是串行的(避免一次转几十首把机器打满);一次提交几十首会排队
  • 解密后立即写入 ffmpeg 能读的临时文件,转换完不会自动清理临时目录
  • QMC/KGM 没有官方测试素材 —— 验证靠「自造合法样本 + 跨语言对拍」, 不是靠真实文件。如果你手上有真实文件跑出问题,欢迎反馈
  • Windows 路径分隔符按反斜杠处理;其他平台未实测

三种用法

① DSH 插件(本项目的主体)

会话视图里多一个「音频转换」页签(conversation.view,order 40),拖文件进去就行。 同时给模型注册 3 个工具,可以直接说「把某个文件夹里的 ncm 全转成 mp3」。

② 命令行(需要 Node + ffmpeg)

node convert.mjs <文件或文件夹...> [--format mp3] [--enhance loudness] [--out 目录]
node convert.mjs --list      # 看支持哪些格式
node convert.mjs --dry       # 只识别格式,不真转

Windows 上也可以双击 convert.bat,或者把文件拖到它上面。

③ 单文件 exe(不需要任何依赖)

npm run build-exe

打出一个约 197 MB 的独立 exe(内嵌 Node + ffmpeg):

  • 拖文件上去 → 直接转成 mp3
  • 双击 → 本地网页设置界面,能选格式/质量/位深/增强

拷到任何 Windows 上都能跑,不需要装 Node、不需要装 ffmpeg。

体积构成:node 88 MB + ffmpeg 100 MB + 酷狗公钥表 8 MB。 不带 ffprobe —— 它是另一个约 100 MB 的静态二进制, 而 probe() 已经能在没有它时解析 ffmpeg -i 的 stderr(22 个断言盯着这条路径)。


文件

lib/crypto/ncm.js               NCM 解密器(AES-128-ECB + RC4 变体)
lib/crypto/kwm.js               KWM 解密器(32 字节循环 XOR + 密钥恢复)
lib/crypto/kgm.js               KGM 解密器(MEND 表 + 三重异或)
lib/crypto/qmc.js               QMC v1(128 字节静态密钥 + 0x7FFF 边界规则)
lib/crypto/qmc2.js              QMC v2(尾包解析 + TEA + Map/RC4 流密码)
lib/crypto/assets/kugou_key.bin 酷狗公钥表(8 MB,覆盖 128 MB 音频)
lib/crypto/assets/kugou_key.xz  同一张表的完整版压缩源(94 KB)
lib/ffmpeg.js                   ffmpeg 封装:探测 / 转码 / 增强 / 打标签
lib/pipeline.js                 格式识别 → 解密 → 转换 → 增强 的调度
lib/resources.js                资源解析:磁盘文件 / exe 内嵌 两种模式
lib/index.js                    host 半边:3 个工具 + 5 条 HTTP 路由 + job 队列
lib/client.js                   浏览器半边:拖拽页签(手写,无构建)
convert.mjs                     命令行入口
convert.bat                        Windows 拖拽入口
exe/main.mjs                    单文件 exe 的入口(拖拽 + 本地界面)
exe/build.mjs                   打包脚本(esbuild → SEA → postject)
scripts/expand-kugou-key.mjs    从 .xz 生成完整公钥表
test-*.mjs                      8 个测试文件,360 个断言
diag-ncm.mjs                    NCM 诊断工具(排查"解出来对不对"用)

参与开发

见 CONTRIBUTING.md。两条硬规矩:

  1. 解密正确性必须用外部锚点证明 —— 自己加密再自己解密只能证明互逆
  2. 做不到的如实标注 —— 宁可报错也不要吐出损坏文件

许可

MIT —— 见 LICENSE。

解密算法的参考资料、酷狗公钥表的来源与性质、FFmpeg 的许可说明, 都写在 THIRD-PARTY-NOTICES.md 里。

免责声明

本项目仅用于个人已购音乐的格式转换 —— 把你花钱买的歌从专有容器里拿出来, 在你自己拥有的设备上播放。请勿用于传播受版权保护的内容。

—/ 5

No ratings yet

Verified DSH bundle

Commit 1c4ed8947c7d

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout