ffmpeg.probe返回meta_dict无rotate信息 如何检测视频旋转
问题原因
你本地安装的是ffmpeg 5.0.1版本,从5.x版本开始,ffmpeg将视频旋转元数据从原来的streams[x]['tags']['rotate']路径迁移到了streams[x]['side_data_list']下的rotation字段,原有代码只读取旧路径,自然无法获取到旋转参数。另外原代码硬编码取streams[0]作为视频流也存在隐患,部分封装格式会把音频流放在第一个索引位,会直接读错元数据。
修复后可直接运行的代码
import ffmpeg import cv2 def check_rotation(path_video_file): meta_dict = ffmpeg.probe(path_video_file) rotate_code = None rotation_angle = 0 # 先定位视频流,避免硬编码索引读错音视频流 video_stream = None for stream in meta_dict['streams']: if stream['codec_type'] == 'video': video_stream = stream break if not video_stream: return rotate_code # 兼容ffmpeg 4.x及更早版本:读取tags下的rotate字段 if 'rotate' in video_stream.get('tags', {}): rotation_angle = int(video_stream['tags']['rotate']) # 兼容ffmpeg 5.x及更新版本:读取side_data_list下的rotation字段 elif 'side_data_list' in video_stream: for side_data in video_stream['side_data_list']: if 'rotation' in side_data: rotation_angle = int(side_data['rotation']) break # 映射旋转角度到cv2内置旋转常量 if rotation_angle == 90: rotate_code = cv2.ROTATE_90_CLOCKWISE elif rotation_angle == 180: rotate_code = cv2.ROTATE_180 elif rotation_angle == 270 or rotation_angle == -90: rotate_code = cv2.ROTATE_90_COUNTERCLOCKWISE return rotate_code # 读取帧时自动修正方向的辅助方法 def read_corrected_frame(cap, rotate_code): ret, frame = cap.read() if ret and rotate_code is not None: frame = cv2.rotate(frame, rotate_code) return ret, frame
使用注意
- 初始化
cv2.VideoCapture后先调用check_rotation拿到旋转码,后续每次读帧后调用cv2.rotate传入旋转码做方向修正,即可解决帧倒置、横竖屏错误的问题。 - 上述代码同时兼容新旧版本ffmpeg,无需针对不同ffmpeg版本单独调整逻辑。
- 新增了视频流遍历逻辑,不会因为视频封装中音视频流的索引顺序变化读错元数据。
- 额外兼容了ffmpeg返回
-90旋转值的场景(等价于顺时针旋转270度),覆盖绝大多数手机、相机拍摄的带方向标记的视频文件。
内容的提问来源于stack exchange,提问作者Lucky Sunda
相关产品推荐
相关产品推荐

