如何让 Handbrake 保留捕获时间/创建时间?

如何让 Handbrake 保留捕获时间/创建时间?

Handbrake 是一款很棒的视频压缩工具,但它似乎在视频压缩后无法保留原始捕获时间。有没有什么办法可以解决这个问题?

答案1

您可以将现有元数据从一个文件复制到另一个文件,而无需使用以下方法重新编码视频FFmpeg。基本上只需要一秒钟。为此,我们假设有三个文件:

  • in.mp4– 转换前的原始文件
  • out.mp4– Handbrake 转换后的文件
  • fixed.mp4– 具有“更正”元数据的文件

将完整的元数据记录复制到新文件的 FFmpeg 命令将是:

ffmpeg -i in.mp4 -i out.mp4 -map 1 -map_metadata 0 -c copy fixed.mp4

语法解释:

具体来说,这将执行以下操作:

  • 取两个输入文件(in.mp4out.mp4),分别分配有 ID 0 和 1。
  • 仅将文件 1 中的视频/音频/字幕流映射到输出(-map 1),因此我们采用已转换的比特流
  • 仅将文件 0 中的元数据映射到输出 ( -map_metadata 0)
  • 使用复制编解码器(-c copy)复制所有比特流,而不是重新编码视频。

此后,您显然可以重命名fixed.mp4out.mp4


证明:

举个例子,这是我的原始文件的元数据记录的一部分:

$ mediainfo in.mp4 | grep "Encoded date" | head -n 1
Encoded date : UTC 2012-01-08 11:16:19

这是 Handbrake 转换后的文件:

$ mediainfo out.mp4 | grep "Encoded date" | head -n 1
Encoded date : UTC 2012-12-24 11:39:35

这是映射元数据后的最终文件:

$ ffmpeg -i in.mp4 -i out.mp4 -map 1 -map_metadata 0 -c copy fixed.mp4
[…]

$ mediainfo fixed.mp4 | grep "Encoded date" | head -n 1
Encoded date : UTC 2012-01-08 11:16:19    

如果您想使用 FFmpeg 完成所有操作:

实际上,如果您可以使用 FFmpeg,您实际上并不需要使用 Handbrake,因为 Handbrake 无论如何都依赖它。在最简单的情况下,您可以像这样进行转换:

ffmpeg -i in.mp4 -c:v libx264 -crf 23 -c:a aac -map_metadata 0 out.mp4

这会将带有 x264 编码器和 AAC 音频的输入转换为输出文件,并复制原始元数据。为了更改输出的质量,您可以:

  • 更改视频的 CRF 值。值越低表示质量越好。23 是默认值,低于 18 的任何值可能在视觉上无损。
  • 更改音频的比特率。请参阅AAC 编码指南了解更多信息。

阅读x264 编码指南更多详情请参阅 FFmpeg wiki。

答案2

不幸的是,handbrake 似乎无法自行完成此操作,但与 ffmpeg 示例类似,可以使用touchunix 命令在压缩后从原始文件复制时间戳:

touch -r MVI_1234.MOV compressed_MVI_1234.m4v

这会将压缩文件上的时间戳设置为与给定的参考文件相同。

答案3

如果你指的是文件级修改时间,那么我遇到了同样的问题,并且能够使用以下方法恢复它外置工具

exiftool -tagsFromFile input.mp4 -extractEmbedded -all:all -FileModifyDate -overwrite_original output.mp4

这将获取元数据并FileModifyDate从中input.mp4复制到output.mp4

由于我有大量文件需要转码,为了实现自动化,我创建了一个名为收缩包装首先转码为FFmpeg(由于需要保留更多元数据,我放弃了 HandBrake),然后使用 exiftool 恢复修改时间戳。

答案4

我制作了一个可以批量传输元数据的 bash 脚本,使用方法touch如上所述。要使其工作,您必须将原始文件和转换后的文件放在不同的目录中,每个目录的文件数量相同(目录必须只有视频文件,因为其他文件/目录会干扰)且顺序相同。然后它只需复制元数据,您就大功告成了。脚本列出了所有文件对,因此您可以在最后检查错误(如果您愿意)。

由于这是我的第一个正确的 bash 脚本,因此该代码可能不是最简洁的,但对我来说它非常快且稳定,因此如下所示:

#!/bin/bash
#Sets IFS to \n to allow for filenames with spaces
IFS=$'\n'

#Source directory and converted direcotry
dir1=$1
dir2=$2

#Array with source filepaths
srcf=()
#Array with converted filepaths
cnvf=()

#Adds filepaths from the source directory to srcf array
for file in $(ls -1 $dir1); do
    srcf+=("$dir1/$file")
done
#Adds filepaths from the converted directory to cnvf array
for file in $(ls -1 $dir2); do
    cnvf+=("$dir2/$file")
done

#Checks if source and convert folders have the same number of files
if [ ${#srcf[*]} -eq ${#cnvf[*]} ]
then
    #Counter variable
    fnum=0
    #Loops through the arrays and runs touch command on pairs of files to transfer the metadata
    while [ $fnum -lt ${#srcf[*]} ]; do
        echo $fnum
        echo ${srcf[$fnum]} ${cnvf[$fnum]}
        touch -r ${srcf[$fnum]} ${cnvf[$fnum]}
        ((fnum++))
    done
else
    echo "The provided paths do not have the same number of files. Both paths must have the same number of files in the same order."
fi

运行如下:sudo bash script.sh /sourcedir /converteddir

相关内容