如何使用FFmpeg将视频旋转180°?


69

录制时我有一个旋转了180°的视频。可以使用FFmpeg纠正此问题吗?


您是否要在播放过程中将其翻转或以正确方向重新编码?
Mxx

@Mxx我正在考虑重新编码,但是在播放过程中您指的是什么?
路易(Louis)

使用ffmpeg作为解码后端的媒体播放器也可以利用其所有过滤器。请参见此屏幕截图ffdshow-tryout.sourceforge.net/images/front1.png “偏移和翻转”过滤器。另请参见stackoverflow.com/questions/3937387/rotating-videos-with-ffmpeg
Mxx

哦,好,酷。那对我有用,但我也想分享。我将看一下SO问题。
路易(Louis)

5
这个问题的措词和标题确实令人困惑。垂直翻转视频与将视频旋转180度不同(与垂直翻转水平翻转相同)。根据接受的答案,我正在编辑以指定旋转。目前,使用ffmpeg垂直翻转视频会对Google结果造成污染。
杰森·C

Answers:


102

原版的旋转的


tl; dr

ffmpeg 会自动旋转视频,除非:

  • 您的输入不包含旋转元数据
  • ffmpeg太老了

旋转元数据

某些视频(例如来自iPhone的视频)在物理上并未翻转,但包含视频流显示矩阵辅助数据或旋转元数据。有些播放器会忽略这些元数据,有些则不会。请参考ffmpeg控制台输出,以查看您的输入是否具有此类元数据:

$ ffmpeg -i input.mp4
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Duration: 00:00:05.00, start: 0.000000, bitrate: 43 kb/s
    Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p, 320x240 [SAR 1:1 DAR 4:3], 39 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
      rotate          : 180
    Side data:
      displaymatrix: rotation of -180.00 degrees

自动旋转

ffmpeg 会根据任何现有的视频流旋转元数据自动对视频进行物理旋转。

从2015年5月2日开始,您需要一个包含提交1630224的构建,才能使用自动旋转功能。

ffmpeg -i input.mp4 -c:a copy output.mp4

要禁用此行为,请使用该-noautorotate选项。


如果输入内容不包含元数据,或者您输入的内容过ffmpeg

您将必须使用过滤器来旋转视频,并且如果存在任何旋转元数据,则必须将其删除,如以下示例所示:

例子

使用,ffmpeg您可以选择三种使用视频滤镜旋转180°的方法。

hflipvflip

ffmpeg -i input.mp4 -vf "hflip,vflip,format=yuv420p" -metadata:s:v rotate=0 \
-codec:v libx264 -codec:a copy output.mkv

transpose

ffmpeg -i input.mp4 -vf "transpose=2,transpose=2,format=yuv420p" \
-metadata:s:v rotate=0 -codec:v libx264 -codec:a copy output.mp4

rotate

该滤镜可以旋转到任意角度,并以弧度为单位而不是度。本示例将旋转π/ 1弧度或180°:

ffmpeg -i input.mp4 -vf "rotate=PI:bilinear=0,format=yuv420p" \
-metadata:s:v rotate=0 -codec:v libx264 -codec:a copy output.mp4

您可以改用度数。一度等于π/ 180弧度。因此,如果您想旋转45°:

ffmpeg -i input.mp4 -vf "rotate=45*(PI/180),format=yuv420p" \
-metadata:s:v rotate=0 -codec:v libx264 -codec:a copy output.mp4

使用rotate滤镜时,应关闭双线性插值(使用bilinear=0)以将角度除以90,否则可能会显得模糊。


笔记

  • 过滤需要编码。这些示例进行H.264视频输出。有关获得所需质量的指导,请参阅FFmpeg H.264视频编码指南

  • 色度二次采样。我将其包括在内,format=yuv420p因为这ffmpeg将尝试最小化或避免色度二次采样(取决于编码器,输入,ffmpeg版本等)。从纯技术角度来讲,这是一种良好的行为,但是大多数播放器与更多的“高级”色度子采样方案不兼容。这与使用相同-pix_fmt yuv420,但位于过滤链中很方便。

  • 复制音频。-codec:a copy选项将流式复制(重新混合)而不是编码。如果您只想操作视频,则没有理由重新编码音频(除非您想转换为其他音频格式)。由于编码非常耗时,因此可以节省时间,并且可以保留音频质量。


