# 音频合并与章节生成完整流程,简称写专辑💿 本文档提供使用 `ffmpeg` 将多个音频文件合并为一个带章节标记的完整文件的标准化操作流程,涵盖从准备文件列表到最终验证的所有步骤。 ## 准备工作 1. 确保系统已安装 `ffmpeg` 和 `ffprobe`。 2. 将所有待合并的音频文件(如 `.m4a`、`.mp3`)放入同一文件夹。 3. 确认合并顺序。 ## 操作流程 ### 第一步:创建文件列表 `list.txt` 在音频文件所在文件夹中创建 `list.txt`,按合并顺序写入文件名,格式为每行一个 `file '文件名'`: ```txt file 'song1.m4a' file 'song2.m4a' file 'song3.m4a' ``` >若文件名包含空格或特殊字符,必须用单引号括起来。 ### 第二步:合并为纯音频文件 执行以下命令,合并所有音频并去除可能存在的封面图像: ```bash ffmpeg -f concat -safe 0 -i list.txt -c copy -map 0:a -fflags +genpts -y merged_audio.m4a ``` 参数说明: -f concat -safe 0 -i list.txt:使用文件列表拼接模式。 -c copy:直接复制流,不重新编码(速度快,无损)。 -map 0:a:仅选择音频流,忽略图像流。 -fflags +genpts:强制生成时间戳,确保时间轴连续。 -y:自动覆盖已存在的输出文件。 ### 第三步:获取每个文件的时长 在同文件夹的终端执行以下命令,查看 list.txt 中每个文件的精确时长(秒): ```bash for f in $(cat list.txt | sed "s/^file '//" | sed "s/'$//"); do echo -n "$f: "; ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f"; done ``` 输出示例: ```text song1.m4a: 136.881633 song2.m4a: 96.084172 ``` ### 第四步:生成章节文件 chapters.txt 根据上一步获得的时长(秒),转换为毫秒(乘以1000),按顺序累加计算起止时间,生成 chapters.txt: ```txt ;FFMETADATA1 title=合并专辑名 [CHAPTER] TIMEBASE=1/1000 START=0 END=136882 title=song1 [CHAPTER] TIMEBASE=1/1000 START=136882 END=232966 title=song2 ``` 计算规则: 第一个文件:START=0,END=第一个文件时长(秒)×1000。 后续文件:START=上一个文件END,END=START+当前文件时长(秒)×1000。 title 字段为章节显示名称,通常使用文件名(不含扩展名)。 ### 第五步:将章节信息写入合并文件 ```bash ffmpeg -i merged_audio.m4a -i chapters.txt -map_metadata 1 -codec copy merged_audio_with_chapters.m4a ``` 参数说明: -i merged_audio.m4a:输入合并后的纯音频文件。 -i chapters.txt:输入章节元数据文件。 -map_metadata 1:将章节信息应用到输出文件。 -codec copy:直接复制流,避免重新编码。 ### 第六步:播放验证 用支持章节显示的播放器(如 VLC、mpv)打开 merged_audio_with_chapters.m4a,在播放菜单中查看“章节”列表,确认标题正确。 ### 常见问题排查 | 问题 | 解决方案 | |------|----------| | 合并后文件时长显示 `N/A` | 使用 `-fflags +genpts` 强制生成时间戳 | | 章节时间全部相同 | 检查 `chapters.txt` 中 `START`/`END` 是否按顺序递增,且 `TIMEBASE=1/1000` | | 文件包含封面图像 | 合并时使用 `-map 0:a` 只选择音频流 | | 文件名含空格导致报错 | 在 `list.txt` 中用单引号括起文件名,如 `file 'my song.m4a'` |