32

我正在编写一个用于制作音频和视频播客的 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 copyifinput_fileoutput_fileare the same。当然我可以生成一个临时文件:

:-$ avconv -i test.wav -c copy -metadata title='Test title' test_temp.mp3
:-$ mv test_tmp.mp3 test.mp3

但是这个解决方案会(临时)在文件系统上创建一个新文件,因此不是可取的。

4

7 回答 7

49

您可以使用 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什么也不做。

于 2012-07-13T22:15:07.580 回答
24
于 2012-07-15T13:50:58.837 回答
6

你也可以做这样的事情,在成功时删除文件并重命名输出

ffmpeg -i default.mp4 -metadata title="my title" -codec copy output.mp4 && mv output.mp4 default.mp4
于 2020-08-21T14:35:10.673 回答
2

由于更改元数据会改变文件的长度,并且我希望元数据接近文件的开头,因此音频和视频将从文件开头的不同偏移量开始。因此,如果不先创建临时文件,然后重命名文件,就无法更改元数据。

如果新元数据的大小完全相同并且您知道元数据在容器(文件)中的位置,则可以使用某种十六进制编辑器来简单地替换字符。祝你好运。

还。如果你用空值填充,你也许可以直接放置较短的数据,但这对某些玩家来说可能是个问题。

于 2018-04-08T22:19:53.627 回答
2

使用ffmpeg,您将始终必须复制到新文件。但它的优点是可以处理许多不同的格式。

不复制整个文件的替代方法取决于格式。对于许多人来说,有一些工具可以让您“就地”编辑元数据。

  • exiftool适用于多种格式
  • metaflac对于 FLAC
  • MP4Box对于.mp4
  • eyeD3, mid3v2, 等用于 MP3
  • 等等

因此,您确实必须检查每种特定文件格式对您有用的内容。

于 2020-07-26T17:20:08.093 回答
0

这取决于文件中元数据的物理位置。如果数据位于文件的开头,您可以“切分”该部分并编辑数据,然后将这些部分“拼接”在一起。仅当您有很多文件要批量处理时,这才有用。如果只编辑一个,请使用两份复制方法之一。

于 2022-01-22T04:31:42.577 回答
-1

如果像我一样,您有很多长名称(和空格)的文件要重命名,您可以在之前将文件名和标题保存为变量,然后始终执行相同的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,则可以通过添加标志来防止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"
于 2020-12-20T18:22:22.247 回答