Setting Rotation of mp4

Started by macin, August 21, 2015, 05:44:59 AM

Previous topic - Next topic

macin

I try to set the rotation of an MP4 file but exiftool refuses to write the tag:

$ exiftool -args -n -*Rotation* -*Orient* test.mp4
-Rotation=90


$ exiftool -v2 -Rotation=0 -overwrite_original test.mp4
Writing PhotoMechanic:Rotation if tag exists
Writing MIE-Orient:Rotation
Writing FotoStation:Rotation if tag exists
Writing CanonVRD:Rotation if tag exists
Writing CanonVRD:Rotation if tag exists
Writing NikonCapture:Rotation if tag exists
Writing Canon:Rotation if tag exists
Writing CanonRaw:Rotation if tag exists
Writing Canon:Rotation if tag exists
Warning: Can't convert Nikon:Rotation (matches more than one PrintConv)
======== test.mp4
Rewriting test.mp4...
  FileType = MP4
  FileTypeExtension = MP4
  MIMEType = video/mp4
  Editing tags in: CanonVRD FotoStation MIE-Orient MakerNotes PhotoMechanic
  Creating tags in: MIE-Orient
  Rewriting Movie
  Rewriting MovieHeader
  Rewriting UserData
  Rewriting Track
  Rewriting TrackHeader
  Rewriting Media
  Rewriting MediaHeader
  Rewriting Track
  Rewriting TrackHeader
  Rewriting Media
  Rewriting MediaHeader
Nothing changed in test.mp4
    0 image files updated
    1 image files unchanged


$ exiftool -v2 -n -Rotation=0 -overwrite_original test.mp4
Writing MIE-Orient:Rotation
Writing FotoStation:Rotation if tag exists
Writing PhotoMechanic:Rotation if tag exists
Writing CanonVRD:Rotation if tag exists
Writing CanonVRD:Rotation if tag exists
Writing Minolta:Rotation if tag exists
Writing Nikon:Rotation if tag exists
Writing Canon:Rotation if tag exists
Writing Canon:Rotation if tag exists
Writing Pentax:Rotation if tag exists
Writing Minolta:Rotation if tag exists
Writing CanonRaw:Rotation if tag exists
Writing Panasonic:Rotation if tag exists
Writing Sony:Rotation if tag exists
Writing Minolta:Rotation if tag exists
Writing Minolta:Rotation if tag exists
Writing Minolta:Rotation if tag exists
Writing Sony:Rotation if tag exists
Writing NikonCapture:Rotation if tag exists
Writing Sony:Rotation if tag exists
======== test.mp4
Rewriting test.mp4...
  FileType = MP4
  FileTypeExtension = MP4
  MIMEType = video/mp4
  Editing tags in: CanonVRD FotoStation MIE-Orient MakerNotes PhotoMechanic
  Creating tags in: MIE-Orient
  Rewriting Movie
  Rewriting MovieHeader
  Rewriting UserData
  Rewriting Track
  Rewriting TrackHeader
  Rewriting Media
  Rewriting MediaHeader
  Rewriting Track
  Rewriting TrackHeader
  Rewriting Media
  Rewriting MediaHeader
Nothing changed in test.mp4
    0 image files updated
    1 image files unchanged


I don't quite get why I need the -n flag even though there should be no conversion of the integer. And second why my file is unchanged in the second try?

Best regards,
macin

Phil Harvey

Hi Macin,

Yes.  ExifTool can not change the rotation of an MP4 video.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

macin

Hi Phil,

where is the difficulty in this? It seems exiftool can write other tags in MP4 files?

Regards,
Tobias

Phil Harvey

Hi Tobias,

I think this information may be stored in multiple locations.  Also, it is not a simple rotation, but a 9-parameter transformation matrix.  ExifTool just calculates and returns the rotation from this matrix, but there is also possibly some scaling going on.

As well, video formats are a real can of worms.  I think they are designed specifically to make it difficult for small software projects to support them.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

macin

And there is no way to print the matrix with exiftool (without patching the source code)?

Phil Harvey

#5
Try using the -v3 option.

- Phil

Edit: I took a look at this for an MP4 sample I have here:

> exiftool ../pics/CanonPowerShotG1X_MarkII.mp4 -rotation -G1
[Composite]     Rotation                        : 0


And checking the Composite Tags documentation, this is derived from QuickTime:MatrixStructure, so you can print the matrix like this:

> exiftool ../pics/CanonPowerShotG1X_MarkII.mp4 -rotation -matrixstructure -G0:1 -a
[Composite]     Rotation                        : 0
[QuickTime]     Matrix Structure                : 1 0 0 0 1 0 0 0 1
[QuickTime:Track1] Matrix Structure             : 1 0 0 0 1 0 0 0 1
[QuickTime:Track2] Matrix Structure             : 1 0 0 0 1 0 0 0 1
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

