36

When I am simply copying a.MOV (from my iPhone) to c.MOV, FFmpeg drops a lot of metadata, including the time and location of the video.

I tried -metadata, but FFmpeg still drops the information. It seems that the metadata is not dropped when FFmpeg prints Output #0, but is dropped when I use ffprobe to see metadata of the output file.

What should I do to make FFmpeg preserve these metadata?

$ ffmpeg -i a.MOV -c copy c.MOV -y
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'a.MOV':
  Metadata:
    major_brand     : qt  
    minor_version   : 0
    compatible_brands: qt  
    creation_time   : 2018-03-...
    com.apple.quicktime.location.ISO6709: .../
    com.apple.quicktime.make: Apple
    com.apple.quicktime.model: iPhone ...
    com.apple.quicktime.software: 11....
    com.apple.quicktime.creationdate: 2018-03-...
  Duration: 00:00:01.77, start: 0.000000, bitrate: 7868 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720, 7707 kb/s, 30 fps, 30 tbr, 600 tbn, 1200 tbc (default)
    Metadata:
      creation_time   : 2018-03-...
      handler_name    : Core Media Data Handler
      encoder         : H.264
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 87 kb/s (default)
    Metadata:
      creation_time   : 2018-03-...
      handler_name    : Core Media Data Handler
    Stream #0:2(und): Data: none (mebx / 0x7862656D), 0 kb/s (default)
    Metadata:
      creation_time   : 2018-03-...
      handler_name    : Core Media Data Handler
    Stream #0:3(und): Data: none (mebx / 0x7862656D), 0 kb/s (default)
    Metadata:
      creation_time   : 2018-03-...
      handler_name    : Core Media Data Handler
Output #0, mov, to 'c.MOV':
  Metadata:
    major_brand     : qt  
    minor_version   : 0
    compatible_brands: qt  
    com.apple.quicktime.creationdate: 2018-03-...
    com.apple.quicktime.location.ISO6709: .../
    com.apple.quicktime.make: Apple
    com.apple.quicktime.model: iPhone ...
    com.apple.quicktime.software: 11....
    encoder         : Lavf57.71.100
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720, q=2-31, 7707 kb/s, 30 fps, 30 tbr, 19200 tbn, 600 tbc (default)
    Metadata:
      creation_time   : 2018-03-...
      handler_name    : Core Media Data Handler
      encoder         : H.264
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 87 kb/s (default)
    Metadata:
      creation_time   : 2018-03-...
      handler_name    : Core Media Data Handler
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame=   23 fps=0.0 q=-1.0 Lsize=     732kB time=00:00:01.76 bitrate=7827.5kbits/s speed= 971x    
video:921kB audio:9kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.291216%
$ ffprobe c.MOV
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'c.MOV':
  Metadata:
    major_brand     : qt  
    minor_version   : 512
    compatible_brands: qt  
    encoder         : Lavf57.71.100
  Duration: 00:00:00.77, start: 0.000000, bitrate: 7819 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720, 7707 kb/s, 30 fps, 30 tbr, 19200 tbn, 38400 tbc (default)
    Metadata:
      handler_name    : DataHandler
      encoder         : H.264
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 92 kb/s (default)
    Metadata:
      handler_name    : DataHandler
$ 
1
  • 1
    I have the same problem; the above doesn't work. I am using ffmpeg version ffmpeg version 3.4.4-1~16.04.york0 Copyright (c) 2000-2018 the FFmpeg developers and this ffmpeg -i a.MOV -map_metadata 0 -c copy c.MOV still causes this to be dropped:- Writing library : Apple QuickTime com.apple.quicktime.make : Apple com.apple.quicktime.model : iPhone 5s com.apple.quicktime.software : 10.3.3 com.apple.quicktime.creationdate : 2018-06-06T01:15:37+0800 and to be replaced with:- Writing application : Lavf57.83.100
    – Mark
    Nov 10, 2018 at 4:14

6 Answers 6

38

Other answers here only work with the "known" meta keys, but for custom/arbitrary meta keys, -map_metadata 0 is not sufficient to keep them all.

In my transcoder project, a lot of camera makers like to inject custom meta keys in the MP4/MOV container, and I want to keep them in the transcoded MP4/MOV files. After a lot of head scratching, FFmpeg does seem to have a switch for this purpose:

-movflags use_metadata_tags

Note that this has to go after the input file, as for example in:

ffmpeg -i $input_file -movflags use_metadata_tags -crf 22 $output_file

Credit goes to the author of this thread and Google:

https://superuser.com/questions/1208273/add-new-and-non-defined-metadata-to-a-mp4-file

2
  • 1
    Nice tip - thanks. One thing I noticed when I converted a bunch of mov files I had recorded on iphones the Rotation tag in the exif data said 180. ffmpeg by default auto rotates the video - but if you also copy the mov tags to the mp4, then it still tells the player to rotate 180 even though ffmpeg auto rotated the mp4 during the conversion. So my videos ended up being upside down when I played them :) - The workaround in my case was to tell ffmpeg to not auto rotate using -noautorotate - a quick workaround is to use Exiftool and set the rotation to 0 - exiftool -Rotation=0 file.mp4
    – joensson
    Apr 11, 2020 at 9:41
  • 2
    Wow, credits indeed. ffmpeg -h full documents use_metadata_tags as "Use mdta atom for metadata", not the least obfuscated way of saying "just preserve my metadata"!
    – RJVB
    Oct 7, 2021 at 10:55
