You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过FFmpeg实现录制时根据相机方向自动调整视频宽高比并修正画面旋转?

如何通过FFmpeg实现录制时根据相机方向自动调整视频宽高比并修正画面旋转?

你的问题我太有共鸣了!之前用WebRTC+FFmpeg做录制时也踩过这个坑——直播时手机旋转画面自动适配,但录出来的HLS要么画面歪着要么宽高比不对,核心原因其实是WebRTC客户端会自动解析视频旋转元数据并渲染适配,但FFmpeg默认只会旋转画面,不会主动调整分辨率和宽高比

问题根源拆解

WebRTC在传输视频时,会通过SPS(序列参数集)里的旋转标记或者SEI信息把手机的旋转方向传给接收端。直播时浏览器拿到这些元数据后,会在渲染阶段自动旋转画面并调整显示宽高比,所以你看直播是正常的;但FFmpeg默认处理RTP流时,只是读取旋转标记把画面转过来,却不会修改视频的实际分辨率(比如竖屏1080x1920旋转后还是输出1080x1920,只是画面转了90度,自然就会有黑边或者拉伸)。

解决方案:用FFmpeg的autorotate滤镜动态适配

FFmpeg 4.3+新增了autorotate智能滤镜,它会自动识别视频的旋转元数据,不仅旋转画面,还会自动交换宽高分辨率,完美解决你的问题。结合你现有的命令,只需要做两处调整:

  1. 添加autorotate滤镜处理视频
  2. 移除无用的-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

火山引擎 最新活动