23

I just want to change the rotation flag in a .mp4 video file. Many similar questions exist, most answers suggest using

ffmpeg -i input.mp4 -map_metadata 0 -metadata:s:v rotate=90 -codec copy output.mp4

My problem with those solutions is that even though it copies most of the metadata, some parts are lost, and the file is 700kb smaller. Attached is before and after metadata from ffprobe and exifer.

An additional odd finding is the ffmpeg rotate=90 command makes a ccw rotation, which in ffprobe is (cw) 270° in metadata, but (ccw)90° in displaymatrix side data.

= equal attributes
* altered attributes
- removed attributes
+ added attributes

ffprobe input.mp4

*Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '.\input.mp4':
=  Metadata:
*    major_brand     : avc1
*    minor_version   : 0
*    compatible_brands: avc1isom
=    creation_time   : 2016-10-29T12:10:41.000000Z
-    firmware        : HD3.11.03.03
*  Duration: 00:00:06.01, start: 0.000000, bitrate: 32072 kb/s
=    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709), 1920x1440 [SAR 1:1 DAR 4:3], 30945 kb/s, 47.95 fps, 47.95 tbr, 720k tbn, 95.90 tbc (default)
=    Metadata:
=      creation_time   : 2016-10-29T12:10:41.000000Z
*      handler_name    :  GoPro AVC
-      encoder         : GoPro AVC encoder
-    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
-    Metadata:
-      creation_time   : 2016-10-29T12:10:41.000000Z
-      handler_name    :  GoPro AAC

ffprobe output.mp4

*Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '.\output.mp4':
=  Metadata:
*    major_brand     : isom
*    minor_version   : 512
*    compatible_brands: isomiso2avc1mp41
=    creation_time   : 2016-10-29T12:10:41.000000Z
+    encoder         : Lavf58.10.100
*  Duration: 00:00:06.01, start: 0.000000, bitrate: 30948 kb/s
=    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709), 1920x1440 [SAR 1:1 DAR 4:3], 30945 kb/s, 47.95 fps, 47.95 tbr, 720k tbn, 95.90 tbc (default)
=    Metadata:
+      rotate          : 270
=      creation_time   : 2016-10-29T12:10:41.000000Z
*      handler_name    : VideoHandler
+    Side data:
+      displaymatrix: rotation of 90.00 degrees

exiftool input.mp4

=ExifTool Version Number         : 10.87
*File Name                       : input.mp4
=Directory                       : C:/
*File Size                       : 23 MB
*File Modification Date/Time     : 2016:10:29 13:10:48+02:00
*File Access Date/Time           : 2018:03:22 22:51:11+01:00
*File Creation Date/Time         : 2018:03:22 22:51:11+01:00
=File Permissions                : rw-rw-rw-
=File Type                       : MP4
=File Type Extension             : mp4
=MIME Type                       : video/mp4
*Major Brand                     : MP4 Base w/ AVC ext [ISO 14496-12:2005]
*Minor Version                   : 0.0.0
*Compatible Brands               : avc1, isom
=Movie Header Version            : 0
=Create Date                     : 2016:10:29 12:10:41
=Modify Date                     : 2016:10:29 12:10:41
*Time Scale                      : 90000
=Duration                        : 6.01 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
-Firmware Version                : HD3.11.03.03
-Lens Serial Number              : LW13121003000141
-Camera Serial Number Hash       : 4833422b363033313530636432356400
=Track Header Version            : 0
=Track Create Date               : 2016:10:29 12:10:41
=Track Modify Date               : 2016:10:29 12:10:41
=Track ID                        : 1
=Track Duration                  : 6.01 s
=Track Layer                     : 0
=Track Volume                    : 0.00%
=Image Width                     : 1920
=Image Height                    : 1440
=Graphics Mode                   : srcCopy
=Op Color                        : 0 0 0
=Compressor ID                   : avc1
=Source Image Width              : 1920
=Source Image Height             : 1440
=X Resolution                    : 72
=Y Resolution                    : 72
-Compressor Name                 : .GoPro AVC encoder
=Bit Depth                       : 24
-Color Representation            : nclc 1 1 1
-Gamma                           : 2.2
=Video Frame Rate                : 47.952
-Matrix Structure                : 1 0 0 0 1 0 0 0 1
=Media Header Version            : 0
=Media Create Date               : 2016:10:29 12:10:41
=Media Modify Date               : 2016:10:29 12:10:41
-Media Time Scale                : 48000
-Media Duration                  : 5.99 s
*Handler Type                    : Audio Track
-Handler Description             : .GoPro AAC
-Balance                         : 0
-Audio Format                    : mp4a
-Audio Channels                  : 2
-Audio Bits Per Sample           : 16
-Audio Sample Rate               : 48000
-Movie Data Size                 : 24045320
-Movie Data Offset               : 32768
*Avg Bitrate                     : 32 Mbps
=Image Size                      : 1920x1440
=Megapixels                      : 2.8
*Rotation                        : 0