13

The -metadata option is for manipulating the metadata. If you just want to copy the metadata from an input file to an output file, you should use the -map_metadata option:

ffmpeg -i a.MOV -map_metadata 0 -c copy c.MOV

The file specifier is a zero-indexed number, so '0' takes the metadata from the first input file.

Note that -map_metadata and -movflags can be used in conjunction to preserve more metadata:

ffmpeg -i in.mp4 -crf 27 -movflags use_metadata_tags -map_metadata 0 out.mp4
4
  • Any idea how to make this work with concat? eg. ffmpeg -nostdin -f concat -safe 1 -i "${concatlist}" -map_metadata 0 -c copy "$outfile" where $concatlist is /tmp/concat.list which has lines like file 'filenamehere.mp3'
    – user25277
    May 22, 2019 at 10:34
  • 1
    ok, got it: ffmpeg -nostdin -i "${infile}" -f ffmetadata "${metadatafile}" then ffmpeg -nostdin -f concat -safe 1 -i "${concatlist}" -i "${metadatafile}" -map_metadata 1 -c copy "$outfile"
    – user25277
    May 22, 2019 at 10:48
  • -map_metadata 0 or -map_metadata 1?
    – evandrix
    Jun 17, 2019 at 9:02
  • 1
    @evandrix As stated in the answer, 0 selects the first input file as the source. For details, see this section of the ffmpeg docs. Jun 17, 2019 at 19:28
7

FFmpeg, by default, makes all metadata from the first input file available, to the output file muxer, for writing. -map_metadata allows to override that, by either pointing to a different input, or by telling ffmpeg to discard input global metadata (value of -1).

However, which of the available metadata, is actually written to the output file, depends on the output muxer. The QT/ISOBMFF muxer (for MOV/MP4/3GP..) only considers a limited number of tags, primarily iTunes-related. As @JerryTian noted, with -movflags use_metadata_tags, all other tags are written to the file. However, these are written in an unconventional manner - Quicktime, in particular, does not recognize these additional metadata entries. Other, ffmpeg-based s/w, should read them. Or anyone who's using custom s/w, like @JerryTian, can adapt their s/w to read them.

Note that movflags only applies to output from the QT muxer. Matroska (MKV) will write anything. Other muxers vary.

2
  • I\m trying to keep metadata when converting music. I have a custom CATALOGID, but when converting from wav to flac. The field is not preserved. ffmpeg -i bb.wav bb2.flac -movflags use_metadata_tags. Any idea ?
    – Léo Coco
    Mar 30, 2019 at 12:09
  • 1
    So if I understand you correctly, you're saying that using FFmpeg to encode into an .mkv should preserve all metadata from the source by default, without needing to speciify any additional options? Apr 28, 2019 at 17:47
5

I haven't found a way to have ffmpeg preserve the data. But I've found that for my needs I wanted the exif metadata and the exiftool was a convenient solution.

You can copy metadata between video files: https://unix.stackexchange.com/a/492338/83370

There's a trick to copy all metadata using the option -all:all>all:all: http://u88.n24.queensu.ca/exiftool/forum/index.php?topic=3440.0

exiftool -TagsFromFile a.MOV "-all:all>all:all" c.MOV
3
  • I tried all above on files from Canon 200D and this one is actually most useful. It still makes further exiftool c.MOV much smaller than the output from the original, but it preserves actual creation date (-map_metadata did it too, but not -movflags) and camera name, but lens information is still gone.
    – virgo47
    Oct 24, 2020 at 13:36
  • 1
    OK, this was actually a great starting point - all I had to do is skip that mapping part. Just using exiftool -TagsFromFile in.mp4 out.mp4 did the job!
    – virgo47
    Oct 24, 2020 at 14:16
  • @virgo47 what should -TagsFromFile look like?
    – CamHart
    Jan 14 at 0:08
1

From the comment in the answer https://superuser.com/questions/523286/how-to-make-handbrake-preserve-capture-time-creation-time/523696#comment2528176_523696

A full command line adding the option to copy special tags will be:

ffmpeg -i in.mp4 -i out.mp4 -map 1 -map_metadata 0 -c copy -movflags use_metadata_tags fixed.mp4

0

Looking at the ffmpeg source

Which metadata is written is hard-coded. There isn't a normal way to write all metadata --- for mov, mp4, etc. Whereas I can see that a mkv file gets all its metadata.

I can't say why they have it work that way. For other encoders, it could be different.

Now I found the use_metadata_tags option to be a bad idea since it is not standard - for example Plex does not read any of the metadata anymore. Funny that I was trying to get more metadata into Plex, but this option actually did the opposite. In the code above I can see that the MDTA way is to write all keys, then all values, whereas I guess most programs expect key/value pairs in a list, and therefore just don't know how to read MDTA metadata.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.