我的视频在录制时旋转了 180°。可以使用 FFmpeg 纠正这个问题吗?
答案1
总结
ffmpeg
将自动旋转视频,除非:
- 您的输入不包含旋转元数据
- 你
ffmpeg
太老了
旋转元数据
有些视频(例如来自 iPhone 的视频)没有进行物理翻转,但包含视频流 displaymatrix 端数据或旋转元数据。有些播放器会忽略这些元数据,有些则不会。请参阅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° 旋转。
hflip
和vflip
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
您可以使用度数来代替。1 度等于 π/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
,对于可被 90 整除的角度,应关闭双线性插值(通过使用bilinear=0
),否则可能会看起来很模糊。
笔记
过滤需要编码。这些示例制作 H.264 视频输出。请参阅FFmpeg H.264 视频编码指南以获得您想要的质量的指导。
色度子采样。我包括了,
format=yuv420p
因为ffmpeg
将尝试最小化或避免色度二次采样(取决于编码器、输入、ffmpeg
版本等)。从纯技术意义上讲,这是良好的行为,但大多数播放器与更“高级”的色度二次采样方案不兼容。这与使用相同-pix_fmt yuv420
,但位于过滤链。复制音频。该
-codec:a copy
选项将流复制(重新复用)而不是编码。如果您只想处理视频,则没有必要重新编码音频(除非您想转换为不同的音频格式)。这将节省时间,因为编码很耗时,并且可以保持音频的质量。
播放时旋转
或者,您可以在播放时旋转并避免重新编码。ffplay
将自动旋转:
ffplay input.mp4
如果没有显示矩阵侧数据或旋转元数据,那么您可以使用过滤器:
ffplay -vf "hflip,vflip" -i input.mp4
...或者参考您最喜欢的播放器。大多数值得使用的播放器(如 VLC)都具有此功能。
获取ffmpeg
ffmpeg 的旧版本不包含过滤功能。请参阅FFmpeg 下载页面,了解包括 Linux、OS X 和 Windows 的便捷版本在内的多个选项,或者参考FFmpeg 维基为了一步一步的 ffmpeg 编译指南。
答案2
FFmpeg 在 v2.7 版本中将默认行为更改为使用“旋转”元数据自动旋转输入视频源2015年。
如果您知道您的脚本或命令永远不会在 FFmpeg 2.7 之前的版本上运行,最简单的解决方案是删除任何基于元数据的自定义旋转。
对于其他情况,您可以通过保留自定义轮换代码并添加标志来确保未来安全-noautorotate
(这在当时仍维护的旧版本中受支持)。
答案3
ffmpeg -i input.mp4 -filter:v "transpose=1,transpose=1" output.mp4
对我来说很管用。我不确定为什么转置过滤器不提供一次旋转 180 度的可能性,但无论如何。
查看文档了解更多信息。
答案4
以下是一个 Bash 脚本,它将输出“fixedFiles”下具有目录结构的文件。它转换和旋转 iOS 视频并转码AVI文件。脚本依赖于已安装Exif工具和 FFmpeg。
#!/bin/bash
# Rotation by 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
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 resolution 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