如何在不创建新文件的情况下使用ffmpeg/avconv更改元数据?

Ste*_*lla 19 python command-line metadata ffmpeg

我正在编写一个用于制作音频和视频播客的python脚本.有一堆录制的媒体文件(音频和视频)和包含元信息的文本文件.

现在我想编写一个函数,它将元数据文本文件中的信息添加到所有媒体文件(原始文件和转换文件).因为我要处理很多不同的文件格式(wav,flac,mp3,mp4,ogg,ogv...),这将是巨大的,有一个工具,它的元数据添加到任意格式.

我的问题:

如何在ffmpeg/avconv不更改文件的音频或视频且不创建新文件的情况下更改文件的元数据?是否有另一个命令行/ python工具可以帮我完成这项工作?

到目前为止我尝试了什么:

我认为ffmpeg/avconv可以成为一种工具,因为它可以处理几乎所有的媒体格式.我希望,如果我设置-i input_fileoutput_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
Run Code Online (Sandbox Code Playgroud)

你看,我不能使用-c copyif input_fileoutput_file是一样的.当然我可以生成一个临时文件:

:-$ avconv -i test.wav -c copy -metadata title='Test title' test_temp.mp3
:-$ mv test_tmp.mp3 test.mp3
Run Code Online (Sandbox Code Playgroud)

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

bla*_*lah 28

您可以使用FFmpeg执行此操作,如下所示:

ffmpeg -i input.avi -metadata key=value -codec copy output.avi
Run Code Online (Sandbox Code Playgroud)

例:

$ 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
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅有关流复制文档-metadata.

另请注意,并非所有格式都允许设置任意元数据,例如,Quicktime正在-metadata title="my title"执行您期望的操作,但-metadata foo=bux不执行任何操作.

  • 在解决方案中,您将创建一个新文件.还有一种方法没有创建新文件? (4认同)
  • 为了澄清一点,`ffmpeg` 需要创建一个输出文件。您有一个输入文件,而 `ffmpeg` 不允许直接操作输入文件。我相信这种做法是由于多媒体文件有多大,因为动态更改输入文件需要缓存整个文件。与后一个概念相关,请注意 `ffmpeg` 不会对输入文件执行任何完整性检查。 (3认同)

Ste*_*lla 14

我在avconv邮件列表中询问并得到以下答案:

"不,[不能在不创建新文件的情况下更改元数据],libavformat API和avconv设计都不允许对文件进行就地编辑."

  • MP3文件中的(原始)ID3元数据格式是文件末尾的固定大小的数据结构。这使得就地编辑变得微不足道。另一方面,较新的ID3v2是文件开头的可变长度结构(以支持流传输),因此通常不能就地编辑。 (5认同)
  • @NikosBaxevanis 最有可能的方法是输出到临时文件,删除原始文件,然后重命名新文件。在读取文件时覆盖文件可能会导致许多问题。例如,如果您执行“ffmpeg -i video.mkv -c:a copy -c:v copy video.mkv”,ffmpeg将破坏您的视频文件 (2认同)

miv*_*ivk 6

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

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

  • exiftool适用于多种格式
  • metaflac对于 FLAC
  • MP4Box对于.mp4
  • eyeD3MP3 的、mid3v2
  • ETC。

因此,您确实必须检查每种特定文件格式是否适合您。


Jer*_*emy 6

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

ffmpeg -i default.mp4 -metadata title="my title" -codec copy output.mp4 && mv output.mp4 default.mp4
Run Code Online (Sandbox Code Playgroud)


Coo*_*lin 5

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

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

还。如果用空值填充,您可能可以直接将较短的数据放在适当的位置,但这对于某些玩家来说可能会出现问题。

  • 您提到的旧/新文件版本之间的不一致是为什么如果文件的艺术作品标签已被编辑,VLC 等程序经常会报告音乐文件中不正确的曲目长度,尽管内容会正确播放。 (2认同)