有看过之前文章『使用 mp3agic 读写 MP3 的 ID3 标签』的读者们应该知道,前段时间我在整理本地音乐库,本篇是对『本地音乐库构建:音源处理』的补充。

前面提到我本地的音乐库体积庞大,经过这次整理和添加,体积已经突破 30GB,并且还在继续膨胀。

众所周知,最近内存价格疯涨,存储空间越来越宝贵,我不得不考虑如何压缩音乐库的体积。

直接用 ZIP 压缩音乐库首先被我排除。原因很简单:ZIP 需要解压后才能读取文件,使用上不够便捷;而且 MP3 本身就是高度压缩的格式,ZIP 几乎无法进一步压缩。

看来只能从音频本身入手了,要么转换格式,要么降低码率。

而在之前『本地音乐库构建:音源处理』中,我通过 FFmpeg 将 OGG 转为 MP3,主要是为了更好的兼容性,目前没有再迁移格式的打算,那么可行的方案就只有降低码率了,准确来说,应该是比特率。因为目前我手头上已经没有高功率的发烧设备,以后大概率也不会再购买,听音乐的需求停留在能听个响就行。

在音频文件中,kbps 是“千比特每秒”(Kilobits Per Second)的缩写,它代表了音频数据的比特率。比特率是指每秒钟传输或处理的比特(bit)数量,是衡量音频质量和文件大小的一个重要指标。一般来说,比特率越高,音频文件的质量越好,因为它能够编码更多的音频数据,提供更丰富的音质细节。然而,更高的比特率也意味着更大的文件大小。

我们在音乐平台选择不同音质时,本质上就是在选择不同的码率:

音乐平台不同音质选择

为了节约存储空间,我一般都是选择「标准音质」,通常情况下,它是 128kbps。

但部分音频可能是早年用不明来源下载的,码率偏高。比如『MelodyInbox』虽然说有多种码率选择,但很多时候都指向同一个高码率的音频文件。

既然如此,我需要先从数千首歌中筛选出高码率音频,再去寻找低码率替代源。

之前做音源处理时就有读者问:如此繁琐的工作,为什么不交给 AI?

不得不承认,AI 时代确实已经到来,但很遗憾,有些场景下程序员的效率依然更高。

以我使用 Claude Code 搭配 MiniMax M2.7 HighSpeed 模型为例,让它列出所有大于 200kbps 的音频文件,等了 6 分钟仍无结果:

AI 筛选

无奈只能关掉 AI,转而手搓脚本:

#!/bin/bash

# 查找当前目录及子目录下所有码率大于 200kbps 的 MP3 文件
# 使用 ffprobe 获取码率,不修改任何文件

echo "正在扫描 MP3 文件..."

while IFS= read -r -d '' file; do
    bitrate=$(ffprobe -v error -show_entries format=bit_rate -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
    size=$(stat -f%z "$file" 2>/dev/null)
    if [ -n "$bitrate" ] && [ "$bitrate" -gt 200000 ]; then
        size_mb=$(awk "BEGIN {printf \"%.2f\", $size / 1024 / 1024}")
        echo "$file | 码率: $((bitrate / 1000)) kbps | 大小: ${size_mb} MB"
    fi
done < <(find . -name "*.mp3" -type f -print0)

echo "扫描完成。"

脚本比较简单,只运行了 2 分多钟就把我需要的结果筛选出来了。

脚本筛选

接下来就是去寻找低码率的替代源。如果实在找不到,可能会考虑对高码率音频进行二次压缩,但这并非最佳方案——音频本身就是从母带压缩而来,二次压缩会导致失真叠加,还是应该优先寻找原生低码率版本。