如何用python-ffmpeg提取多视频流MOV文件的帧?
解决ffmpeg-python指定输入视频流的问题
你遇到的问题是因为stream_index并非ffmpeg.input()的有效参数——这个参数是ffmpeg用于输出流索引指定的选项,不能用来选择输入流。要读取MOV文件中指定的视频流,需要用map选项来定位目标流。
修正后的代码示例
import numpy as np from PIL import Image import ffmpeg from pathlib import Path # 替换为你的文件路径和保存目录 file = "your_input.mov" video_streams_dir = Path("./output_frames") video_streams_dir.mkdir(exist_ok=True) # 探测文件中的流信息 probe = ffmpeg.probe(file) video_streams = [stream for stream in probe['streams'] if stream['codec_type'] == 'video'] for stream in video_streams: stream_idx = stream["index"] # 获取当前流的分辨率(不同流可能分辨率不同) width = stream['width'] height = stream['height'] # 构建ffmpeg命令:选择指定视频流,输出为rgb24原始帧 out, _ = ( ffmpeg .input(file) .map(f'0:v:{stream_idx}') # 0代表第一个输入文件,v代表视频流,stream_idx为目标流索引 .output('pipe:', format='rawvideo', pix_fmt='rgb24') .run(capture_stdout=True, quiet=True) # quiet=True避免打印ffmpeg日志 ) # 将原始字节转为numpy数组 video = np.frombuffer(out, np.uint8).reshape([-1, height, width, 3]) # 创建当前流的保存目录 stream_dir = video_streams_dir / str(stream_idx) stream_dir.mkdir(exist_ok=True) # 逐帧保存为JPEG for i in range(video.shape[0]): frame = Image.fromarray(video[i,...]) frame.save(stream_dir / f"frame_{i:04d}.jpeg")
关键说明
- 使用
.map(f'0:v:{stream_idx}')来选择输入文件中的指定视频流:0表示第一个输入文件(如果只有一个输入源就用0)v表示筛选视频流stream_idx是从probe中获取的流索引值
- 每个视频流的分辨率可能不同,必须单独从stream信息中读取
width和height,否则会导致reshape失败 - 加入
quiet=True可以避免ffmpeg在运行时输出冗余日志,保持控制台整洁
内容的提问来源于stack exchange,提问作者Dolev Shapira
相关产品推荐
相关产品推荐

