首先,为什么要切成小文件:如果你像我一样将音乐储存在文件服务器上,通过映射驱动器然后在本地播放。那么切分对于文件服务器具有极大的优势,文件服务器可以有效地缓存小文件。例如使用ZFS作为储存后端,启用ARC+L2ARC后可以最大限度地利用缓存,从而获得更短的响应时间,同时也减少机械磁盘的读写。

也许大家知道ARC和L2ARC都是块级的缓存机制,切不切开来好像也没太大所谓。但大家也应该知道并不是所有协议都支持随机读取的,比如基于WebDAV的网络共享在处理大型文件上就比较尴尬了。

快速上手

首先,介绍一下我写的一个Python小工具cuecut,用pip安装后直接就可以在命令行中使用cuecut命令根据cue文件切分对应的音频文件了。
PyPI链接–>https://pypi.org/project/cuecut/
Github链接–>https://github.com/jsjyhzy/cuecut

要是对原理不是很感兴趣的话,那么把FFmpeg的可执行文件复制到PATH中的任一目录,假设cue文件的位置是/a/b.cue,希望切分出来的音频文件是flac格式,那么打开命令行,输入如下命令

cuecut /a/b.cue -c flac

就可以了。音频文件将会自动根据cue文件中的演奏者,单曲名称命名为`演奏者 – 单曲名`。当然目前还不支持配置自动命名的样式,也许以后会有吧。

原理与方法论

技术上还是在使用ffmpeg的命令行,因此难点还是主要集中在ffmpeg的命令行参数的选取上。首先一些无关痛痒的参数,诸如是否显示banner(--hide_banner)、输入文件是什么(-i FILE)、输出编码是什么(-c:a codec)、日志级别(-loglevel levelname)、元数据(-metadata xxx=yyy)就不再展开讨论了。接下来主要讨论一些比较重要的参数:

移除原有的元数据

对于有一些音频镜像文件,原作者会将cue文件作为元数据写入音频文件中,如果不移除这些元数据,可能会导致播放音频文件时出现分章。因此需要用参数 -map_metadata -1 来移除这些元数据。

切取位置

既然是切分出音轨,那么就要确定切分位置,音轨的开始位置(或者说偏移量)用 -ss where 参数描述,其中where是一个浮点数(建议只取小数点后两位),结束位置则用 -to where 参数描述。

元数据写入

既然要写入一些诸如演奏者、音轨名或者专辑名称的元数据,那么就要让FFmpeg写入ID3数据块,这一点可以用 -write_id3v1 1 参数来指定。

移除视频流

部分音频镜像会把专辑封面作为一个视频流插入文件中,在切分这样的文件时,往往第一个音轨是能够正常获得这个视频流的。然而后续的音轨都将无法获得,同时由于这个问题,还进一步导致后续音轨丢失长度信息(duration),会使部分播放器无法seek到某一具体位置。目前没有什么特别好的方法让所有音轨都正确地获取视频流,因此较为实际的方案就是扔掉所有视频流,用参数 -vn 来完成。

平台依赖的非法文件名

这个问题是可以通过修改输出文件名的模式来规避的,主要是我的cuecut中的文件名模式中存在演奏者和单曲名,因此对于一些奇怪的名字还是要加以处理的,例如名字中不能出现 \/:*?<>| 这些字符。此外在Windows平台上AUX,CON,COM[1-9],NUL,LPT[1-9],PRN都是保留名称,即使带扩展名也不能创建这类文件。

加入对话

1条评论

留下评论