播放时旋转

另外,您可以在播放时旋转并避免重新编码。ffplay会自动旋转:

ffplay input.mp4

如果没有displaymatrix辅助数据或旋转元数据,则可以使用过滤器:

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

...或参考您最喜欢的球员。像VLC这样的大多数值得使用的播放器都具有此功能。


得到 ffmpeg

较旧的ffmpeg版本不包含过滤功能。请参阅FFmpeg下载页面,以获取多个选项,包括适用于Linux,OS X和Windows的便捷构建,或参阅FFmpeg Wiki获取ffmpeg逐步编译指南


谢谢,我刚尝试完-vf vflip,它就像一种魅力。但这是重新编码。我不确定我在读对吗。您是说-vf hflip,vflip不会重新编码吗?
路易(Louis)

@Louis ffmpeg要求您在使用视频和音频过滤器时重新编码。但是,ffplay如我的第二个示例所示,在回放过程中也可以使用许多过滤器。
llogan

啊,没注意到这是一个不同的程序。
路易(Louis)

我想知道是否还有其他方法可以保持视频质量-codec:v libx264?可以ffmpeg仅使用相同的编码而无需用户尝试弄清楚吗?
2013年

1
@Louis rotate使用弧度而不是度作为单位。我认为人们对学位更加熟悉,因此我尝试在示例中展示如何使用学位。一度等于π/ 180弧度。因此,如果您想旋转45°,只需使用rotate="45*(PI/180)"
llogan 2013年

7

FFMPEG 在2015年的v2.7版本中将默认行为更改为使用“旋转”元数据自动旋转输入视频源。

如果您知道您的脚本或命令将永远无法在2.7之前的ffmpeg版本上运行,则最简单的解决方案是删除基于元数据的所有自定义轮换。

对于其他情况,您可以通过保留自定义的旋转代码并添加-noautorotate标志来适应将来的需求(在当时仍在维护的旧版本中支持此功能)。


2

使用ffmpeg作为解码后端的媒体播放器也可以利用其所有过滤器。使用“偏移和翻转”过滤器查看此屏幕截图。在此处输入图片说明

另外,如果您想重新编码视频,请在Stackoverflow上查看使用FFmpeg旋转视频


1
不幸的是,据我所知,使用FFmpeg旋转视频中transpose引用的滤镜不会旋转180°。
llogan

1
@LordNeckbeard不是直接的,但是您可以将两个transpose过滤器链接在一起以达到效果。
evilsoup

1
@evilsoup啊,是的,我没有想到。空间推理很难;我们去买东西吧。随时用示例更新我的答案。
llogan 2013年

1

以下是一个bash脚本,它将输出具有“ fixedFiles”下目录结构的文件。它可以转换和旋转iOS视频并转码AVI。该脚本依赖于同时安装了exiftoolffmpeg

#!/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

1

我被要求对其进行编辑,以作为文本的开头,指出我最终找到的解决方案是在文本结尾。因此,最后您将找到两个连续的ffmpeg命令,这些命令已成功将我的视频旋转到正确的方向。之前的文字旨在提供尽可能多的信息,因为我看到其他信息由于缺乏信息而被拒绝。无论如何,我希望这对使用ffmpeg的人有所帮助。在我看来,ffmpeg中的hflip和vflip的目的至少是令人困惑的,并且与我的预期相反。

merlin.mov文件是我在iphone上拍摄的视频的副本,该视频首先上传到Dropbox,然后下载到运行Ubuntu的笔记本电脑:

    $ uname -a
    Linux gazelle 3.13.0-135-generic #184-Ubuntu SMP
    Wed Oct 18 11:55:51 UTC 2017 x86_64 x86_64 x86_64
    GNU/Linux

我知道我应该能够通过USB挂载iphone并直接复制文件,但这是行不通的。我的笔记本电脑会识别iphone已连接,但不会挂载其文件系统,并且我的iphone上没有提示“信任”笔记本电脑。

