我正在编写一个用于制作音频和视频播客的Python脚本。有一堆录制的媒体文件(音频和视频)和包含元信息的文本文件。
现在我想编写一个函数,将元数据文本文件中的信息添加到所有媒体文件(原始文件和转换后的文件)中。因为我必须处理许多不同的文件格式(
wav
,flac
,mp3
,mp4
,ogg
,ogv
...),如果有一个工具可以将元数据添加到任意格式。
我的问题:
如何使用
ffmpeg/avconv
更改文件的元数据,而不更改文件的音频或视频,也不创建新文件?是否有另一个命令行/Python 工具可以为我完成这项工作?
到目前为止我尝试过的:
我认为
ffmpeg/avconv
可能是这样一个工具,因为它可以处理几乎所有媒体格式。我希望,如果我将 -i input_file
和 output_file
设置为同一个文件,ffmpeg/avconv
将足够聪明,使文件保持不变。然后我可以设置 -metadata key=value
并且只更改元数据。
但我注意到,如果我输入
avconv -i test.mp3 -metadata title='Test title' test.mp3
,音频 test.mp3
将以另一种比特率重新转换。
所以我想到用
-c copy
来复制所有视频和音频信息。不幸的是,这也不起作用:
:~$ du -h test.wav # test.wav is 303 MB big
303M test.wav
:~$ avconv -i test.wav -c copy -metadata title='Test title' test.wav
avconv version 0.8.3-4:0.8.3-0ubuntu0.12.04.1, Copyright (c) 2000-2012 the
Libav developers
built on Jun 12 2012 16:37:58 with gcc 4.6.3
[wav @ 0x846b260] max_analyze_duration reached
Input #0, wav, from 'test.wav':
Duration: 00:29:58.74, bitrate: 1411 kb/s
Stream #0.0: Audio: pcm_s16le, 44100 Hz, 2 channels, s16, 1411 kb/s
File 'test.wav' already exists. Overwrite ? [y/N] y
Output #0, wav, to 'test.wav':
Metadata:
title : Test title
encoder : Lavf53.21.0
Stream #0.0: Audio: pcm_s16le, 44100 Hz, 2 channels, 1411 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press ctrl-c to stop encoding
size= 896kB time=5.20 bitrate=1411.3kbits/s
video:0kB audio:896kB global headers:0kB muxing overhead 0.005014%
:~$ du -h test.wav # file size of test.wav changed dramatically
900K test.wav
你看,如果
-c copy
和 input_file
相同,我就不能使用 output_file
。当然我可以制作一个临时文件:
:-$ avconv -i test.wav -c copy -metadata title='Test title' test_temp.mp3
:-$ mv test_tmp.mp3 test.mp3
但是此解决方案会在文件系统上(暂时)创建一个新文件,因此并不可取。
您可以使用 FFmpeg 执行此操作,如下所示:
ffmpeg -i input.avi -metadata key=value -codec copy output.avi
示例:
$ du -h test.mov
27M test.mov
$ ffprobe -loglevel quiet -show_format out.mov | grep title # nothing found
$ ffmpeg -loglevel quiet -i test.mov -codec copy -metadata title="My title" out.mov
$ du -h out.mov
27M out.mov
$ ffprobe -loglevel quiet -show_format out.mov | grep title
TAG:title=My title
请参阅 文档了解
-metadata
和流复制以了解更多信息。
另请注意,并非所有格式都允许设置任意元数据,例如,Quicktime 执行
-metadata title="my title"
会执行您所期望的操作,但 -metadata foo=bux
不会执行任何操作。
我在avconv的邮件列表上询问并得到以下答案:
“不,不可能[在不创建新文件的情况下更改元数据],libavformat API 和 avconv 设计都不允许就地编辑文件。”
您还可以进行类似的操作,在成功时删除文件并重命名输出
ffmpeg -i default.mp4 -metadata title="my title" -codec copy output.mp4 && mv output.mp4 default.mp4
由于更改元数据会更改文件的长度,并且我预计元数据位于文件开头附近,因此音频和视频将从与文件开头不同的偏移量开始。因此,如果不先创建临时文件,然后重命名文件,就无法更改元数据。
如果新元数据完全相同大小,并且您知道元数据位于容器(文件)中的位置,您可能能够使用某种十六进制编辑器来简单地替换字符。祝你好运。
还有。如果用空值填充,您可能可以直接将较短的数据放在适当的位置,但这对于某些玩家来说可能会出现问题。
使用
ffmpeg
,您将始终需要复制到新文件。但它的优点是可以处理许多不同的格式。
另一种方法(不复制整个文件)取决于格式。对于许多人来说,有一些工具可以让您“就地”编辑元数据。
exiftool
适用于多种格式metaflac
适用于 FLACMP4Box
.mp4eyeD3
、mid3v2
等因此,您确实必须检查每种特定文件格式是否适合您。
这取决于文件中元数据的物理位置。如果数据位于文件的头部,您可以“切片”该部分并编辑数据,然后将这些部分“拼接”回一起。仅当您要批量处理大量文件时,这才有用。如果只编辑一份,请使用两份复制方法之一。
很抱歉重提此对话,但显然没有确凿的答案......
我正在寻找类似的东西,我需要更改 MP4 视频文件的元数据,以便它们在播放器中正确显示,但我想在不生成新文件的情况下执行此操作,只需编辑原始文件的元数据.
原因
定期重新写入整个文件会给我的存储驱动器的使用寿命带来太大压力。
如果像我一样,您有很多名称很长(和空格)的文件需要重命名,您可以在之前将文件名和标题保存为变量,并在之后始终执行相同的
ffmpeg
命令:
input="My default video.mp4" && title="My title video"
ffmpeg -i "$input" -metadata title="$title" -codec copy output.mp4 && mv output.mp4 "$input"
如果您通过添加
ffmpeg
标志出现 < v.3.2, you can prevent Codec for stream 0 does not use global headers but container format requires global headers
-flags +global_header
警告:
ffmpeg -i "$input" -metadata title="$title" -codec copy -flags +global_header output.mp4 && mv output.mp4 "$input"
注意:我还必须更改权限才能检索与以前相同的文件(可能需要
sudo
):
chmod 774 "$input" && chown admin:users "$input"