我有一个文件夹,其中包含名为0001.mp4
、0002.mp4
、 ...的文件
,我想将所有这些文件合并到combined.mp4
,并且我希望它有一个内部章节标记。例如在 vlc 中播放时很方便,因为您可以在时间轴中看到章节名称。
我怎样才能做出这样的combined.mp4
?最好使用命令行脚本ffmpeg
,并且没有其他依赖项。
有相似的问题,但提问者想要使用手刹。
答案1
章节信息存储在文件元数据中。 Ffmpeg 允许将元数据导出到文件,并从文件加载元数据。文档在这里:ffmpeg 元数据 1
现在我们需要准备一个元数据文件,用于合并.mp4。我们可以一次性完成此操作,无需首先从所有文件创建组合文件,然后创建另一个文件,但注入元数据。我们节省存储空间。
multiple_mp4_to_single_mp4_with_chapters.py
我编写了一个可以完成下列工作的Python 脚本:
import subprocess
import os
import re
def make_chapters_metadata(list_mp4: list):
print(f"Making metadata source file")
chapters = {}
for single_mp4 in list_mp4:
number = single_mp4.removesuffix(".mp4")
duration_in_microseconds = int((subprocess.run(f"ffprobe -v quiet -of csv=p=0 -show_entries format=duration {folder}/{single_mp4}", shell=True, capture_output=True).stdout.decode().strip().replace(".", "")))
chapters[number] = {"duration": duration_in_microseconds}
chapters["0001"]["start"] = 0
for n in range(1, len(chapters)):
chapter = f"{n:04d}"
next_chapter = f"{n + 1:04d}"
chapters[chapter]["end"] = chapters[chapter]["start"] + chapters[chapter]["duration"]
chapters[next_chapter]["start"] = chapters[chapter]["end"] + 1
last_chapter = f"{len(chapters):04d}"
chapters[last_chapter]["end"] = chapters[last_chapter]["start"] + chapters[last_chapter]["duration"]
metadatafile = f"{folder}/combined.metadata.txt"
with open(metadatafile, "w+") as m:
m.writelines(";FFMETADATA1\n")
for chapter in chapters:
ch_meta = """
[CHAPTER]
TIMEBASE=1/1000000
START={}
END={}
title={}
""".format(chapters[chapter]["start"], chapters[chapter]["end"], chapter)
m.writelines(ch_meta)
def concatenate_all_to_one_with_chapters():
print(f"Concatenating list of mp4 to combined.mp4")
metadatafile = f"{folder}/combined.metadata.txt"
os.system(f"ffmpeg -hide_banner -loglevel error -y -f concat -i list_mp4.txt -i {metadatafile} -map_metadata 1 combined.mp4")
if __name__ == '__main__':
folder = "." # Specify folder where the files 0001.mp4... are
list_mp4 = [f for f in os.listdir(folder) if re.match(r'[0-9]{4}\.mp4', f)]
list_mp4.sort()
# Make the list of mp4 in ffmpeg format
if os.path.isfile("list_mp4.txt"):
os.remove("list_mp4.txt")
for filename_mp4 in list_mp4:
with open("list_mp4.txt", "a") as f:
line = f"file '{filename_mp4}'\n"
f.write(line)
make_chapters_metadata(list_mp4)
concatenate_all_to_one_with_chapters()
现在您可以将其放入 mp4 文件所在的文件夹中(或编辑folder
脚本中的变量),然后运行它:
$ ls
0001.mp4 0002.mp4 0003.mp4 0004.mp4 multiple_mp4_to_single_mp4_with_chapters.py
$ python multiple_mp4_to_single_mp4_with_chapters.py
现在您将拥有combined.mp4
,当它在 vlc 中打开时,您将看到章节标记。
我在 bash 上看到一个使用 mp4box 和 mp4chaps 执行此操作的脚本:这个要点
还有一个没有此类依赖项的 bash 版本:这个要点
还有 python 上的另一个版本,但它创建合并文件两次:这个要点