How to change metadata with ffmpeg/avconv without creating a new file?

Stephan Kulla picture Stephan Kulla · Jul 13, 2012 · Viewed 51.4k times · Source

I am writing a python script for producing audio and video podcasts. There are a bunch of recorded media files (audio and video) and text files containing the meta information.

Now I want to program a function which shall add the information from the meta data text files to all media files (the original and the converted ones). Because I have to handle many different file formats (wav, flac, mp3, mp4, ogg, ogv...) it would be great to have a tool which add meta data to arbitrary formats.

My Question:

How can I change the metadata of a file with ffmpeg/avconv without changing the audio or video of it and without creating a new file? Is there another commandline/python tool which would do the job for me?

What I tried so far:

I thought ffmpeg/avconv could be such a tool, because it can handle nearly all media formats. I hoped, that if I set -i input_file and the output_file to the same file, ffmpeg/avconv will be smart enough to leave the file unchanged. Then I could set -metadata key=value and just the metadata will be changed.

But I noticed, that if I type avconv -i test.mp3 -metadata title='Test title' test.mp3 the audio test.mp3 will be reconverted in another bitrate.

So I thought to use -c copy to copy all video and audio information. Unfortunately also this does not work:

:~$ 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

You see, that I cannot use -c copy if input_file and output_file are the same. Of course I could produce a temporarily file:

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

But this solution would create (temporarily) a new file on the filesystem and is therefore not preferable.

Answer

blahdiblah picture blahdiblah · Jul 14, 2012

You can do this with FFmpeg like so:

ffmpeg -i input.avi -metadata key=value -codec copy output.avi

Example:

$ 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

See the documentation for -metadata and on stream copying for more information.

Note also that not all formats allow setting arbitrary metadata, for, e.g., Quicktime doing -metadata title="my title" does what you'd expect, but -metadata foo=bux does nothing.