How to rotate videos using FFmpeg

Quite often, when using a smartphone, we shoot videos in portrait mode, also known as vertical video, or even rotated 180 degrees. Depending on the software or app you're using to edit, preview or share, the videos might appear rotated or even upside down.

This might also happen if you start recording in one orientation and then rotate the smartphone before the device has a chance to update it's orientation settings. Video rotation is one tricky, but simple issue to overcome and in this guide we will show you how to fix rotated videos using FFMpeg.

Video rotation metadata

Videos and images created by mobile devices including iPhones and Android phones contain a lot of metadata like GPS position, device make and model, fps, rotation and many others.

In this article we'll focus on the rotation - it represents the orientation of the device. It has 4 possible values (0, 90, 180 and 270) and it stores how the device was held when starting the recording:

No rotationRotated 90 degreesRotated 180 degreesRotated 270 degrees
portraitverticalportraitvertical
90°180°270°

However, it's not only the rotation that needs to be fixed, it's also the width and height of the video that needs to be adjusted as these can also be he wrong way round.

This tutorial will show you how to use FFmpeg to rotate videos and get the right orientation, width and height with just a couple of commands.

Prerequisites

This guide covers Windows, Mac and Linux distributions - the apps we'll use are platform independent.

FFmpeg is the leading multimedia framework used to manipulate and transform video files easily. ExifTool is a free and open-source program for reading and modifying metadata and exif information.

Sample videos

We prepared a few sample videos if you want to experiment using different video rotations - please check the Test Media repository for free to use samples.

For this article we used the h1920_w1080_f30_a9-16_r90.mp4 video, which was shot using a Samsung S9 Android device in vertical, portrait orientation.

First let's take a look at the metadata of the video we want to fix. We can use ExifTool, ffprobe or ffmpeg.

Get rotated video metadata using ExifTool

exiftool h1920_w1080_f30_a9-16_r90.mp4 

This command will return all metadata from the video file. We only need to retrieve the rotation and the dimensions, so we can pass the -Rotation, -ImageWidth and -ImageHeight options.

You can pass them individually:

exiftool -Rotation h1920_w1080_f30_a9-16_r90.mp4

or all at once:

exiftool -Rotation -ImageWidth -ImageHeight h1920_w1080_f30_a9-16_r90.mp4

The output confirms what we described - the rotation is 90 and the width and height are switched:

Rotation                        : 90
Image Width : 1920
Image Height : 1080

Because the video is shot in vertical mode, we would expect the width to be 1080 and the height, 1920 pixels.

Get video rotation metadata using FFprobe or FFmpeg

FFprobe is an utility that comes bundled with FFmpeg. It analyzes the video metadata and prints the information in human readable format

ffprobe -i h1920_w1080_f30_a9-16_r90.mp4

or

ffmpeg -i h1920_w1080_f30_a9-16_r90.mp4

We can see in the output that rotate is set to 90:

    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 14067 kb/s,
SAR 1:1 DAR 16:9, 30.01 fps, 30 tbr, 90k tbn, 180k tbc (default)
Metadata:
rotate : 90
creation_time : 2020-04-18T05:27:06.000000Z
handler_name : VideoHandle
Side data:
displaymatrix: rotation of -90.00 degrees

To filter the FFprobe info we can use different commands:

To retrieve just the rotation:

ffprobe -v error -select_streams v:0 -show_entries stream_tags=rotate -of default=nw=1:nk=1 -i h1920_w1080_f30_a9-16_r90.mp4

To retrieve the width:

ffprobe -v error -select_streams v:0 -show_entries stream=width -of default=nw=1:nk=1 -i h1920_w1080_f30_a9-16_r90.mp4

We'll get rotation = 90 and width = 1920

Fix video rotation using FFmpeg

To fix the video rotation so it is compatible with the widest range of software and viewing applications we will need to reset the rotation and then swap around the width and height.

First we need to reset the rotation to 0:

ffmpeg -i h1920_w1080_f30_a9-16_r90.mp4 -c copy -metadata:s:v:0 rotate=0 temp.mp4

This will create a copy of the video and reset the rotation metadata to 0. However, the width and height are still the wrong way round. You might notice the thumbnail of the newly generated video is rotated.

Let's check the metadata just to make sure we got the rotation right:

exiftool -Rotation -ImageWidth -ImageHeight temp.mp4
Rotation                        : 0
Image Width : 1920
Image Height : 1080

The rotation is correct but the width should be 1080 and height 1920.

Try it again with ffprobe:

ffprobe -i temp.mp4

We'll see the Rotation info was dropped - so it is now set to 0:

    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 14067 kb/s,
SAR 1:1 DAR 16:9, 30.01 fps, 30 tbr, 90k tbn, 180k tbc (default)
Metadata:
handler_name : VideoHandler

Fix video width and height

We now need to re-encode the video to ensure the width and height will be flipped so that the dimensions are correct:

ffmpeg -i temp.mp4 -vf "transpose=1" -crf 23 -c:a copy rotated.mp4

The -crf (Constant Rate Factor) value is a quality setting used for mp4 video compression. For our example we used 23 which gives a file size close to the original.

The transpose feature uses static values; you can use either the integer or the string value:

IntegerStringValue
0cclock_flip90° counterclockwise and vertical flip (default)
1clock90° clockwise
2cclock90° counterclockwise
3clock_flip90° clockwise and vertical flip

The same command can be run, passing the corresponding string to the transpose parameter:

ffmpeg -i temp.mp4 -vf "transpose=clock" -crf 23 -c:a copy rotated.mp4

To rotate videos by 180 degrees counter clockwise, you to need to add the transpose parameter twice like below.

ffmpeg -i temp.mp4 -vf "transpose=2,transpose=2" -crf 23 -c:a copy rotated.mp4

or

ffmpeg -i temp.mp4 -vf "transpose=cclock,transpose=cclock" -crf 23 -c:a copy rotated.mp4

One last step, to confirm the width and height are correct:

exiftool -Rotation -ImageWidth -ImageHeight rotated.mp4

There it is:

Rotation                        : 0
Image Width : 1080
Image Height : 1920

If we need one more confirmation:

ffprobe -v error -select_streams v:0 -show_entries stream=width -of default=nw=1:nk=1 -i rotated.mp4

the width is confirmed at 1080.

ffprobe -v error -select_streams v:0 -show_entries stream=height -of default=nw=1:nk=1 -i rotated.mp4

will confirm the height is 1920.

Generating vertical video with Shotstack

Once you have resolved any rotation issues with your video it is now ready to be used in an edit and rendered by the Shotstack video editing API.

Here is the JSON we post to the API to render a vertical video. In this example we are using a fixed version of our original h1920_w1080_f30_a9-16_r90.mp4 file. The aspect ratio and the fit parameters ensure we render a vertical video:

{
"timeline": {
"background": "#000000",
"soundtrack": {
"src": "https://shotstack-assets.s3-ap-southeast-2.amazonaws.com/music/unminus/palmtrees.mp3",
"effect": "fadeOut"
},
"tracks": [
{
"clips": [
{
"asset": {
"type": "video",
"src": "https://shotstack-video-hosting.s3-ap-southeast-2.amazonaws.com/h1920_w1080_f30_a9-16_r90-fixed.mp4"
},
"start": 0,
"length": 10,
"fit": "contain"
}
]
}
]
},
"output": {
"format": "mp4",
"resolution": "sd",
"aspectRatio": "9:16"
}
}

Which creates the video below:

Icons made by prettycons from Flaticon

Jeff Shillitto

BY VLAD BARTUSICA
22nd February, 2021