exiftool output.mp4

=ExifTool Version Number         : 10.87
*File Name                       : output.mp4
=Directory                       : C:/
*File Size                       : 22 MB
*File Modification Date/Time     : 2018:03:23 12:29:19+01:00
*File Access Date/Time           : 2018:03:23 12:28:18+01:00
*File Creation Date/Time         : 2018:03:23 12:28:18+01:00
=File Permissions                : rw-rw-rw-
=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
+Movie Data Size                 : 23232544
+Movie Data Offset               : 48
=Movie Header Version            : 0
=Create Date                     : 2016:10:29 12:10:41
=Modify Date                     : 2016:10:29 12:10:41
*Time Scale                      : 1000
=Duration                        : 6.01 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                   : 2
=Track Header Version            : 0
=Track Create Date               : 2016:10:29 12:10:41
=Track Modify Date               : 2016:10:29 12:10:41
=Track ID                        : 1
=Track Duration                  : 6.01 s
=Track Layer                     : 0
=Track Volume                    : 0.00%
+Matrix Structure                : 0 1 0 -1 0 0 0 0 1
=Image Width                     : 1920
=Image Height                    : 1440
=Media Header Version            : 0
=Media Create Date               : 2016:10:29 12:10:41
=Media Modify Date               : 2016:10:29 12:10:41
+Media Time Scale                : 720000
+Media Duration                  : 6.01 s
+Media Language Code             : eng
+Handler Description             : VideoHandler
=Graphics Mode                   : srcCopy
=Op Color                        : 0 0 0
=Compressor ID                   : avc1
=Source Image Width              : 1920
=Source Image Height             : 1440
=X Resolution                    : 72
=Y Resolution                    : 72
=Bit Depth                       : 24
+Pixel Aspect Ratio              : 1:1
=Video Frame Rate                : 47.952
*Handler Type                    : Metadata
+Handler Vendor ID               : Apple
+Encoder                         : Lavf58.10.100
*Avg Bitrate                     : 30.9 Mbps
=Image Size                      : 1920x1440
=Megapixels                      : 2.8
*Rotation                        : 270

