Rotating a Video 90° or 180°: the Flag or the Pixels
Published 8/10/2026 · 11 min read · File tools
Daniel Okonkwo — Front-end developer and tech writer at Allin
Web performance · File formats
Checked against 3 sources
This tool re-encodes. It does not set a rotation flag. The command it builds is -i <file> -vf <chain> -c:v libx264 -preset ultrafast -crf 23 -c:a aac -b:a 192k <output>, where the chain is transpose=1 for a quarter turn to the right, transpose=2 for a quarter turn to the left, and hflip,vflip for a half turn — two mirrors being cheaper than two transposes and giving exactly the same picture, which a frame-by-frame comparison confirms. A WebM source takes the same route through libvpx and Opus instead. Ticking a mirror box appends hflip or vflip to the chain. Turning off the sound replaces the audio arguments with -an. Every pixel is therefore decoded, moved and re-compressed, which is slow, costs one lossy generation, and produces a file that plays the right way up in absolutely everything because there is no flag left for a player to ignore. Two consequences worth knowing before you press the button. A quarter turn swaps the stored frame size: a 1080x1920 clip comes out 1920x1080, and the tool prints that swap on screen before you run it. And the file does not get smaller. On a 6-second 1080x1920 test clip of 493,466 bytes, a 90-degree turn produced 513,371 bytes — 4 percent larger than the source, because preset ultrafast at CRF 23 spends bits more freely than whatever encoder made the original. Sound is kept but re-encoded to AAC at 192 kbps; it is never copied across untouched.
There are two completely different ways to turn a video, and only one of them touches the picture. This tool takes the slow, lossy, universal road — and there is a good chance your sideways phone clip does not need it at all.
Two operations that look identical and are not
A video file can be turned in two ways. The first writes a small instruction into the container — a display matrix, in the MP4 and QuickTime family — that says "show this rotated by 90 degrees". The pixels are untouched, the operation takes as long as rewriting a few dozen bytes, and it is perfectly reversible. The second decodes every frame, moves the pixels, and compresses them again. That takes minutes rather than milliseconds, costs one generation of lossy compression, and cannot be undone.
The catch with the flag is that it is only advice. A player has to read the container, find the matrix and apply it, and not every player does. Web players honour it inconsistently, some editing programs import the raw frames and ignore the instruction, some set-top boxes and older televisions never learned about it, and a few tools apply it a second time on top of a player that already did — which is how a clip ends up upside down. The flag is instant and lossless and sometimes not obeyed; the re-encode is slow and lossy and always obeyed. There is no third option that is both.
This tool chose the second road deliberately, and it says so in a line under its controls: the turn is written into the picture itself, not into a flag some players ignore and others apply twice, and that is why it re-encodes. That is an honest description of the code. The table below is the trade in full, so you can decide whether you want it before you spend the minutes.
Your sideways phone clip may not need rotating at all
This is the most common reason people arrive at a rotation tool, and it is usually the wrong fix. A phone records with its sensor in a fixed orientation and writes a rotation flag describing how you were holding it. The file is therefore correct: the pixels are landscape, the flag says "quarter turn", and every application that reads the flag shows the video upright. When one application shows it sideways, that application is the thing at fault, not the file.
The tool does not surface the existing flag, and that is its most useful missing feature. It reads the clip's dimensions from a hidden video element in the page, and browsers already report those dimensions after applying the rotation — so a portrait phone clip shows up as portrait, correctly, with nothing to say whether that is because the pixels are portrait or because a flag said so. From inside the tool you cannot tell the two apart. Do the check outside it: open the clip in two different players. If one shows it upright and the other sideways, there is a flag, the file is fine, and re-encoding it will only cost you quality. If every player shows it sideways, the pixels really are sideways and this is the right tool.
One reassurance if you go ahead anyway. This build of ffmpeg applies an existing rotation flag before your filter runs, so the turn you ask for composes with the flag rather than fighting it: the output is what the preview showed, and it carries no flag afterwards. You will not get a clip that is rotated twice. You will simply have paid for a re-encode you may not have needed.
The mirror boxes, the live preview and the file
The tool shows a live preview: your clip playing, turned by CSS, so you can see the framing before committing. It is a genuinely good idea, and for a while it was right for every combination but four. The preview used to apply its transform as rotate then scale, and CSS composes those right to left — so the mirror happened first and the rotation second. The filter chain does the opposite: transpose comes first, the mirrors are appended after it. Rotating and mirroring do not commute, so those two orders are not the same picture, and a quarter turn with exactly one mirror ticked produced a file half a turn from the preview. The preview now writes scale then rotate, which composes as rotate-then-mirror and matches the chain. The file was always the correct one; it was the picture of it that lied.
Running both orders through the same encoder settles it. On the same test clip, transpose=1,hflip and hflip,transpose=1 produced two different frames — different byte counts, different checksums — while running either command twice produced byte-identical output, so the difference is real and not encoder noise. Tick both mirrors together and the disagreement vanishes: transpose=1,hflip,vflip and hflip,vflip,transpose=1 gave the identical frame, because a pair of mirrors is a half turn and a half turn does commute with anything.
In practice, all sixteen button combinations now agree with the preview, and the two-pass workaround this article used to recommend — turn first, download, then run the download again with only the mirror — is no longer needed. If you find any combination where the download does not match what you saw, that is worth reporting: it would be a new fault, not this one.
What happens to the sound, and why the file grows
The sound is never copied across. Keep it and it is re-encoded to AAC at 192 kbps, or to Opus at the same rate if the source is WebM; drop it and the audio arguments become -an, which removes the track entirely rather than silencing it. Re-encoding audio that was already lossy is a second generation, and although 192 kbps is generous enough that most people will not hear it, it is not nothing. If the sound matters and the picture does not need to be perfect, consider extracting the audio first and putting it back afterwards.
The picture is encoded with libx264 at preset ultrafast and CRF 23. Ultrafast is the fastest of the eleven speed presets and the least efficient of them: it skips most of the analysis that lets an encoder spend fewer bits on the same quality, which is the right compromise for a single browser thread and the wrong one for file size. On the test clip a 6-second 1080x1920 file of 493,466 bytes came back at 513,371 bytes after a 90-degree turn. Nothing was added to the video; it simply took more bits to store the same footage badly. Expect the same shape of result on your own clips: rotation is not a compression step, and treating it as one will disappoint you.
| Property | Rotation flag (metadata) | Re-encode (this tool) |
|---|---|---|
| Work done | A few dozen bytes rewritten | Every frame decoded, moved and re-compressed |
| Picture quality | Untouched — no pixel is decoded | One lossy generation (libx264, CRF 23, preset ultrafast) |
| Stored frame size | Unchanged — 1080×1920 stays 1080×1920 | Swapped on a quarter turn — 1080×1920 becomes 1920×1080 |
| File size | Identical to within a few bytes | Measured 493,466 → 513,371 bytes on a 6-second test clip (+4 %) |
| Shown upright by | Players that read the display matrix — not all of them do | Everything, because there is nothing left to honour |
| Audio track | Untouched | Re-encoded to AAC at 192 kbps, or removed with -an |
| Reversible | Yes — set the flag back | No — the pixels have moved and been re-compressed |
Frequently asked questions
- Is a quarter turn to the left worse than a quarter turn to the right?
- No. They are the same operation with a different parameter: transpose=1 for clockwise, transpose=2 for anticlockwise. Both move every pixel exactly once, both cost the same time, and both trigger the same single re-encode. The 180-degree button is not worse either, despite being implemented as two mirrors rather than two turns — running hflip,vflip and transpose=1,transpose=1 on the same frame produced byte-identical output, so the shortcut is exact as well as faster.
- Why did my rotated file come out bigger than the original?
- Because it was re-encoded, and the encoder settings favour speed over size. The tool uses libx264 with preset ultrafast, which does very little of the analysis a slower preset uses to squeeze the same picture into fewer bits, at a constant quality target of CRF 23. If the original was compressed by a patient encoder — a phone's hardware chip, or an editor exporting overnight — then a hurried second pass at similar quality genuinely needs more room. A 4 percent increase was measured on the test clip; a well-compressed source can grow further than that. Nothing has gone wrong; you are seeing the cost of a re-encode, which is the price of the universal-compatibility route.
- My video is upright on my phone and sideways on my computer. What should I do?
- That is the signature of a rotation flag being honoured by one program and ignored by another, which means the file is not broken. If the only program that gets it wrong is one you rarely use, leave the file alone. If it has to be right everywhere — you are uploading it, sending it to someone, or importing it into an editor that ignores flags — then re-encode it here, accepting one generation of loss in exchange for a file with nothing left to misinterpret. Do not re-encode a file that is already correct in the places that matter to you.
- Does the tool ever rotate a clip twice by accident?
- Not for the rotation itself. The ffmpeg build behind the tool applies any existing rotation flag before your filter runs and writes no flag into the output, so a quarter turn asked for on a flagged clip gives one quarter turn in total, not two. The preview agrees with the file as well: it used to compose its CSS transform in the opposite order from the filter chain, which put a quarter turn combined with exactly one mirror half a turn away from what you had approved, and that has been corrected on the preview side rather than on the output side.
- Can I rotate here without re-encoding?
- No. The tool has one path and it goes through the encoder; there is no flag-only mode and no stream-copy option. That is a deliberate choice rather than an oversight — a flag-only rotation is the operation most likely to produce a file that looks fixed on the machine you fixed it on and wrong on the machine you send it to, which is a bad outcome for a tool whose users mostly cannot check. If you specifically want the metadata route, you need a command-line tool or a container editor. If you want a file that is right everywhere without thinking about it, this is that.
Articles you may find interesting
All guides →Related tools
These four tools run ffmpeg in your browser: nothing is uploaded, and nothing here depends on a server staying up. The behaviour described was read out of each component's source and then confirmed by executing the same argument arrays against the very ffmpeg build the site ships, so it is true of the version live today and not of ffmpeg in general. Sizes and loudness figures came from short synthetic test files; your own footage will give different numbers on the same commands. Where a tool's on-screen wording and its code disagree, this article follows the code.
Sources
Spotted a mistake in this article?