HOWTO: Preserve photo & video media metadata after transcoding

Mac OS Bash shell

Have you ever been asked, “is metadata really that important?” No, you haven’t? Well, of course not —nearly all photographers, videographers, digital asset managers, and media librarians understand that media metadata is crucial to organizing files. Can you imagine curating years of digital imagery by using some strange app to copy them all to a folder, which then proceeds to reset their creation date? OH, THE HORROR.

No one would ever seriously use such a disastrous DAM system but you’d be surprised how many mundane consumer tasks are capable of ruining your photos and videos. Simply changing the container type of your old .AVI videos can inadvertently mess things up when you finally decide to archive them. Using something like Samsung’s Kies app to transfer photos/video off a phone or camera could destroy metadata (I kid you not, it really does).

Why bad data is bad

How could incorrect date/times affect your photo/video workflow? Try importing those modified files into something like iPhoto or even flickr.com. For example, with EXIF/IPTC tags changed, the timestamps on all your historical DSC2491.JPG from June 2006, 10:52 a.m., will get uploaded with TODAY’s date and current time.  Not quite convinced? Okay, now try searching for your photos taken in 2006. You can’t because the DAM or website will honestly reply that such media doesn’t exist. You also won’t be able to sort your photos/video by their origination date (when they were captured by the device).

How to easily screw up your multimedia timestamps

I had some BlizzCon 2010 footage shot using an old Creative Vado HD which I offloaded to a staging folder a while back. These videos are AVIs with an H.264 video track and AC3 audio track.  It would be more ideal to have these stored as standard H.264 MP4 files with an AAC audio track, for the purpose of loading into popular NLE apps like iMovie or Final Cut Pro. Theoretically, you could just cram the AVIs as a batch into Handbrake and bulk transcode, but that would be like compressing a JPEG into a JPEG —you’d risk an unnecessary loss of visual quality, even if minor. The best thing to do is feed the file through FFmpeg, passing the video data along without conversion but allow it to transcode the audio track to AAC. Plan’s set, right? WRONG.

Even though I can easily batch all the videos through transcode/passthrough script, the output files would have TODAY’S timestamp, rather than that of the original footage. Imagine searching your DAM system for the BlizzCon media, which should be dated late 2010 …only to find out that they’re dated April 2014. WTF? Serious noob mistake!

Make things right

A simple addition to an FFmpeg script can fix the problems caused by creating a batch of new, properly transcoded files. My original script was called “vado.” Here’s what I started with:

Getsuga-Tenshou:~ glenn$ cat bin/vado
#/bin/bash
ls -p *.AVI | xargs -I {} /opt/local/bin/ffmpeg -i {} -y -vcodec copy -acodec libfaac -map_metadata 0 {}.mp4

This bash script in OS X (using a MacPorts variant of FFmpeg) pipes all AVI files found in a folder through FFmpeg, preserving the video stream but converting the AC3 track to AAC, and saving the results as files of the same name but with an .mp4 extension.

If your list of source AVI videos may look like this (sorted by timestamp):

Getsuga-Tenshou:transcode glenn$ ls -lt
total 255856
-rw-rw-r--  1 glenn  staff  15208530 Jul 21  2010 VID00997.AVI
-rw-rw-r--  1 glenn  staff  74679466 Jul 21  2010 VID00996.AVI
-rw-rw-r--  1 glenn  staff   6284810 Jul 21  2010 VID00995.AVI
-rw-rw-r--  1 glenn  staff   8123934 Jul 21  2010 VID00994.AVI
-rw-rw-r--  1 glenn  staff  26688416 Jul 21  2010 VID00993.AVI

Running the original transcode script… (partial output):

Getsuga-Tenshou:transcode glenn$ ~/bin/vado .
ffmpeg version 2.1.3 Copyright (c) 2000-2013 the FFmpeg developers
  built on Feb 27 2014 13:15:47 with Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
  configuration: --prefix=/opt/local --enable-swscale --enable-avfilter --enable-avresample --enable-libmp3lame --enable-libvorbis --enable-libopus --enable-libtheora --enable-libschroedinger --enable-libopenjpeg --enable-libmodplug --enable-libvpx --enable-libspeex --enable-libass --enable-libbluray --enable-gnutls --enable-fontconfig --enable-libfreetype --disable-indev=jack --disable-outdev=xv --mandir=/opt/local/share/man --enable-shared --enable-pthreads --cc=/usr/bin/clang --arch=x86_64 --enable-yasm --enable-gpl --enable-postproc --enable-libx264 --enable-libxvid --enable-nonfree --enable-libfaac
  libavutil      52. 48.101 / 52. 48.101
  libavcodec     55. 39.101 / 55. 39.101
  libavformat    55. 19.104 / 55. 19.104
  libavdevice    55.  5.100 / 55.  5.100
  libavfilter     3. 90.100 /  3. 90.100
  libavresample   1.  1.  0 /  1.  1.  0
  libswscale      2.  5.101 /  2.  5.101
  libswresample   0. 17.104 /  0. 17.104
  libpostproc    52.  3.100 / 52.  3.100
