如何通过FFmpeg实现录制时根据相机方向自动调整视频宽高比并修正画面旋转?
如何通过FFmpeg实现录制时根据相机方向自动调整视频宽高比并修正画面旋转?
你的问题我太有共鸣了!之前用WebRTC+FFmpeg做录制时也踩过这个坑——直播时手机旋转画面自动适配,但录出来的HLS要么画面歪着要么宽高比不对,核心原因其实是WebRTC客户端会自动解析视频旋转元数据并渲染适配,但FFmpeg默认只会旋转画面,不会主动调整分辨率和宽高比。
问题根源拆解
WebRTC在传输视频时,会通过SPS(序列参数集)里的旋转标记或者SEI信息把手机的旋转方向传给接收端。直播时浏览器拿到这些元数据后,会在渲染阶段自动旋转画面并调整显示宽高比,所以你看直播是正常的;但FFmpeg默认处理RTP流时,只是读取旋转标记把画面转过来,却不会修改视频的实际分辨率(比如竖屏1080x1920旋转后还是输出1080x1920,只是画面转了90度,自然就会有黑边或者拉伸)。
解决方案:用FFmpeg的autorotate滤镜动态适配
FFmpeg 4.3+新增了autorotate智能滤镜,它会自动识别视频的旋转元数据,不仅旋转画面,还会自动交换宽高分辨率,完美解决你的问题。结合你现有的命令,只需要做两处调整:
- 添加
autorotate滤镜处理视频 - 移除无用的
-movflags参数(这个是给MP4容器用的,HLS用TS容器不需要)
修改后的FFmpeg命令参数
let commandArgs = [ "-loglevel", "info", "-protocol_whitelist", "pipe,udp,rtp", "-fflags", "+genpts+discardcorrupt", "-reinit_filter", "1", // 必须保留!动态调整分辨率时需要重新初始化滤镜链 "-strict", "-2", "-f", "sdp", "-i", "pipe:0", "-map", "0:v:0", "-vf", "autorotate", // 核心新增:自动处理旋转+适配宽高比 "-c:v", "libx264", "-b:v", "1500k", "-profile:v", "high", "-level:v", "4.1", "-pix_fmt", "yuv420p", "-g", "30", "-map", "0:a:0", "-c:a", "aac", "-b:a", "128k", "-f", "hls", "-hls_time", "4", "-hls_list_size", "0", "-hls_flags", "split_by_time", `${filePath}.m3u8` ];
关键参数说明
-vf "autorotate":这个滤镜会自动检测视频的旋转角度(0/90/180/270度),旋转画面的同时交换宽高分辨率,比如90度旋转后,原来的1080x1920会变成1920x1080,完美匹配横屏的宽高比。-reinit_filter 1:当手机旋转导致分辨率变化时,FFmpeg需要重新初始化滤镜链才能适配新的分辨率,这个参数必须保留,否则滤镜可能失效。- 移除
-movflags:HLS是基于TS分片的,这个MP4专属参数完全没用,删掉避免潜在问题。
额外优化建议(可选)
如果想提升HLS播放的切换流畅度,可以加-flags +cgop,让每个TS分片都以关键帧开头,这样从直播切到录制或者切换分片时不会卡顿:
// 在-libx264参数前添加 "-flags", "+cgop",
问题现象回顾
- 录制视频异常表现:
- 1.1 竖屏录制:画面正常
- 1.2 向左横屏录制:画面旋转90度,但宽高比仍为竖屏,出现黑边
- 1.3 向右横屏录制:画面旋转90度,宽高比未适配
- 直播视频正常表现:
- 2.1 竖屏直播:画面正常
- 2.2 横屏直播:浏览器自动解析旋转元数据,调整宽高比显示
备注:内容来源于stack exchange,提问作者jestrabikr