macin

Thanks Phil. I can reproduce this. But the matrix structure is also not writable. The QuickTime Tags documentation seems to confirm this. Too bad...

PiXLHH

I played around with ffmpeg, lossless (flag-based) rotations (and realized they delete quite some metadata in the process, even with -map_metadata option enabled, 700kb in total).
Unhappy about this (and who knows what this might be good for at a later time) I compared all four rotations of the same file with a hex editor to see where the differences are. Only in one small section!


  • 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
  • look for one of the following patterns and alter it to whatever rotation you need

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


This has also the advantage, that it works blazing fast on a server, as only these bytes are changed, and not the whole file has to be rewritten. For practice runs, make a backup, though!

Also, the audio channels won't be affected by this, in case you care about it and have stereo sound, this might result in something odd.

@Phil - can this be implemented into exiftool? Seems like a fairly easy switch, and I tried lots of different mp4 files and all worked fine.

more on this on https://superuser.com/questions/1307158/change-rotation-flag-in-mp4-video-without-losing-metadata

Phil Harvey

#8
The rotation matrix exists in both the movie header and the track header.  I suppose it wouldn't be too hard to allow ExifTool to write these.  I'll look into it.

- Phil

Edit:  I've added the code to write the MatrixStructure in the movie header and all tracks by setting the value of the Rotation tag.  It seems to work, so this will appear in Exiftool 10.89.
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

PiXLHH

Phil, thanks for the quick response, I'm excited to try it. From my intense web research this seems to be the only program that will be able to do this job.

I don't understand enough about the different tracks, but from the files I inspected I saw the 0° rotation matrix in every track, but only in the video track I found all the 0°, 90°, 180° and 270° variants. This is from both, "ffmpeg rotate" stream copy and from Samsung Galaxy S2, S5 and S8 mp4 video file analysis. So I am not sure if it is a good idea to write the MatrixStructure in all headers. Also, it did not swap the sound left and right in the audio track in VLC and Windows player.

Axel

Phil Harvey

#10
Hi Axel,

This turns out to be not as simple as I had hoped, but I should still be able to pull this off.  The MatrixStructure needs to be offset by the size of the video when a rotation is applied.  So for a 640x480 video, these are the structures that ExifTool will write:

0 degrees: 1 0 0 0 1 0 0 0 1
90 degrees: 0 1 0 -1 0 0 480 0 1
180 degrees: -1 0 0 0 -1 0 640 480 1
270 degrees: 0 -1 0 1 0 0 0 640 1

Also, ExifTool will only apply the rotation to a track where the image size is non-zero.

This should hopefully address the potential issues with offsets and rotation of tracks that shouldn't be rotated.

ExifTool will also allow you to rotate by any arbitrary angle, but I doubt the viewers support this.  For these, I don't apply any offsets.

As well, you will be able to write MatrixStructure directly for any track, or the movie header itself.

- Phil

Edit: Actually, I don't think I'll make the movie header rotation matrix writable.  Rotating the video track does the job.
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

PiXLHH

Hi Phil,

I'm sure you have better resources than my web research (such as the mp4 metadata whitepaper), I honestly could not find any offset in the metadata of my files in the hex code. So it seems like it's not really pursued in practice with the offset (at least Samsung and ffmpeg).

Since I have already rotated all my upside-down GoPro videos manually by hex editor, without problems for now, I'll keep the offset in the back of my head in case it causes problems at a later time. Thanks for your amazing tool and its support!

Axel

Phil Harvey

I've just released ExifTool 10.89, which gives you the ability to set the rotation of MOV/MP4 videos.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

PiXLHH

Works like a charm, thanks!

Could you explain what the offset is good for? Could not find any information regarding this field, and it's also not shown in exiftool or ffprobe metadata tags.

Also, I couldn't figure out whether it is possible to just overwrite the bits instead of rewriting the whole files? I do lots of work on NAS, also for timestamp adjustments on videos and photos, and it would save hours or even days if exiftool could just adjust the bits accordingly.

Best
Axel

Phil Harvey

Hi Axel,

If there are multiple overlaid video tracks then the x/y offsets would be crucial, but for a single video track it seems that the players assume the video must be on screen, so they compensate for an incorrect offset.

It is certainly possible to just overwrite these bits in the file, but ExifTool doesn't do this.  The reason is because it would break the ExifTool interface, which is designed specifically to work with unseekable media so it can be used in a pipeline (eg. editing a file as it is being downloaded).  I would have to create a whole other set of writing functions to do this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).