[avi @ 0x7fcdd480f000] sample size (1) != block align (1024)
Guessed Channel Layout for  Input Stream #0.1 : mono
Input #0, avi, from 'VID00993.AVI':
  Duration: 00:00:25.17, start: 0.000000, bitrate: 8483 kb/s
    Stream #0:0: Video: h264 (Main) (H264 / 0x34363248), yuv420p, 1280x720, 30 fps, 30 tbr, 30 tbn, 60 tbc
    Stream #0:1: Audio: adpcm_ms ([2][0][0][0] / 0x0002), 44100 Hz, mono, s16, 176 kb/s
Output #0, mp4, to 'VID00993.AVI.mp4':
  Metadata:
    encoder         : Lavf55.19.104
    Stream #0:0: Video: h264 ([33][0][0][0] / 0x0021), yuv420p, 1280x720, q=2-31, 30 fps, 15360 tbn, 30 tbc
    Stream #0:1: Audio: aac (libfaac) ([64][0][0][0] / 0x0040), 44100 Hz, mono, s16, 128 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (adpcm_ms -> libfaac)
Press [q] to stop, [?] for help
frame=  755 fps=0.0 q=-1.0 Lsize=   25743kB time=00:00:25.17 bitrate=8378.3kbits/s    
video:25487kB audio:234kB subtitle:0 global headers:0kB muxing overhead 0.086883%
…

The output file list after processing all files:

Getsuga-Tenshou:transcode glenn$ ls -lt
total 508560
-rw-r--r--  1 glenn  staff  15022684 Apr  7 16:57 VID00997.AVI.mp4
-rw-r--r--  1 glenn  staff   6209487 Apr  7 16:57 VID00995.AVI.mp4
-rw-r--r--  1 glenn  staff  73759613 Apr  7 16:57 VID00996.AVI.mp4
-rw-r--r--  1 glenn  staff  26360682 Apr  7 16:57 VID00993.AVI.mp4
-rw-r--r--  1 glenn  staff   8024570 Apr  7 16:57 VID00994.AVI.mp4
-rw-rw-r--  1 glenn  staff  15208530 Jul 21  2010 VID00997.AVI
-rw-rw-r--  1 glenn  staff  74679466 Jul 21  2010 VID00996.AVI
-rw-rw-r--  1 glenn  staff   6284810 Jul 21  2010 VID00995.AVI
-rw-rw-r--  1 glenn  staff   8123934 Jul 21  2010 VID00994.AVI
-rw-rw-r--  1 glenn  staff  26688416 Jul 21  2010 VID00993.AVI

Unacceptable! Note that the MP4 timestamps have a different date than the original files. If you’re organizing your multimedia by event date then this isn’t going to work. Here’s how to make things right. Luckily the source files have associated metadata which can be applied to the destination files. With the touch command I can copy the timestamp properties of the source files using the -r flag. The new vado script reads:

Getsuga-Tenshou:~ glenn$ cat bin/vado
#/bin/bash
ls -p *.AVI | xargs -I {} /opt/local/bin/ffmpeg -i {} -y -vcodec copy -acodec libfaac -map_metadata 0 {}.mp4
ls -p *.AVI | xargs -I {} touch -r {} {}.mp4

The file list after running the source files through the updated script will look like this:

Getsuga-Tenshou:transcode glenn$ ls -lt
total 508560
-rw-rw-r--  1 glenn  staff  15208530 Jul 21  2010 VID00997.AVI
-rw-r--r--  1 glenn  staff  15022684 Jul 21  2010 VID00997.AVI.mp4
-rw-rw-r--  1 glenn  staff  74679466 Jul 21  2010 VID00996.AVI
-rw-r--r--  1 glenn  staff  73759613 Jul 21  2010 VID00996.AVI.mp4
-rw-rw-r--  1 glenn  staff   6284810 Jul 21  2010 VID00995.AVI
-rw-r--r--  1 glenn  staff   6209487 Jul 21  2010 VID00995.AVI.mp4
-rw-rw-r--  1 glenn  staff   8123934 Jul 21  2010 VID00994.AVI
-rw-r--r--  1 glenn  staff   8024570 Jul 21  2010 VID00994.AVI.mp4
-rw-rw-r--  1 glenn  staff  26688416 Jul 21  2010 VID00993.AVI
-rw-r--r--  1 glenn  staff  26360682 Jul 21  2010 VID00993.AVI.mp4

Perfect! Notice that the dates of the processed MP4 videos match up exactly to the original AVIs. Now I can import these MP4 videos directly into a consumer DAM like iPhoto or a video NLE with no metadata issues and they’ll end up in the correct spot in the media timeline.


Comments

One response to “HOWTO: Preserve photo & video media metadata after transcoding”

  1. ubuntu networking setup

    47 Ronin Research HOWTO: Preserve photo & video media metadata after transcoding » 47 Ronin Research

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.