20、视频旋转与翻转:旋转90°/180°/270°、水平/垂直翻转、处理旋转元数据

视频旋转和翻转,听起来好像是个小功能。但说实话,我在实际项目中踩过的坑,有一半都跟这个有关。你想想看,手机拍的视频、监控摄像头录的素材、无人机航拍的画面……它们的朝向千奇百怪。如果不处理好旋转,播放出来就是歪的,甚至上下颠倒。

这一章,我就带你彻底搞懂FFmpeg里旋转和翻转的几种玩法。包括硬转、软转、还有元数据修正。嗯,咱们一个一个来。

旋转的基本操作:transpose 和 rotate

FFmpeg里最常用的旋转滤镜有两个:transposerotate。我个人习惯用 transpose,因为它简单直接,专门处理90°、180°、270°这种固定角度。

transpose 的取值有几种:

参数值 效果
0 逆时针旋转90° + 垂直翻转
1 顺时针旋转90°
2 逆时针旋转90°
3 顺时针旋转90° + 垂直翻转

举个例子,把一段竖屏视频顺时针旋转90°变成横屏:

ffmpeg -i input.mp4 -vf "transpose=1" output.mp4

如果你想旋转180°,那就连续用两次 transpose=1,或者直接用 rotate 滤镜:

ffmpeg -i input.mp4 -vf "rotate=PI" output.mp4

rotate 的参数是弧度,PI 就是180°。270°的话就是 3*PI/2。不过我个人觉得,旋转180°用 transpose 两次更直观,不容易算错。

小提示: 如果你只是临时看看效果,不想重新编码,可以用 -c copy 配合 -metadata:s:v rotate=0 来修改元数据。但注意,这只对支持旋转元数据的容器有效,比如MP4。

翻转:水平翻转和垂直翻转

翻转和旋转是两码事。翻转是镜像,旋转是转角度。FFmpeg里用 hflipvflip 分别做水平翻转和垂直翻转。

水平翻转,就像照镜子:

ffmpeg -i input.mp4 -vf "hflip" output.mp4

垂直翻转,就是上下颠倒:

ffmpeg -i input.mp4 -vf "vflip" output.mp4

我在项目中遇到过一种情况:客户给的视频是倒着拍的,但播放器里显示正常。后来发现是摄像头本身装反了,但元数据里写了一个旋转标记。这时候直接 vflip 反而会弄巧成拙。嗯,要先检查元数据。

处理旋转元数据

很多手机和相机拍摄的视频,会在文件头里写一个 rotate 元数据。播放器读取这个值后自动旋转画面。但如果你用FFmpeg直接转码,这个元数据可能会丢失,或者被错误地保留。

查看视频的旋转元数据:

ffprobe -v error -show_entries stream_side_data=rotation -of default=noprint_wrappers=1 input.mp4

如果输出是 rotation=90,说明视频需要顺时针旋转90°才能正常观看。

有两种处理方式:

  1. 保留元数据:转码时加上 -metadata:s:v rotate=90,让播放器自己处理。
  2. 实际旋转画面:用 transpose 滤镜把画面转过来,同时把元数据清零。

我个人建议用第二种。因为不是所有播放器都支持旋转元数据。我曾经遇到过一个项目,视频在VLC里正常,在Windows Media Player里就是歪的。后来我干脆把画面硬转过来,再删掉元数据,一劳永逸。

ffmpeg -i input.mp4 -vf "transpose=1" -metadata:s:v rotate=0 output.mp4
注意: 如果你用 -c copy 直接复制流,旋转元数据会被保留。但如果你重新编码了视频流,元数据可能会丢失。所以最好显式地设置 -metadata:s:v rotate=0

组合使用:旋转+翻转

有时候你需要同时做旋转和翻转。比如,把一段视频先顺时针旋转90°,再水平翻转。FFmpeg的滤镜链可以轻松搞定:

ffmpeg -i input.mp4 -vf "transpose=1, hflip" output.mp4

滤镜的顺序很重要。先旋转再翻转,和先翻转再旋转,结果完全不同。你想想看,一张纸先转90°再镜像,跟先镜像再转90°,效果能一样吗?

我一般会在测试的时候,先用一小段视频试一下,确认效果对了再批量处理。毕竟编码一次挺费时间的。

SVG流程图:旋转与翻转的核心逻辑

视频旋转与翻转核心逻辑 输入视频 有旋转元数据? 读取元数据 (rotate=90/180/270) 硬转还是软转? (实际旋转 vs 保留元数据) 输出视频

避坑指南:我曾经踩过的坑

我曾经接手过一个项目,客户说视频播放时画面是倒的。我一看元数据,rotate=180。于是我直接用 transpose=2,transpose=2 做了两次逆时针旋转。结果画面是正了,但编码时间翻了一倍。后来我才发现,其实用 rotate=PI 一次就能搞定,而且性能更好。

还有一个坑:有些老旧视频的旋转元数据是写在容器级别的,不是流级别。你用 ffprobe 查不到。这时候只能靠肉眼判断,或者用 ffplay 播放时加 -vf "transpose=1" 试出来。

嗯,这里要注意:如果你批量处理大量视频,最好先写个脚本自动检测旋转元数据。否则一个一个手动调,累死你。

核心总结:
  • 旋转用 transposerotate,翻转用 hflipvflip
  • 旋转元数据可以用 -metadata:s:v rotate=0 清零。
  • 滤镜顺序影响最终效果,先测试再批量。
  • 硬转(实际旋转画面)比软转(保留元数据)更可靠。

好了,这一章的内容就到这里。旋转和翻转其实不难,但细节很多。你只要记住:先查元数据,再决定用硬转还是软转,最后别忘了测试。这样基本不会出问题。

公众号:蓝海资料掘金营,微信deep3321