我用来从Dropbox复制到笔记本电脑的命令是这样的:

    cp ~/Dropbox/Camera\ Uploads/Video\ Nov\ 02\,\ 9\ 41\ 55\ AM.mov \
            merlin.mov

原始文件是Video 1920 x 1080编解码器HEVC / H.265帧速率30 /秒,比特率8140 kbps,音频编解码器MPEG-4 AAC音频通道立体声,采样率44100 Hz,比特率85 kbps。当我在iPhone上播放时,它的方向正确,并且声音已同步。当我在笔记本电脑上的视频中播放时,它既颠倒又水平颠倒,并且声音不同步。这是“ ffmpeg -i merlin.mov”的部分输出:

    Metadata:
    rotate          : 180
    creation_time   : 2017-11-02T14:41:55.000000Z
    handler_name    : Core Media Data Handler
    encoder         : HEVC

这是“ ffmpeg -version”输出的第一行:

ffmpeg版本3.3.3版权所有(c)2000-2017 FFmpeg开发人员

以下内容使回放在垂直和水平方向上都反转了,尽管它确实转换为MPEG-4视频(video / mp4)并同步了声音:

    ffmpeg -i merlin.mov -vf 'hflip,vflip' merlinhflipvflip.mp4

以下内容垂直翻转,因此播放是直立的,同步了声音,并转换为MPEG-4,但是水平错误地从头到尾翻转了一下(这不是错别字,我确实指定了“ hflip”):

    ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4

以下内容将水平方向翻转为正确的方向,但将播放倒置:

    ffmpeg -i merlin.mov -vf 'vflip' merlinvflip.mp4

以下似乎没有任何作用:

    ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4
    ffmpeg -i merlinhflip.mp4 -vf 'vflip' merlin2stepA.mp4

我也根据在superuser.com上找到的命令尝试了此操作。它成功地同步了声音,并转换为MPEG-4,但是水平和垂直方向仍然不正确:

    ffmpeg -i merlin.mov \
            -vf "rotate=PI:bilinear=0,format=yuv420p" \
            -metadata:s:v rotate=0 -codec:v libx264 \
            -codec:a copy merlinrotate.mp4

我也尝试过这种方法,但在纠正方向方面没有用:

    ffmpeg -noautorotate -i merlin.mov merlinnoautorotate.mp4

以下两步过程终于得到了我想要的;垂直和水平翻转,声音同步,并转换为MPEG-4格式(同样,这不是拼写错误;我在两个命令中都使用了hflip):

    ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4
    ffmpeg -i merlinhflip.mp4 -vf 'hflip' merlin2stepB.mp4

很长一段时间-确实对我来说是一个答案-他只是简单地完成了解决问题的过程。
Journeyman Geek

@JourneymanGeek确实你是正确的。我现在在他的最后一段中看到以下两步过程终于得到了我想要的。好眼睛 (我确实阅读了整篇文章,但到那里时我的眼睛可能已经呆呆了)。
Twisty模仿者

做好您的答案。您做得很好,为您的答案提供了足够的细节。当您浏览站点时,请尝试观察其他好的答案如何在清晰度和细节之间取得平衡。
Twisty模仿者

0

步骤如下:

  1. 首先在QuickTime中打开您的视频文件。您可以先启动QuickTime,然后转到“文件”,然后转到“打开文件”。或者,您可以右键单击文件本身,选择“打开方式”,然后选择QuickTime。

  2. 视频打开后,单击“编辑”,然后直接在下面找到“旋转”和“翻转”选项

  3. 锁定所需的方向后,您必须使用已添加的新更改导出视频。您会在QuickTime的“文件”菜单下找到“导出”选项。

选择要导出为的文件设置,然后单击“确定”以开始导出。

导出操作完成后,您将在选择以正确方向保存文件的位置找到新文件!

整个修复过程只花了我不到5分钟的时间,但是视视频的长度而定,它可能要花费更长的时间(或更短,还是有所不同)。

博客来源


0
ffmpeg -i input.mp4 -filter:v "transpose=1,transpose=1" output.mp4

为我做了把戏。不知道为什么转置滤波器不能立即旋转180度,但是可以旋转。查看文档以获取更多信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.