20、视频旋转与翻转:旋转90°/180°/270°、水平/垂直翻转、处理旋转元数据
视频旋转和翻转,听起来好像是个小功能。但说实话,我在实际项目中踩过的坑,有一半都跟这个有关。你想想看,手机拍的视频、监控摄像头录的素材、无人机航拍的画面……它们的朝向千奇百怪。如果不处理好旋转,播放出来就是歪的,甚至上下颠倒。
这一章,我就带你彻底搞懂FFmpeg里旋转和翻转的几种玩法。包括硬转、软转、还有元数据修正。嗯,咱们一个一个来。
旋转的基本操作:transpose 和 rotate
FFmpeg里最常用的旋转滤镜有两个:transpose 和 rotate。我个人习惯用 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里用 hflip 和 vflip 分别做水平翻转和垂直翻转。
水平翻转,就像照镜子:
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°才能正常观看。
有两种处理方式:
- 保留元数据:转码时加上
-metadata:s:v rotate=90,让播放器自己处理。 - 实际旋转画面:用
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=180。于是我直接用 transpose=2,transpose=2 做了两次逆时针旋转。结果画面是正了,但编码时间翻了一倍。后来我才发现,其实用 rotate=PI 一次就能搞定,而且性能更好。
还有一个坑:有些老旧视频的旋转元数据是写在容器级别的,不是流级别。你用 ffprobe 查不到。这时候只能靠肉眼判断,或者用 ffplay 播放时加 -vf "transpose=1" 试出来。
嗯,这里要注意:如果你批量处理大量视频,最好先写个脚本自动检测旋转元数据。否则一个一个手动调,累死你。
- 旋转用
transpose或rotate,翻转用hflip或vflip。 - 旋转元数据可以用
-metadata:s:v rotate=0清零。 - 滤镜顺序影响最终效果,先测试再批量。
- 硬转(实际旋转画面)比软转(保留元数据)更可靠。
好了,这一章的内容就到这里。旋转和翻转其实不难,但细节很多。你只要记住:先查元数据,再决定用硬转还是软转,最后别忘了测试。这样基本不会出问题。