Reputation: 21105
I have been trying to figure out how to rotate videos with FFmpeg. I am working with iPhone videos taken in portrait mode. I know how to determine the current degrees of rotation using MediaInfo (excellent library, btw) but I'm stuck on FFmpeg now.
From what I've read, what you need to use is a vfilter option. According to what I see, it should look like this:
ffmpeg -vfilters "rotate=90" -i input.mp4 output.mp4
However, I can't get this to work. First, -vfilters doesn't exist anymore, it's now just -vf. Second, I get this error:
No such filter: 'rotate'
Error opening filters!
As far as I know, I have an all-options-on build of FFmpeg. Running ffmpeg -filters shows this:
Filters:
anull Pass the source unchanged to the output.
aspect Set the frame aspect ratio.
crop Crop the input video to x:y:width:height.
fifo Buffer input images and send them when they are requested.
format Convert the input video to one of the specified pixel formats.
hflip Horizontally flip the input video.
noformat Force libavfilter not to use any of the specified pixel formats
for the input to the next filter.
null Pass the source unchanged to the output.
pad Pad input image to width:height[:x:y[:color]] (default x and y:
0, default color: black).
pixdesctest Test pixel format definitions.
pixelaspect Set the pixel aspect ratio.
scale Scale the input video to width:height size and/or convert the i
mage format.
slicify Pass the images of input video on to next video filter as multi
ple slices.
unsharp Sharpen or blur the input video.
vflip Flip the input video vertically.
buffer Buffer video frames, and make them accessible to the filterchai
n.
color Provide an uniformly colored input, syntax is: [color[:size[:ra
te]]]
nullsrc Null video source, never return images.
nullsink Do absolutely nothing with the input video.
Having the options for vflip and hflip are great and all, but they just won't get me where I need to go. I need to the ability to rotate videos 90 degrees at the very least. 270 degrees would be an excellent option to have as well. Where have the rotate options gone?
Upvotes: 591
Views: 453070
Reputation: 4774
If you don't want to re-encode your video and your player can handle rotation metadata, you can just change the rotation in the metadata using FFmpeg with the flag display_rotation
with the values 0
, 90
, 180
and 270
:
ffmpeg -display_rotation 90 -i input.mp4 -codec copy output.mp4
Older versions of FFmpeg that doesn't support the flag display_rotation
can modify the metada using this flags:
ffmpeg -i input.mp4 -map_metadata 0 -metadata:s:v rotate="90" -codec copy output.mp4
Upvotes: 271
Reputation: 1069
If you're getting a "Codec is experimental but experimental codecs are not enabled" error use this :
ffmpeg -i inputFile -vf "transpose=1" -c:a copy outputFile
Happened with me for some .mov file with aac audio.
Upvotes: 9
Reputation: 8741
By default, the ffmpeg.exe rotate filter may cut images. In order to keep the original window width and height, to rotate 90° counterclockwise, one can use this:
ffmpeg.exe -i infilename -vf rotate=-PI/2:oh=iw:ow=ih outfilename
By adding :oh=iw:ow=ih
, it specifies that [out window width] = [input window height], [out window width] = [input window height]. This is equivalent to -vf transpose=2, rotating without image cutting.
Here:
iw: input width
ih: input height
ow: output width
oh: output height
Please see 11.210 rotate.
Upvotes: 3
Reputation: 7110
I had the same problem as the OP, getting the No such filter: 'rotate'
error, even though the rotate filter shows as supported in --filters
.
I needed to rotate by an arbitrary angle, and so all the current answers which are alternatives to rotating by a multiple of 90 degrees didn't work. I figured out that the syntax for -vf
requires spaces around the tokens, which is contrary to the official documentation.
Changing:
-vf 'rotate=1.23'
to
-vf 'rotate = 1.23'
got it to work for me.
Full example:
ffmpeg.exe -i input.mp4 -vf "rotate = 3.0 , crop = 1920:1080" out.mp4
For what it's worth, this is on FFmpeg version 4.3.2.
Upvotes: 3
Reputation: 1225
Since the FFmpeg transpose command is very slow, use the command below to rotate a video by 90 degrees clockwise.
Fast command (without encoding):
ffmpeg -i input.mp4 -c copy -metadata:s:v:0 rotate=270 output.mp4
For full video encoding (slow command, does encoding):
ffmpeg -i inputFile -vf "transpose=1" -c:a copy
Upvotes: 3
Reputation: 1144
For me it works like this:
Rotate clockwise
ffmpeg -i "path_source_video.mp4" -filter:v "transpose=1" "path_output_video.mp4"
Rotate counterclockwise
ffmpeg -i "path_source_video.mp4" -filter:v "transpose=0,transpose=1,transpose=0" -acodec copy "path_output_video.mp4"
The package I use is zeranoe.
Upvotes: 1
Reputation: 622
An additional solution with a different approach from the last mentioned solutions, is to check if your camera driver supports the v4l2 camera controls (which is very common).
In the terminal, just type:
v4l2-ctl -L
If your camera driver supports the v4l2 camera controls, you should get something like this (the list below depends on the controls that your camera driver supports):
contrast (int) : min=0 max=255 step=1 default=0 value=0 flags=slider
saturation (int) : min=0 max=255 step=1 default=64 value=64 flags=slider
hue (int) : min=0 max=359 step=1 default=0 value=0 flags=slider
white_balance_automatic (bool) : default=1 value=1 flags=update
red_balance (int) : min=0 max=4095 step=1 default=0 value=128 flags=inactive, slider
blue_balance (int) : min=0 max=4095 step=1 default=0 value=128 flags=inactive, slider
exposure (int) : min=0 max=65535 step=1 default=0 value=885 flags=inactive, volatile
gain_automatic (bool) : default=1 value=1 flags=update
gain (int) : min=0 max=1023 step=1 default=0 value=32 flags=inactive, volatile
horizontal_flip (bool) : default=0 value=0
vertical_flip (bool) : default=0 value=0
And if you are lucky it supports horizontal_flip and vertical_flip.
Then all you need to do is to set the horizontal_flip by:
v4l2-ctl --set-ctrl horizontal_flip=1
Or the vertical_flip by:
v4l2-ctl --set-ctrl vertical_flip=1
And then you can call your video device to capture a new video (see example below), and the video will be rotated/flipped.
ffmpeg -f v4l2 -video_size 640x480 -i /dev/video0 -vcodec libx264 -f mpegts input.mp4
Of course that if you need to process an already existing video, then this method is not the solution you are looking for.
The advantage in this approach is that we flip the image in the sensor level, so the sensor of the driver already gives us the image flipped, and that's saves the application (like FFmpeg) any further and unnecessary processing.
Upvotes: 8
Reputation: 113
Smartphone: Recorded a video in vertical format
We want to send it to a website it was 90° to the left (counterclockwise, landscape format). Hmm.
ffmpeg -i input.mp4 -vf "rotate=0" output.mp4
does it. I got the vertical format back again.
Debian 10 (Buster): ffmpeg --version
Output:
ffmpeg version 4.1.4-1~deb10u1 Copyright (c) 2000-2019 the FFmpeg developers
Upvotes: 2
Reputation: 9434
To rotate the picture clockwise you can use the rotate filter, indicating a positive angle in radians. With 90 degrees equating with π/2, you can do it like so:
ffmpeg -i in.mp4 -vf "rotate=PI/2" out.mp4
For counterclockwise, the angle must be negative
ffmpeg -i in.mp4 -vf "rotate=-PI/2" out.mp4
The transpose filter will work equally well for 90 degrees, but for other angles this is a faster or the only choice.
Upvotes: 30
Reputation: 305
This script that will output the files with the directory structure under "fixedFiles". At the moment it is fixed to MOV files and will execute a number of transformations depending on the original "rotation" of the video. It works with iOS captured videos on a Mac running Mac OS X v10.9 (Mavericks), but it should be easily exportable. It relies on having installed both ExifTool and FFmpeg.
#!/bin/bash
# Rotation of 90 degrees. It will have to concatenate.
#ffmpeg -i <originalfile> -metadata:s:v:0 rotate=0 -vf "transpose=1" <destinationfile>
#/VLC -I dummy -vvv <originalfile> --sout='#transcode{width=1280,vcodec=mp4v,vb=16384,vfilter={canvas{width=1280,height=1280}:rotate{angle=-90}}}:std{access=file,mux=mp4,dst=<outputfile>}\' vlc://quit
# Allowing blanks in file names
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
# Bit Rate
BR=16384
# Where to store fixed files
FIXED_FILES_DIR="fixedFiles"
#rm -rf $FIXED_FILES_DIR
mkdir $FIXED_FILES_DIR
# VLC media player
VLC_START="/Applications/VLC.app/Contents/MacOS/VLC -I dummy -vvv"
VLC_END="vlc://quit"
#############################################
# Processing of MOV in the wrong orientation
for f in `find . -regex '\./.*\.MOV'`
do
ROTATION=`exiftool "$f" |grep Rotation|cut -c 35-38`
SHORT_DIMENSION=`exiftool "$f" |grep "Image Size"|cut -c 39-43|sed 's/x//'`
BITRATE_INT=`exiftool "$f" |grep "Avg Bitrate"|cut -c 35-38|sed 's/\..*//'`
echo Short dimension [$SHORT_DIMENSION] $BITRATE_INT
if test "$ROTATION" != ""; then
DEST=$(dirname ${f})
echo "Processing $f with rotation $ROTATION in directory $DEST"
mkdir -p $FIXED_FILES_DIR/"$DEST"
if test "$ROTATION" == "0"; then
cp "$f" "$FIXED_FILES_DIR/$f"
elif test "$ROTATION" == "180"; then
# $(eval $VLC_START \"$f\" "--sout="\'"#transcode{vfilter={rotate{angle=-"$ROTATION"}},vcodec=mp4v,vb=$BR}:std{access=file,mux=mp4,dst=\""$FIXED_FILES_DIR/$f"\"}'" $VLC_END )
$(eval ffmpeg -i \"$f\" -vf hflip,vflip -r 30 -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\")
elif test "$ROTATION" == "270"; then
$(eval ffmpeg -i \"$f\" -vf "scale=$SHORT_DIMENSION:-1,transpose=2,pad=$SHORT_DIMENSION:$SHORT_DIMENSION:\(ow-iw\)/2:0" -r 30 -s "$SHORT_DIMENSION"x"$SHORT_DIMENSION" -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\" )
else
# $(eval $VLC_START \"$f\" "--sout="\'"#transcode{scale=1,width=$SHORT_DIMENSION,vcodec=mp4v,vb=$BR,vfilter={canvas{width=$SHORT_DIMENSION,height=$SHORT_DIMENSION}:rotate{angle=-"$ROTATION"}}}:std{access=file,mux=mp4,dst=\""$FIXED_FILES_DIR/$f"\"}'" $VLC_END )
echo ffmpeg -i \"$f\" -vf "scale=$SHORT_DIMENSION:-1,transpose=1,pad=$SHORT_DIMENSION:$SHORT_DIMENSION:\(ow-iw\)/2:0" -r 30 -s "$SHORT_DIMENSION"x"$SHORT_DIMENSION" -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\"
$(eval ffmpeg -i \"$f\" -vf "scale=$SHORT_DIMENSION:-1,transpose=1,pad=$SHORT_DIMENSION:$SHORT_DIMENSION:\(ow-iw\)/2:0" -r 30 -s "$SHORT_DIMENSION"x"$SHORT_DIMENSION" -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\" )
fi
fi
echo
echo ==================================================================
sleep 1
done
#############################################
# Processing of AVI files for my Panasonic TV
# Use ffmpegX + QuickBatch. Bitrate at 16384. Camera res 640x424
for f in `find . -regex '\./.*\.AVI'`
do
DEST=$(dirname ${f})
DEST_FILE=`echo "$f" | sed 's/.AVI/.MOV/'`
mkdir -p $FIXED_FILES_DIR/"$DEST"
echo "Processing $f in directory $DEST"
$(eval ffmpeg -i \"$f\" -r 20 -acodec libvo_aacenc -b:a 128k -vcodec mpeg4 -b:v 8M -flags +aic+mv4 \"$FIXED_FILES_DIR/$DEST_FILE\" )
echo
echo ==================================================================
done
IFS=$SAVEIFS
Upvotes: 3
Reputation: 709
Alexy's answer almost worked for me except that I was getting this error:
timebase 1/90000 not supported by MPEG 4 standard, the maximum admitted value for the timebase denominator is 65535
I just had to add a parameter (-r 65535/2733) to the command and it worked. The full command was thus:
ffmpeg -i in.mp4 -vf "transpose=1" -r 65535/2733 out.mp4
Upvotes: 2
Reputation: 9750
Rotate 90 clockwise:
ffmpeg -i in.mov -vf "transpose=1" out.mov
For the transpose parameter you can pass:
0 = 90° counterclockwise and vertical flip (default)
1 = 90° clockwise
2 = 90° counterclockwise
3 = 90° clockwise and vertical flip
Use -vf "transpose=2,transpose=2"
for 180 degrees.
Make sure you use a recent FFmpeg version from here (a static build will work fine).
Note that this will re-encode the audio and video parts. You can usually copy the audio without touching it, by using -c:a copy
. To change the video quality, set the bitrate (for example with -b:v 1M
) or have a look at the H.264 encoding guide if you want VBR options.
A solution is also to use this convenience script.
Upvotes: 971
Reputation: 19
Unfortunately, the Ubuntu version of FFmpeg does support video filters.
You need to use avidemux or some other editor to achieve the same effect.
In the programmatic way, mencoder has been recommended.
Upvotes: 1
Reputation: 129
ffmpeg -vfilters "rotate=90" -i input.mp4 output.mp4
won't work, even with the latest source...
You must change the order:
ffmpeg -i input.mp4 -vf vflip output.mp4
It works fine.
Upvotes: 12
Reputation: 231
I came across this page while searching for the same answer. It is now six months since this was originally asked and the builds have been updated many times since then. However, I wanted to add an answer for anyone else that comes across here looking for this information.
I am using Debian 6.0 (Squeeze) and FFmpeg version from those repositories.
The man page for FFmpeg states the following use:
ffmpeg -i inputfile.mpg -vf "transpose=1" outputfile.mpg
The key being that you are not to use a degree variable, but a predefined setting variable from the man page.
0=90CounterCLockwise and Vertical Flip (default)
1=90Clockwise
2=90CounterClockwise
3=90Clockwise and Vertical Flip
Upvotes: 23
Reputation: 21497
Use transpose
. Like (from the other answer):
ffmpeg -i input -vf transpose=2 output
If you are using an old version, you have to update FFmpeg if you want to use the transpose feature, as it was added in October 2011.
The FFmpeg download page offers static builds that you can directly execute without having to compile them.
Upvotes: 105