
简介面向macOS用户的QQ音乐QMC格式转码工具能将qmcflac转为flac、qmc0/qmc3转为mp3并支持mflac、mflac0等变体转flac附带完整源码与Xcode工程配置。它解决QQ音乐加密音频无法在普通播放器直接使用的问题适合音频处理爱好者、计算机相关专业学生作为课程设计或毕设项目的实践参考。压缩包共34个文件核心为9个Swift源文件涵盖QMCKeyDecoder密钥解码、QMCipher及TeaCipher解密等模块另有11张演示截图、GIF效果图、JSON/plist配置以及工程管理文件整体约946KB结构紧凑。资源以Xcode工程形式呈现目录清晰便于按模块定位功能代码。目前已有1406人学习下载实用价值获众多用户验证。源码包含QMCDecodeTests测试与README文档可直接运行调试也可基于现有模块二次开发深入理解QMC格式的解析思路与Swift编码实践。1. 一个Mac用户的真实困境QQ音乐下载的flac出了播放器就变砖在Mac上把QQ音乐的无损文件导进自己的播放器是我折腾过最憋屈的一件事。下载时客户端里明明写着SQ无损缓存目录里却是 .qmcflac、.mflac 这类加密后缀拖到 IINA、VLC 里全部提示无法解码。文件后缀看着像 flac内容却被套了一层壳这就是 QMC 格式转换要解决的问题。这个 zip 包专跑 macOS把 qmcflac、mflac、mflac0 解密还原成真正的 flac把 qmc0、qmc3 还原成 mp3。适合下载了会员歌曲、想在 Mac 本地播放器或音频库里正常使用的用户。下面我从加密原理、落地脚本到翻车点一次讲完。2. 认识QMC格式家族qmcflac、qmc0、qmc3、mflac的两代加密差异2.1 两代加密QMC1固定密钥表、QMC2在文件头里藏密钥QMC 不是一个算法而是 QQ音乐对本地缓存文件的统称。按客户端更新节奏它实际上分了两代解密路径完全不同。第一代是 QMC1对应 qmcflac、qmc0、qmc3 这类后缀。它的做法是把一段固定密钥表写死在客户端里用 RC4 流对音频数据做异或加密所以同一批老客户端下载的文件解密时只需要拿到那一套密钥表一个工具就能通吃。劣势也非常明显密钥表是全局共享的只要被提取出来整个加密体系对社区来说就没有秘密所以后来 QQ音乐换掉了方案。第二代是 QMC2对应 mflac、mflac0。密钥不再是全局固定而是写进每个加密文件自己的头部结构里。解密第一步是读文件头部找到密钥段解析出密钥长度和实际密钥内容再做流式异或。因此转换工具必须明确区分两条解密路径看到 qmc 前缀走固定密钥表看到 mflac 前缀先拆头部取密钥。如果你搜过同类问题会发现网上很多人把 qmcflac 和 mflac 混为一谈这会导致解密到一半开始出乱码输出文件时长不对或爆音属于原理层面的踩坑。这套加密方案对音频数据本身没有做压缩或重编码它只是做了一层流式异或所以解密后的数据在理论上和原始文件逐字节一致。这一点很重要意味着转换是无损的不需要重编码转换速度取决于磁盘 IO 和 RC4 解开的吞吐而不是 CPU 编码速度。很多刚接触格式转换的人以为转 flac 要像转 aac 那样跑一遍编码器其实这里没有编码动作只有解码和搬运。解密程序本身黑匣子一样的地方在于密钥表的来源和 QMC2 头部偏移的组织方式这也是后面避坑章里各种怪问题的根源。2.2 终端三件套file、xxd、ffprobe 判断文件是否加密、属于哪一代把文件丢进 Finder 看不到任何编码信息Mac 的显示简介也不会告诉你里面是不是真 flac。我一般先在终端里跑三个命令摸底cd ~/Music/QQMusic file *.qmcflac *.mflac *.qmc0 *.qmc3 2/dev/null xxd -l 128 测试.qmcflac xxd -l 128 测试.mflacfile 对正常 flac 会输出 FLAC audio bitstream data对加密后的文件基本只能输出 data如果它输出 MPEG ADTS 反而是好事说明这个文件没有加密或者已经被还原过。xxd 看的是文件头正常 flac 前 4 字节是 fLaC 这个可见签名qmcflac 加密后前面 128 字节基本看不到任何可读签名mflac 因为头部带密钥结构看起来像一段乱码里夹杂少量可辨识的长度段。我这里不给你背固定偏移原因很简单不同客户端产出的文件头部偏移并不统一与其对照十六进制不如直接看被加密后 file 能不能认出这个文件。ffprobe -v error -show_format 测试.mflac 21 | head -5这条命令如果直接报 Invalid data found when processing input说明文件没被识别成任何已知封装基本可以确定是加密状态。ffprobe 是 ffmpeg 套件里的探针工具后文还要反复用到macOS 上装一个很值brew install ffmpeg会连它一起装上。注意 -v error 只输出严重错误不会刷一大屏日志head -5 是防止报错信息太长。这套判断方法只依赖文件本身不需要网络、不需要登录账号也不依赖客户端版本所以我把它放在转换前面当成固定流程。早期社区流传过一张表说 qmcflac 的文件头在某个偏移有什么标记我用它批量判断翻过车。原因是不同版本的客户端对文件头做了不同处理尤其 mflac 系变体头部会有额外字段。现在我的习惯改成后缀 ffprobe 两条判断。后缀决定用哪条解密路径ffprobe 决定解密有没有成功这个组合比盲目读 hex 可靠得多。2.3 先摸清你的文件规模按扩展名统计再决定批量策略动手转换之前建议先按扩展名统计一下手上文件的规模免得写了一下午脚本最后发现只有两个文件要转。也可以避免另一个极端五千个文件一次性塞进命令行参数让 shell 直接卡死。下面这条命令按扩展名分组计数find ~/Music/QQMusic -type f \( -name *.qmcflac -o -name *.mflac -o -name *.mflac0 -o -name *.qmc0 -o -name *.qmc3 \) | awk -F. {ext$NF; count[ext]} END {for (e in count) print e, count[e]} | sortawk 的 -F. 把文件名按点拆开取最后一列当扩展名count[ext] 做累加最后统一输出。这里有个小坑文件名如果带多个点比如 周杰伦.七里香.qmcflac-F. 取的 $NF 依然是最后一个点后的字段所以没问题。统计完你会得到类似 qmcflac 240、qmc0 86、mflac 22 的数字。这个数字决定了两件事第一要不要写批处理脚本少于 10 个文件的话手动敲单条命令反而省事第二给后面 xargs 的并发数定上限文件越碎、单文件越小并发越可以开大。如果你发现一批 .mgg 后缀那属于 QMCv2 新变体部分老工具不支持别指望这一个 zip 全包后面避坑章还会提到一次。统计完后把可疑的、后缀被改坏的文件单独挪到一个未知目录交给转换工具按内容探测不要手工乱改名。3. 在macOS上跑通转换环境准备、Gatekeeper、单文件验证3.1 先把环境补齐Command Line Tools、ffprobe为什么坚持终端流程而不是找个图形界面的转换 App因为 QMC 转换属于典型的文件多、单文件小、报错信息藏在深处的批量场景。图形工具一次拖几百个文件进去你根本不知道哪个失败、为什么失败日志窗口往往是面子工程。命令行脚本的每一步都有输出失败文件能被单独标记这比在界面里等一个转圈按钮踏实得多。macOS 自带 unzip、bash、zsh但转换完你总得验证结果所以 ffprobe 几乎是必装。先检查已有环境xcode-select -p which ffprobe第一条如果输出 /Library/Developer/CommandLineTools 说明命令行工具已装如果提示找不到运行xcode-select --install会弹窗引导安装。第二条看 ffprobe 在不在 PATH 里没输出就说明没装或没链接。ffprobe 可以通过 Homebrew 装也可以直接装 ffmpeg 一整套brew install ffmpeg。我不建议为了省空间只装 ffprobe因为后面的避坑场景里你还可能用到 ffplay 试听和 ffmpeg 抽封面。3.2 解压 zip 包顺手处理 Gatekeeper 隔离属性解压和查看结构是第一步cd ~/Downloads unzip -o QQ音乐QMC格式转换*.zip cd QQ音乐QMC格式转换*/ ls -la file ./qmc-decoder 2/dev/nullfile 那一行会打印这是一个 Mach-O 可执行文件这是 macOS 的二进制格式如果显示 ELF 说明下错包了那是 Linux 版本Mac 跑不了。接下来是每个 Mac 用户都会遇到的那道坎从互联网下载的 zip 压缩出来的程序会被打上 com.apple.quarantine 隔离属性直接双击或者第一次执行系统会弹无法验证开发者因为未签名。这个 zip 里的命令行工具大概率没有苹果开发者签名所以终端执行前先把隔离属性摘掉xattr -d com.apple.quarantine ./qmc-decoder 2/dev/null || true这里我把可执行文件统一写成 qmc-decoder 占位名每个包的实际命令名不一定叫这个以你解压目录里真实文件名和 README 为准。xattr -d 删除指定属性2/dev/null 把属性不存在的报错吞掉|| true 保证即使失败脚本也不中断。如果这个包的执行文件不止一个建议对所在目录逐个操作或者干脆xattr -dr com.apple.quarantine .-r 递归注意别在别的目录乱用。操作之前还有一道保险把原始文件复制到一个只读工作目录再转避免原地覆盖。下载目录里的 qmcflac 就当存档留着直到整批文件验证通过再清理。我吃过亏密钥表版本对不上时手里没有原始文件就等于没有后悔药。3.3 单文件转换跑通先用最小样本验证批量之前一定先单文件不要上来就五万个文件怼给脚本。我一般挑一个刚才统计出来的普通样本./qmc-decoder -i 测试.qmcflac -o 测试.flac这是假定的命令行参数风格实际参数名以 README 为准-i 指向输入文件-o 指向输出路径。跑完后立刻验证ffprobe -v error -show_streams -select_streams a:0 -of defaultnoprint_wrappers1 测试.flac如果能看到 codec_nameflac、sample_rate44100 这类输出说明文件已经被解开。如果 ffprobe 还是报错先不要怀疑工具坏了把输出文件用 xxd 看前四字节能看到 fLaC 就说明解了一半、封装有问题看不到则说明解密路径没走对。这一步只花两分钟能省掉后面批量转换时的所有不确定性。跑通过的输出文件也不要删把它当作基线。后面批量转换时如果某些文件产出不对拿基线的 ffprobe 输出和失败文件对比能很快定位是这个文件本身损坏还是工具在这个变体上翻车。4. 批量转换脚本与参数调优qmcflac转flac、qmc0转mp3的完整落地4.1 按扩展名映射输出格式写一个 zsh/bash 批处理脚本单文件跑通后批量只是把逻辑重复起来。格式映射关系是核心qmcflac、mflac、mflac0 全部落 flacqmc0、qmc3 落 mp3。写成脚本#!/bin/zsh tool$HOME/qmc-tool/qmc-decoder out_dir$HOME/Music/QMC_Converted mkdir -p $out_dir [[ -x $tool ]] || { echo 工具不存在请检查 tool 路径; exit 1; } declare -A map( [qmcflac]flac [mflac]flac [mflac0]flac [qmc0]mp3 [qmc3]mp3 ) if [[ $# -lt 1 ]]; then echo 用法: $0 文件或通配符 ... exit 1 fi for f in $; do [[ -f $f ]] || { echo 跳过不存在: $f; continue; } ext${f##*.} target${map[$ext]} if [[ -z $target ]]; then echo 跳过未知扩展名[$ext]: $f continue fi base${f%.*} out$out_dir/$(basename $base).$target $tool -i $f -o $out \ echo [OK] $f - $out \ || echo [FAIL] $f done这段的逻辑分三段看。第一段是环境准备tool 指向解压出来的可执行文件实际路径如果你的工具名不一样改这一行就行out_dir 是输出目录mkdir -p 保证它存在。第二段是映射表declare -A 定义关联数组这是 bash 4 的特性macOS 自带的 bash 是 3.2默认会报 declare: -A: invalid option所以脚本第一行我直接写成 #!/bin/zshzsh 原生支持关联数组macOS 的 zsh 版本也够新这是最省事的绕坑方案。第三段是循环主逻辑。${f##.} 是去掉最长前缀后取扩展名${f%.} 是去掉后缀取主干这两个参数展开式在处理带空格、带多点文件名时比 cut 命令稳。整个脚本对每个文件做一次映射判断映射不到的扩展名直接跳过不会影响其他文件。调用方式chmod x convert_qmc.sh ./convert_qmc.sh ~/Music/QQMusic/*.qmcflac ~/Music/QQMusic/*.qmc0 ~/Music/QQMusic/*.qmc3如果文件多到命令行参数超限几千个文件时常见改用 find 配合 xargsfind ~/Music/QQMusic -type f \( -name *.qmcflac \) -print0 | xargs -0 ./convert_qmc.sh4.2 并发调优M系列芯片开几路最合适批量转换本质是 IO 加轻量解密CPU 不会吃满但你开太多并发内存会先爆。8GB 内存的 M1 机器我一般开 2 到 3 路16GB 或 32GB 的 M2、M3 开 4 到 6 路比较稳。用 xargs 控制并发最省事直接把文件喂给上一个脚本让并发参数决定同时跑几个脚本进程find ~/Music/QQMusic -type f \( -name *.qmcflac -o -name *.mflac \) -print0 \ | xargs -0 -P 4 -I{} ./convert_qmc.sh {}-P 4 代表同时最多起 4 个脚本进程-I{} 是占位符每次把读到的文件名替换到 {} 位置。这样不用关心 bash -c 引号转义中文和空格文件名也能安全传递。如果转完发现磁盘一直响但 CPU 占用很低说明瓶颈在 IO把 -P 降一档反而整体更快这个要靠现场压测看。还有个容易撞上的同名覆盖问题同一首歌可能同时有 qmcflac 和 mflac 两个版本base 名一样先转的会被后转的覆盖。我的习惯是输出文件名保留原扩展名线索比如把输出命名为 歌名.qmcflac.flac虽然丑但不会丢文件。你如果介意可以按原文件的相对目录重建 out_dir 结构。4.3 参数边界不重采样、保留元数据和封面的正确姿势转换工具的默认行为应该是原样解密不重采样、不重编码。你唯一可能要改的是输出目录、并发数和是否保留原文件名。不要试图在转换时把 96kHz/24bit 的 flac 顺手转成 alac 或 aac那是另一层工作。很多人在这一步上当以为工具能解密就能顺便转码结果 flac 96kHz 24bit 转换 alac 失败回头怪工具。QMC 转换的目标是把加密壳去掉不是做音频转码头。如果你手里的原始文件是 mflac但播放器只收 mp3正确的做法是先让工具输出 flac再用 ffmpeg 二压 mp3别的什么都别动。mflac 转 mp3 是两步不是一步。元数据方面老工具往往只还原音频流不保证保留内嵌封面。想要封面的转换后用 ffmpeg 抽ffmpeg -i 输出.flac -an -vcodec copy cover.jpg这条命令从 flac 里把封面帧单独拷出来如果输出为空说明原文件就没内嵌封面跟工具无关。另外整个下载目录如果混着 ncm 格式的网易云文件或者酷狗 kgg 转换 mp3 的文件那是完全不同的加密体系不要试图用这个工具去解脚本只会把未知扩展名安静地跳过。同样的道理想搜QQ音乐下载mgg转换为mp3的人也得先确认手里的 mgg 是不是这个 zip 支持的版本新客户端产物经常和老工具脱节。5. QMC转换避坑指南我翻过车的5个典型场景5.1 解压后双击闪退终端执行报无法验证开发者现象zip 解出来的工具第一次跑就闪退或者终端里执行直接弹 killed。原因macOS Gatekeeper 给所有网络下载文件加了隔离属性未签名的命令行程序不经过右键打开会被直接拦截M 系列芯片上还可能叠加架构不匹配的问题Intel 版二进制在 Apple Silicon 上需要 Rosetta 2 才能跑。解决先执行xattr -d com.apple.quarantine ./qmc-decoder摘掉隔离属性如果还闪退用file ./qmc-decoder检查是 Mach-O 64-bit x86_64 还是 arm64。Intel 版在 Apple Silicon 上要么装 Rosetta 2要么找原生 arm64 的构建这个在下载时就要看清说明。5.2 转出来的 flac 有几十 MB播放器里时长却是 0:00现象文件大小正常拖进 IINA 显示时长 0进度条不能拖播放器直接卡住。原因解密路径选错了最常见于把 QMC2 的 mflac 文件走 QMC1 固定密钥表去解。解出来的是从错误偏移开始的二进制流头部损坏播放器无法计算时长。mflac 和 mflac0 的头段解析在部分工具里混着用也会出现类似问题。解决确认扩展名后缀没被改过如果确实是 mflac看工具 README 是否明确声明支持 QMC2不支持就换一个维护更新一些的替代工具。这一条没太多参数可调属于原理性限制靠调参数救不回来。5.3 Apple Music 认不出输出 flac96kHz/24bit 转 ALAC 又失败现象转出来的 flac 在 Finder 里 QuickTime 能预览但 Music 应用里导入显示不识别。原因Apple Music 的原生曲库不读 flac这是产品限制不是转换失败。如果你想进曲库只能先转成 ALAC而 96kHz/24bit 的高采样 flac 用 macOS 自带的音频转换组件经常报错这个错误在社区里已经是大面积存在的现象。解决plist 层面没有后悔药我一般就是不改动直接用 IINA 或 VLC 播放 flac或者把 flac 放进支持它的第三方播放器非要进曲库用 ffmpeg 手动转 alac同时把采样率降到 48kHz 以内可以避开大多数失败。5.4 中文文件名带空格批量跑一半报 unable to open output file现象大部分文件成功了个别中文名或带空格的文件失败报找不到输出文件或输出路径。原因脚本里变量没有加双引号路径里的空格和中文在传给工具时被 shell 拆成了多个参数工具拿着半截路径去创建文件自然就失败。解决所有引用变量的地方都写成 $f $out参数展开式不要省引号如果已经翻车用 find -print0 配 xargs -0 的方式传参空字符分隔保证文件名原样传递这是应对文件名里什么都有的批量场景最稳的一套组合。5.5 qmc3 转出来的 mp3 有杂音或沙沙声现象转换成功、可以播放但声音像加了噪声尤其前几秒最明显越往后越乱。原因QMC1 的密钥表存在多个版本旧客户端下载的文件用的是老密钥表工具内置的新密钥表解出来对不上流式解密错位。同一个扩展名、不同年份下载的文件解出来的效果可能完全不一样这块很玄学。解决看工具 README 是否带多个密钥表或者类似 -m qmc1_v2 的版本参数有就换着试没有的话只能找维护更全的工具。遇到这类文件我一般会先保留原始文件等找到匹配的工具版本再解而不是拿新工具硬压。提示转换前永远留一份只读原文件输出目录单独建。密钥表版本对不上或者变体识别错误时原始文件就是你的后悔药。6. 转换结果验证用ffprobe确认还原本真顺手把封面抽出来6.1 逐文件核对编码参数批量转完我习惯跑一条汇总验证把输出目录里所有音频的编码信息打出来find ~/Music/QMC_Converted -type f \( -name *.flac -o -name *.mp3 \) -print0 \ | xargs -0 -I{} ffprobe -v error -show_entries streamcodec_name,sample_rate,channels,bits_per_raw_sample -of defaultnoprint_wrappers1:nokey0 {}输出会按文件顺序打印 codec_namesample_ratechannelsbits_per_raw_sample 组合比如 flac44100216。真实无损下载对应该组合如果看到 flac96000224说明这是高解析度版本也是正常的。对不上的文件单独挑出来重新检查原扩展名和工具版本别带着疑问进入下一步。6.2 试听和封面核对参数对完再试听一首用 ffplay 可以直接播ffplay -nodisp -autoexit 输出.flac最后把封面抽出来看一眼是否完整ffmpeg -i 输出.flac -an -vcodec copy cover.jpg封面缺失不影响听感但如果你要整理曲库封面墙这一步就别省。我现在养成的习惯是转换前先跑一次文件统计和 ffprobe 留底转换后再对一次输出目录两次对不上就去翻工具版本不硬解。这个流程看起来多花两分钟但能避免整批文件解错后才发现的大返工。希望帮到你。本文还有配套的精品资源点击获取