使用ffmpeg转换视频格式和复制标签

16

我一直在尝试将我拍摄的一些视频转换为压缩格式以节省存储空间。我已经找到了如何使用ffmpeg将视频转换为所需格式,但是我尚未能够弄清楚如何复制元数据。我想复制从拍摄视频时记录的原始元数据(最重要的是创建时间)。我尝试使用 -map_meta_data 0:0 选项运行 ffmpeg,但似乎没有起作用。有什么想法吗?

看起来,我想要复制的数据在视频的格式部分中。使用带有 show_format 选项的 ffprobe ,我得到以下输出:

[FORMAT]
filename=video.AVI
nb_streams=2
format_name=avi
format_long_name=AVI format
start_time=0.000000
duration=124.565421
size=237722700
bit_rate=15267331
TAG:creation_time=2012-02-07 12:15:27
TAG:encoder=CanonMVI06
[/FORMAT]

我想将这两个标签复制到我的新视频中。

3个回答

12

请查看有关转储和加载元数据的文档

FFmpeg可以将媒体文件的元数据转储到一个简单的UTF-8编码的INI类似文本文件中,然后使用元数据复用器/解复用器将其加载回来。

该过程可能如下所示:

# First extract metadata
ffmpeg -i original.mov -f ffmetadata metadata.txt
# Next, transcode, including extracted metadata
ffmpeg -i original.mov -f ffmetadata -i metadata.txt compressed.mp4

我现在没有元数据齐全的视频可供测试,但类似这样的应该可以工作。


看起来应该可以工作,但是当我提取元数据时,creation_time标签没有被提取。这就是保存到文件中的所有内容,这也可能解释为什么map_meta_data选项不起作用:;FFMETADATA1 encoder=CanonMVI06 - Scott
@Scott 的确可能会有用。虽然这样做非常不优雅,也不应该是必要的,但您可以尝试使用 ffprobe 和 grep 获取创建时间,然后使用 -metadata 直接将其设置到输出中。 - blahdiblah
2
这个方法还不太行,但是它指引了我正确的方向。当我运行ffmpeg命令时,我最终注意到输出了一条消息,说stfptime不可用(我一直在尝试在Windows上完成这个任务)。原来由于这个库在Windows上不可用,日期从未被放入元数据中。所以,我尝试在Linux中转换我的视频,因为stfptime在那里是可用的,map_metadata和ffmetadata选项都可以将creation_time标签保存到视频元数据中。 - Scott
1
最后一个命令不会起作用。因为你没有告诉FFmpeg应该选择哪个元数据。你需要使用“-map_metadata 1”来将第二个输入选择为元数据。 - Wang

11

使用"-map_metadata 0:g"来复制所有全局元数据。

0代表输入#0。g代表全局元数据。

这是我的ffprobe结果。享受吧!

input.mp4

[FORMAT]
filename=input.mp4
nb_streams=2
nb_programs=0
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
start_time=0.000000
duration=60.560500
size=190252680
bit_rate=25132246
probe_score=100
TAG:major_brand=mp42
TAG:minor_version=1
TAG:compatible_brands=mp42avc1
TAG:creation_time=2016-05-14 10:01:17
[/FORMAT]

输出.mp4

[FORMAT]
filename=output.mp4
nb_streams=2
nb_programs=0
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
start_time=0.000000
duration=60.632000
size=38636429
bit_rate=5097826
probe_score=100
TAG:major_brand=isom
TAG:minor_version=512
TAG:compatible_brands=isomiso2avc1mp41
TAG:creation_time=2016-05-14 01:01:17
TAG:encoder=Lavf57.36.100
[/FORMAT]

10

要将所有元数据(全局,视频,音频)写入文件,请使用

ffmpeg -i in.mp4 -c copy -map_metadata 0 -map_metadata:s:v 0:s:v -map_metadata:s:a 0:s:a -f ffmetadata in.txt

要添加文件中的所有元数据,请使用

ffmpeg -i in.mp4 -f ffmetadata -i in.txt -c copy -map_metadata 1 out.mp4

我正在尝试这个操作,它会重新编码整个文件,这是预期的吗?也许有一个开关只插入元数据吗?顺便说一下,我的目标是使用 ffmpegffprobe 读取视频信息(帧高度、宽度、速率等),并将其保存到视频文件元数据中。 - André Levy
不,不需要重新编码。-c copy 应该只是复制。 - Frank Breitling
我不确定它是否重新编码,但我看到的是它逐分钟爬行整个视频。这就是-c copy应该做的吗?顺便说一下,我发现我的问题不是文件缺少元数据,而是Windows在其文件系统中不会本地读取mkv文件的元数据,就像它对mp4文件所做的那样。Shark007编解码器解决了这个问题(可能还提供了其他问题的解决方案)。 - André Levy
根据我的测试,不正确。要导出所有全局数据(尤其是缺少creation_time):ffmpeg -i in.mp4 -f ffmetadata meta.txt。要导出所有全局数据:ffmpeg -i in.mp4 -map_metadata 0 -f ffmetadata meta.txt。注意:全局的encoder始终会更新。要导出所有元数据:ffmpeg -t 0 -i in.mp4 -c copy -map 0 -map_metadata 0 -f ffmetadata meta.txt。请注意添加了-map 0-t 0可以节省时间(如果所有数据都在前面)。像-map_metadata:s:v 0:s:v这样做只会通过将第一个视频流的数据映射到所有视频流来搞乱事情。 - juanitogan
1
@almcnicoll: 如果我能记得为什么一开始没有这样做的话,我可能会这样做。这可能与导出为txt文件时不总是需要该导出步骤有关。stegoma在2016年的回答看起来对于这个特定情况是正确的,假设他们运行了:ffmpeg -i in.mp4 -c copy -map_metadata 0:g out.mp4(默认的:g是可选的)。---- 无论如何,现在是一个好时机指出我上面关于:s:v的最后一句话写反了(它将所有数据映射到第一个,覆盖多个视频流的情况下的数据)。-t 0只是防止进行完整的-c copy扫描。 - juanitogan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接