I compared ffmpeg rotate=0 and rotate=90 .mp4 files in notepad++ to identify the rotate flag / matrix, but without luck, just jibberish. I would prefer to just edit the flag (like exiftool is doing it for all kinds of metadata, but can't do rotate in videos) instead of streaming the content into a new container, also for faster processing (all videos are on NAS).

aXeL-HH
  • 930
  • 1
  • 8
  • 15

3 Answers3

31

exiftool version 10.89 now has support to rotate mp4 videos without changing other metadata.

Usage:

exiftool -rotation=90 video.mp4
aXeL-HH
  • 930
  • 1
  • 8
  • 15
  • Didn't work for me for some reason. – Suncatcher Aug 10 '18 at 13:48
  • Worked like a charm - thank you! – emrass Jun 30 '19 at 17:10
  • 1
    @Suncatcher Try `exiftool -rotation=0 video.mov`. Makes no sense but it worked on my iPhone video. – pacoverflow Nov 23 '19 at 08:14
  • does not work with `mkv`. – bomben Mar 10 '21 at 11:20
  • check version with 'exiftool -ver' . Default installation was 10.10 on an older Lubuntu 16, in Apr '21. Version 11.88 on a newer Lubuntu 20. – DragonLord Apr 14 '21 at 01:21
  • @pacoverflow This does make sense, because the video is encoded in landscape, it's only marked as "rotated 90 degrees" to tell video players to render it in portrait (rotating 90 degrees after decoding). This is probably because the encoding is done by hardware. Always encoding in the same orientation could simplify hardware design, I imagine. – aross Jun 13 '22 at 13:27
28

To get true lossless rotation, I couldn't find a solution, so I grabbed a hex editor (eg HxD) and analyzed the rotated video files.

  • open mp4 with hex editor and search for vide to find the metadata of the video track
  • some rows above (for my files mostly 9, sometimes 12) you should see trak...\tkhd
  • in between there should be an @ sign (HEX 40)
  • in the two rows before it the rotation matrix is stored
  • no rotation:

    00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    40
    
  • 180°:

    FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    40
    
  • 90° cw:

    00 00 00 00 00 01 00 00 00 00 00 00 FF FF 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    40 
    
  • 90° ccw:

    00 00 00 00 FF FF 00 00 00 00 00 00 00 01 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    40
    

Alter the file as you need it, and it should be rotated in players that support the rotation flag (most current players do).

In case your video contains stereo audio, this is obviously not switched, so in case you want the sound to match with video rotation (180°), you need to switch the left and right channels.

aXeL-HH
  • 930
  • 1
  • 8
  • 15
0

Some answers suggest that exiftool can't be used for this, but as of recent versions it definitely can.

exiftool -rotation=0 video.mp4 

This clears any rotation flags and assumes that the camera was used in it's normal (landscape) orientation. It does take about a minute which is surprising since it's only changing a couple bytes.

O:\>exiftool -ver
12.29

T:\>dir 2021*658*.mp4
 Volume in drive T is temp
 Volume Serial Number is 30A1-6AD0

 Directory of T:\

03/06/2021  02:45 PM       327,499,207 20210306_144335-00.00.00.000-00.01.32.658.mp4
               1 File(s)    327,499,207 bytes
               0 Dir(s)  16,700,923,904 bytes free

T:\>exiftool -rotation=0 20210306_144335-00.00.00.000-00.01.32.658.mp4
    1 image files updated

T:\>dir 2021*658*.mp4

12/07/2021  05:19 PM       327,499,207 20210306_144335-00.00.00.000-00.01.32.658.mp4
               1 File(s)    327,499,207 bytes
               0 Dir(s)  16,229,441,536 bytes free
Al Ro
  • 119
  • 3
  • How is this better than accepted answer? – Toto Dec 10 '21 at 17:59
  • accepted answer has several comments that it doesn't work; this provides proof that it does leave the size unchanged and documents the version used. – Al Ro Dec 11 '21 at 18:06
  • Sorry, but [accepted answer](https://superuser.com/a/1307206/763386) doesn't have any negative comments. – Toto Dec 11 '21 at 18:10
  • " Didn't work for me for some reason. – Suncatcher Aug 10 '18 at 13:48 " – Al Ro Dec 12 '21 at 00:08
  • This comment isn't attach to accepted answer. – Toto Dec 12 '21 at 09:21
  • the accepted answer of using a hex editor is certainly interesting and useful, but way beyond what most people can do. – Al Ro Dec 22 '21 at 06:51
  • Thanks VERY much for providing this answer. This made all the difference to me. My up vote now cancels the down vote. I've seen some terrible (wrong) answers on the various SO sites that definitely deserve a down vote. I don't think this is one of them. – NeilG Aug 13 '23 at 08:20
  • To clarify the usefulness of this answer I was attempting to use `ffmpeg` command lines from various SO answers to rotate a video 90', and hopefully go on to lighten it in size. `ffmpeg` was doing some work but stripping the "Side data" `displaymatrix` rotation, which meant that the applied rotation of 90' ended up being 180', even in the same player. I couldn't get any answers to work for me. But applying this `exiftool` command immediately allowed `ffmpeg` to apply rotations consistently and make the videos viewable right way up. – NeilG Aug 13 '23 at 08:25