当我尝试删除字幕时,FFmpeg 不会复制章节元素

当我尝试删除字幕时,FFmpeg 不会复制章节元素

我有一些用 The Criterion Collection 编码的视频,他们的视频使用这些称为“章节原子”的东西。真正奇怪的是它ffprobe没有检测到这些。我假设章节原子是 H.264/H.265/MP4/MOV 的东西,但 Matroska 视频容器可能有自己的章节元数据,对吧?不确定...

例如,当我使用时ffprobe -show_chapters <video file>,它只会给我一个章节,如下所示:

[CHAPTER]
id=0
time_base=1/1000000000
start=7235652000000
start_time=7235.652000
end=7235652000000
end_time=7235.652000
TAG:title=XXXXXX
[/CHAPTER]

但是当我用 MKVToolNix GUI 打开它并使用他们的“信息工具”时,我在最底部看到一个可折叠的菜单项,上面写着“章节”,我将其展开为“版本条目”,它有“版本标志隐藏”、“版本标志默认”、“版本 UID”等内容,最后还有多个“章节原子”。这些都是 ffmpeg/ffprobe 无法通过正常方式检测到的东西。

ffmpeg好了,现在来谈谈我要解决的问题。我用来保存的带有命令行的脚本全部数据(除字幕外)如下:

#!/bin/sh

if [ $# -eq 0 ]; then
    >&2 echo "Error: No filename(s) specified."
    exit 1
fi

# TODO: Sometimes it does not copy over chapter info
for f in "$@"; do
    ffmpeg -i "$f" -threads 4 \
    -c:v copy -c:a copy -sn \
    -map 0 -map_metadata 0 -map_chapters 0 \
    -movflags use_metadata_tags \
    "${f%.*}-subs-removed.${f##*.}"
done

我这样做的原因主要是因为强迫症。我一直希望我的字幕是分开的。原因有很多。有时字幕中会有错误或失误,我想修复这些错误或失误,格式不精确的问题,OCR 转换错误,删除字幕中烦人的第三方网站版权/水印,调整字幕时间、同步和持续时间,让人们更容易在重新分发时翻译成其他语言,从一种字幕格式转换为另一种字幕格式,等等……

我觉得我已经尽我所能尝试将一个视频文件中的所有数据(包括元数据)保留到另一个视频文件中。但 FFmpeg 似乎还不足以胜任这项工作确切地我希望它做什么,因为它总是缺少文件中一些自定义标签和元数据,否则这些标签和元数据应该被复制过去。

那么 ffmpeg 是不是不适合这个工作的工具?看起来mkvextractfrommkvtoolnix能够检测并提取这些章节原子,但ffmpeg实际上却不能。这是为什么呢?

也许有办法将章节单元转换成常规的 Matroska 视频章节?不过,我希望有更自动化的方法,因为我有几个 shell 脚本ffmpeg-subs-remove.sh,并且ffmpeg-subs-extract.sh,删除字幕的那个是我上面发布的代码片段,如果能让它再次正常工作就太好了。

答案1

这实际上并不是 FFMpeg 的解决方案,但它可以与 MKVToolNix 一起工作。

#!/bin/sh

if [ $# -eq 0 ]; then
    >&2 echo "Error: No filename(s) specified."
    exit 1
fi

for f in "$@"; do
    destfile="${f%.*}-subs-removed.${f##*.}"
    ffmpeg -i "$f" -threads 4 \
    -c:v copy -c:a copy -sn \
    -map 0 -map_metadata 0 -map_chapters 0 \
    -movflags use_metadata_tags+faststart \
    "$destfile"

    # We need to do more post-processing with mkvtoolnix because ffmpeg
    # is not an advanced enough tool yet to copy over all MKV container data
    if mkvinfo "$f" > /dev/null 2>&1; then
        tagsfile="/tmp/mkv-tags.xml"
        chaptersfile="/tmp/mkv-chapters.xml"
        echo "Notice: Matroska container format detected. Copying over extra data."
        mkvextract -f "$f" tags "$tagsfile"
        mkvextract -f "$f" chapters "$chaptersfile"
        if [ -r "$tagsfile" ]; then
            mkvpropedit "$destfile" --tags all:"$tagsfile"
            rm -f "$tagsfile"
        fi
        if [ -r "$chaptersfile" ]; then
            mkvpropedit "$destfile" --chapters "$chaptersfile"
            rm -f "$chaptersfile"
        fi
    fi
done

我还没有用多个文件测试过,可能还有其他测试用例我遗漏了。虽然不完美,但目前对我来说还算可以。

相关内容