Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a video that was recorded upside down. Is it possible to correct this with FFmpeg?

share|improve this question
    
Are you asking about flipping it during a playback or re-encoding with correct orientation? –  Mxx Apr 5 '13 at 6:37
    
@Mxx I was thinking re-encoding, but what did you mean by during playback? –  Louis Apr 5 '13 at 6:38
    
Media players that use ffmpeg as a decoding backend can also utilize all of its filters. See this screenshot ffdshow-tryout.sourceforge.net/images/front1.png "Offset and flip" filter. Also see stackoverflow.com/questions/3937387/rotating-videos-with-ffmpeg –  Mxx Apr 5 '13 at 6:44
    
Oh okay, cool. That would work for me, but I also want to share it. I'll take a look at the SO question. –  Louis Apr 5 '13 at 6:46

3 Answers 3

up vote 18 down vote accepted

Using ffmpeg you have a choice of three video filters to rotate 180°.

normal rotated Normal and rotated images.

hflip and vflip

ffmpeg -i input.mp4 -vf "hflip,vflip,format=yuv420p" -codec:v libx264 \
-preset medium -crf 23 -codec:a copy output.mkv

Notes

Filtering requires re-encoding. The above example encodes with x264. See the FFmpeg and x264 Encoding Guide for guidance on getting the quality you want.

I included format=yuv420p since, depending on your input, ffmpeg can output other pixel formats when using this encoder. The is technically the correct behavior, but most players are incompatible with more "advanced" pixel formats. This is the same as using -pix_fmt yuv420, but is conveniently in the filterchain.

The -codec:a copy option will copy the audio from the input to the output instead of re-encoding. There is no reason to re-encode the audio if you just want to manipulate the video only. This will save time since encoding is time consuming and it will preserve the quality of the audio.

transpose

ffmpeg -i input.mp4 -vf "transpose=2,transpose=2" -codec:a copy output.mp4

rotate

This filter can rotate to any arbitrary angle and uses radians as a unit instead of degrees. This example will rotate π/1 radians, or 180°:

ffmpeg -i input.mp4 -vf "rotate=PI:bilinear=0" -codec:a copy output.mp4

You can use degrees instead. One degree is equal to π/180 radians. So if you want to rotate 45°:

ffmpeg -i input.mp4 -vf "rotate=45*(PI/180)" -codec:a copy output.mp4

When using rotate the bilinear interpolation should be turned off (by using bilinear=0) for angles divisible by 90 – otherwise it may look blurry.

Rotate upon playback

Alternatively you can rotate upon playback and avoid re-encoding:

ffplay -vf "hflip,vflip" -i input.mp4

...or refer to your favorite player. Most players worth using have this capability.

Getting ffmpeg

Older builds of ffmpeg do not include filtering capabilities. See the FFmpeg download page for several options including convenient builds for Linux, OS X, and Windows, or refer to the FFmpeg Wiki for step-by-step ffmpeg compile guides.

share|improve this answer
    
Thanks, I just finished trying -vf vflip and it worked like a charm. But it was a re-encode. I'm not sure if I'm reading you right. Are you saying -vf hflip,vflip won't re-encode? –  Louis Apr 5 '13 at 6:52
    
@Louis ffmpeg requires that you re-encode when using video and audio filters. However, ffplay can also utilize many of the filters during playback as shown in my second example. –  LordNeckbeard Apr 5 '13 at 6:55
    
Ah, didn't notice it was a different program. –  Louis Apr 5 '13 at 6:57
    
I wonder if there's a way of preserving video quality other than -codec:v libx264? Can ffmpeg just use the same encoding without user trying to figure it out? –  Sadi Oct 3 '13 at 10:15
    
@Sadi No. You must re-encode when using filters, but that does not mean it has to look bad. See the FFmpeg and x264 Encoding Guide and use the lowest -crf value that still looks good to you (a good range is ~18-24), or if in a hurry just use -crf 18. –  LordNeckbeard Oct 3 '13 at 16:10

Media players that use ffmpeg as a decoding backend can also utilize all of its filters. See this screenshot with "Offset & flip" filter. enter image description here

Alternatively, if you want to re-encode your video, check out Rotating videos with FFmpeg on Stackoverflow.

share|improve this answer
1  
Unfortunately the transpose filter referenced in Rotating videos with FFmpeg will not rotate 180° as far as I can tell. –  LordNeckbeard Apr 5 '13 at 7:06
    
@LordNeckbeard not directly, but you can chain two transpose filters together to achieve the effect. –  evilsoup Apr 5 '13 at 8:56
1  
@evilsoup Ah, yes, I didn't think of that. Spatial reasoning is hard; let's go shopping. Feel free to update my answer with an example. –  LordNeckbeard Apr 7 '13 at 2:17

Following is a bash script which will output the files with the directory structure under "fixedFiles". It transforms and rotates iOS videos and transcodes AVIs. The script relies on having installed both exiftool and ffmpeg.

#!/bin/bash

# rotation of 90 degrees. 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
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
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.