Skip to main content

Preserving Metadata With FFmpeg

ffmpeg-logo.png

The FFmpeg suite of multimedia tools is a very powerful toolkit, but sometimes its default behavior just plain surprises me. While I am totally impressed by its capability to stabilize videos taken by my mobile phone, it took me some time to realize that this processing step lost all the metadata. Of course, I did not expect this, and it is trivial to fix the script, but first you need to be aware that the problem even exists.

To see the problem, we use exiftool to look at the metadata of a video shot with a mobile phone:

dzu@krikkit:~/Bilder/2022/09/2022-09-09-Geigerhof$ exiftool VID_20220909_121236.mp4 
ExifTool Version Number         : 12.44
File Name                       : VID_20220909_121236.mp4
Directory                       : .
File Size                       : 27 MB
File Modification Date/Time     : 2022:09:09 12:12:36+02:00
File Access Date/Time           : 2022:09:09 12:12:36+02:00
File Inode Change Date/Time     : 2022:09:11 23:35:40+02:00
File Permissions                : -rw-------
File Type                       : MP4
File Type Extension             : mp4
MIME Type                       : video/mp4
Major Brand                     : MP4 v2 [ISO 14496-14]
Minor Version                   : 0.0.0
Compatible Brands               : isom, mp42
Movie Header Version            : 0
Create Date                     : 2022:09:09 10:12:36
Modify Date                     : 2022:09:09 10:12:36
Time Scale                      : 1000
Duration                        : 17.30 s
Preferred Rate                  : 1
Preferred Volume                : 100.00%
Preview Time                    : 0 s
Preview Duration                : 0 s
Poster Time                     : 0 s
Selection Time                  : 0 s
Selection Duration              : 0 s
Current Time                    : 0 s
Next Track ID                   : 3
Android Version                 : 9
Track Header Version            : 0
Track Create Date               : 2022:09:09 10:12:36
Track Modify Date               : 2022:09:09 10:12:36
Track ID                        : 1
Track Duration                  : 17.30 s
Track Layer                     : 0
Track Volume                    : 0.00%
Image Width                     : 1920
Image Height                    : 1080
Graphics Mode                   : srcCopy
Op Color                        : 0 0 0
Compressor ID                   : hvc1
Source Image Width              : 1920
Source Image Height             : 1080
X Resolution                    : 72
Y Resolution                    : 72
Bit Depth                       : 24
Pixel Aspect Ratio              : 65536:65536
Color Representation            : nclx 1 1 1
Video Frame Rate                : 29.819
Matrix Structure                : 1 0 0 0 1 0 0 0 1
Media Header Version            : 0
Media Create Date               : 2022:09:09 10:12:36
Media Modify Date               : 2022:09:09 10:12:36
Media Time Scale                : 48000
Media Duration                  : 17.19 s
Handler Type                    : Audio Track
Handler Description             : SoundHandle
Balance                         : 0
Audio Format                    : mp4a
Audio Channels                  : 2
Audio Bits Per Sample           : 16
Audio Sample Rate               : 48000
Media Data Size                 : 26446287
Media Data Offset               : 810338
Image Size                      : 1920x1080
Megapixels                      : 2.1
Avg Bitrate                     : 12.2 Mbps
dzu@krikkit:~/Bilder/2022/09/2022-09-09-Geigerhof$

Then I used my incorrect script to stabilize this video:

dzu@krikkit:~/Bilder/2022/09/2022-09-09-Geigerhof$ ffmpeg-vidstab -o output.mp4 VID_20220909_121236.mp4

Running exiftool on the result, it is clear that metadata was lost:

