如何将FastAPI接收的MP4二进制内容加载为NumPy数组?
将FastAPI接收的MP4二进制内容直接转为NumPy数组(无需磁盘写入)
不需要把二进制内容写入磁盘再读取,你可以用内存流配合视频处理库直接完成转换,以下是几种可行方案:
方案1:使用scikit-video + BytesIO
scikit-video的FFmpegReader支持读取类文件对象,用BytesIO把二进制内容包装成内存流即可:
from io import BytesIO import skvideo.io import numpy as np # 假设contents是FastAPI接收的MP4二进制数据 video_stream = BytesIO(contents) # 初始化FFmpegReader,指定输入格式为mp4 reader = skvideo.io.FFmpegReader(video_stream, inputdict={'-f': 'mp4'}) # 逐帧读取并拼接成NumPy数组 videodata = [] for frame in reader.nextFrame(): videodata.append(frame) videodata = np.array(videodata)
转换后的videodata形状为(帧数, 高度, 宽度, 3),和skvideo.io.vread的输出格式完全一致。
方案2:使用ffmpeg-python(推荐,灵活性更高)
ffmpeg-python是FFmpeg的Python绑定,可以直接处理内存中的视频流,解码效率更高:
import ffmpeg import numpy as np from io import BytesIO # 将二进制内容转为内存流 video_stream = BytesIO(contents) # 第一步:获取视频的宽高信息(用于后续数组重塑) probe = ffmpeg.probe(video_stream.getvalue()) video_info = next(s for s in probe['streams'] if s['codec_type'] == 'video') width = int(video_info['width']) height = int(video_info['height']) # 第二步:通过FFmpeg解码内存中的视频流,输出为raw RGB格式 raw_video, _ = ( ffmpeg .input('pipe:', format='mp4') .output('pipe:', format='rawvideo', pix_fmt='rgb24') .run(input=video_stream.getvalue(), capture_stdout=True) ) # 第三步:将原始二进制数据转为NumPy数组 videodata = np.frombuffer(raw_video, np.uint8).reshape([-1, height, width, 3])
方案3:使用OpenCV + BytesIO
如果项目已经依赖OpenCV,可以用以下方式处理(需要确保OpenCV编译时包含FFmpeg支持):
import cv2 import numpy as np from io import BytesIO # 将二进制内容转为NumPy字节数组 video_bytes = np.frombuffer(contents, dtype=np.uint8) # 通过内存管道读取视频 cap = cv2.VideoCapture() cap.open('pipe:', cv2.CAP_FFMPEG) cap.write(video_bytes) # 逐帧读取 videodata = [] while cap.isOpened(): ret, frame = cap.read() if not ret: break # OpenCV默认返回BGR格式,如需转为RGB可执行:frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) videodata.append(frame) videodata = np.array(videodata) cap.release()
注意事项
- 所有方案都需要系统安装FFmpeg(scikit-video、ffmpeg-python、OpenCV的视频解码都依赖FFmpeg)。
- 安装对应Python库:
- scikit-video:
pip install scikit-video - ffmpeg-python:
pip install ffmpeg-python - OpenCV:
pip install opencv-python
- scikit-video:
- 如果视频使用特殊编码,需要在输入参数中指定对应编码(比如
inputdict={'-vcodec': 'h265'})。 - 处理大视频时,建议逐帧处理而非一次性加载到NumPy数组,避免内存溢出。
内容的提问来源于stack exchange,提问作者Yonatan
相关产品推荐
相关产品推荐

