本地音乐是音乐客户端里最容易被低估的功能。买了数字专辑、存了现场录音、或者从 CD 抓了轨,这些文件散在硬盘里,用文件夹管理迟早会乱。客户端的做法是建索引:读标签、算音频指纹、把结果与曲库、云盘合并成一份检索结果。
测试用的资料库来自一位有十年收藏习惯的用户:12000 个文件,620GB,格式包括 FLAC、MP3、WAV、APE 与少量 M4A。目录结构混乱,有的按歌手分,有的按年份,还有三个「新建文件夹」。这大概是真实用户的平均水平。
扫描到底在扫什么
扫描分三段。第一段是文件系统遍历,读目录树与文件头,拿到路径、大小、时长;第二段是标签解析,读 ID3v1/ID3v2、Vorbis Comment、APE Tag;第三段是音频指纹计算,用于把同一首歌的不同版本归到一起。
指纹计算最耗 CPU。客户端会抽样前 30 秒做频谱特征,一首 4 分钟的歌大约 0.2 秒,12000 首理论上要 40 分钟。实际只用了 4 分钟,因为它做了两级缓存:同一文件的哈希不变就跳过,同一专辑的指纹批量计算。
标签缺失时回退到文件名解析,支持「歌手 - 歌名」「01. 歌名」「歌名 - 歌手」三种格式。回退结果会标记为「推测」,在列表里以灰色字体显示,避免和真实标签混淆。
12000 个文件的实测数据
测试机为 Windows 11、NVMe SSD、16GB 内存,客户端 9.2.10,扫描目录放在第二块 SSD 上。首次扫描与二次扫描分别计时,二次扫描在清空缓存后进行。
| 阶段 | 首次耗时 | 二次耗时 | 说明 |
|---|---|---|---|
| 目录遍历 | 38 秒 | 12 秒 | 元数据已在系统缓存 |
| 标签解析 | 1 分 46 秒 | 9 秒 | 按文件哈希跳过 |
| 指纹计算 | 1 分 31 秒 | 0 秒 | 缓存命中 |
| 写入索引 | 17 秒 | 6 秒 | SQLite 批量提交 |
| 合计 | 4 分 12 秒 | 27 秒 | 二次扫描接近瞬时 |
标签缺失的情况比预想严重:2210 个文件没有可读标签,占 18.4%。其中大部分是从老 CD 抓轨的 WAV,以及从各种论坛下载的 APE。文件名解析救回了 2033 个,剩下 177 个文件名只有「track01」这类信息,只能靠指纹匹配到曲库。
| 格式 | 文件数 | 缺标签 | 文件名可解析 | 指纹匹配 |
|---|---|---|---|---|
| FLAC | 5400 | 312 | 298 | 14 |
| MP3 | 4300 | 486 | 470 | 16 |
| WAV | 1500 | 1020 | 935 | 85 |
| APE | 800 | 392 | 330 | 62 |
WAV 是重灾区,因为它本身不支持 ID3 标签,客户端只能读 RIFF 信息块,而抓轨软件通常不写。这也解释了为什么很多人的本地库「一半是未知歌手」。
「本地库的体验上限不在扫描速度,而在标签质量。扫描再快,标签是空的也搜不到。」——客户端本地音乐模块的产品说明
合并检索的六步设置
第一步,把音乐目录一次性加进「本地音乐 → 添加文件夹」,不要分批加。分批会触发多次全量比对,反而更慢。
第二步,等待首次扫描完成再操作。扫描中搜索会返回不完整结果,容易误判为「文件没被识别」。
第三步,打开「按来源分栏」。搜索时本地、云盘、曲库三栏并列,本地命中会标「本地文件」标签,点击直接播放,不耗流量。
第四步,修标签。选中灰色字体的条目,右键「编辑标签」,批量填入歌手与专辑。客户端支持多选后统一改专辑名,但歌手需要逐条确认。
第五步,处理重复。同一首歌的单曲版、专辑版、现场版会被指纹归到一组,展开后默认播放本地文件。不想要的版本可以「从本地库隐藏」,不会删除硬盘文件。
第六步,设置监控目录。「自动扫描新文件」开启后,往目录里拖新歌会在 30 秒内出现,不需要手动刷新。机械盘建议关掉这个开关,扫描时的寻道会影响其他程序。
六步做完,12000 个文件基本能做到「搜得到、播得动、不重复」。本地库不会上传你的文件,索引只存在本机,换设备需要重新扫描。客户端在下载页可获取。
用户评论(4 条)
WAV 没标签这点太真实了,我 800 多首全是未知艺术家,只能靠文件名。
按来源分栏之后舒服多了,以前搜一首歌出来三个版本,不知道点哪个。
二次扫描 27 秒这个可以,我 2 万首,第一次扫了快十分钟。
APE 标签乱码是编码问题,转成 FLAC 就好了,别硬修。