dzu@krikkit:~/Bilder/2022/09/2022-09-09-Geigerhof$ exiftool output.mp4 
ExifTool Version Number         : 12.44
File Name                       : output.mp4
Directory                       : .
File Size                       : 16 MB
File Modification Date/Time     : 2022:09:12 00:35:31+02:00
File Access Date/Time           : 2022:09:12 00:34:56+02:00
File Inode Change Date/Time     : 2022:09:12 00:35:31+02:00
File Permissions                : -rw-r--r--
File Type                       : MP4
File Type Extension             : mp4
MIME Type                       : video/mp4
Major Brand                     : MP4 Base Media v1 [IS0 14496-12:2003]
Minor Version                   : 0.2.0
Compatible Brands               : isom, iso2, avc1, mp41
Media Data Size                 : 15750230
Media Data Offset               : 48
Movie Header Version            : 0
Create Date                     : 0000:00:00 00:00:00
Modify Date                     : 0000:00:00 00:00:00
Time Scale                      : 1000
Duration                        : 17.30 s
Preferred Rate                  : 1
Preferred Volume                : 100.00%
Preview Time                    : 0 s
Preview Duration                : 0 s
Poster Time                     : 0 s
Selection Time                  : 0 s
Selection Duration              : 0 s
Current Time                    : 0 s
Next Track ID                   : 3
Track Header Version            : 0
Track Create Date               : 0000:00:00 00:00:00
Track Modify Date               : 0000:00:00 00:00:00
Track ID                        : 1
Track Duration                  : 17.30 s
Track Layer                     : 0
Track Volume                    : 0.00%
Image Width                     : 1920
Image Height                    : 1080
Graphics Mode                   : srcCopy
Op Color                        : 0 0 0
Compressor ID                   : avc1
Source Image Width              : 1920
Source Image Height             : 1080
X Resolution                    : 72
Y Resolution                    : 72
Compressor Name                 : Lavc59.37.100 libx264
Bit Depth                       : 24
Pixel Aspect Ratio              : 1:1
Buffer Size                     : 0
Max Bitrate                     : 7094010
Average Bitrate                 : 7094010
Video Frame Rate                : 29.833
Matrix Structure                : 1 0 0 0 1 0 0 0 1
Media Header Version            : 0
Media Create Date               : 0000:00:00 00:00:00
Media Modify Date               : 0000:00:00 00:00:00
Media Time Scale                : 48000
Media Duration                  : 17.19 s
Media Language Code             : eng
Handler Description             : SoundHandle
Balance                         : 0
Audio Format                    : mp4a
Audio Channels                  : 2
Audio Bits Per Sample           : 16
Audio Sample Rate               : 48000
Handler Type                    : Metadata
Handler Vendor ID               : Apple
Encoder                         : Lavf59.27.100
Location Information            : (none) Role=shooting Body=earth Notes=
Image Size                      : 1920x1080
Megapixels                      : 2.1
Avg Bitrate                     : 7.28 Mbps
dzu@krikkit:~/Bilder/2022/09/2022-09-09-Geigerhof$

It is somewhat unfortunate that I realized this problem only after converting a few of the movies, but then again better late than never. Studying the FFmpeg documentation it turns out that there is an easy solution for the problem. Just add the option -map_metadata 0 to the command line.

Somehow I would have expected FFmpeg to use such a configuration by default, and maybe you would too!

So remember, preserving metadata with FFmpeg is your own duty! Specify -map_metadata 0 for transformations to do this.

Deshaking script

For your convenience, here is my script ffmpeg-vidstab to deshake the videos from my mobile:

#!/bin/sh
set -e

usage() {
    echo "usage: `basename $0` [-h] [-c] [-o <out-file>] <in-file> ..." >&2
    echo "        stabilizes video file <in-file> and writes to <out-file>" >&2
    echo "       <-c> will also create a side-by-side comparison video 'comparison.mp4'" >&2
    exit 1
}

OUTFILE=output.mp4
while getopts cho: OPTION
do
    case $OPTION in
        c) COMP=yes
           ;;
        o) OUTFILE=$OPTARG
           ;;
        h) HELP=yes
           ;;
    esac
done
shift $(( $OPTIND - 1 ))

if [ "yes" = "$HELP" ]; then
    usage
fi

if [ $# -lt 1 ]; then
    usage
fi

TRANSFORMS=`mktemp --tmpdir transforms.XXXX` 
ffmpeg -i $1 -vf vidstabdetect=stepsize=32:shakiness=10:accuracy=15:result=$TRANSFORMS -f null -
ffmpeg -y -i $1 -vf vidstabtransform=input=${TRANSFORMS}:zoom=0:smoothing=20,unsharp=5:5:0.8:3:3:0.4 \
       -vcodec libx264 -tune film -acodec copy -preset slow -map_metadata 0 $OUTFILE
rm $TRANSFORMS

if [ "yes" = "$COMP" ]; then 
   # Generate a side by side comparison
    ffmpeg -i $1 -i $OUTFILE -filter_complex "hstack,format=yuv420p" -c:v libx264 -crf 18 \
           comparison.mp4
fi

Comments

Comments powered by Disqus