如何将cv2处理的numpy帧列表转为st.video可接收的视频字节数据
实现帧序列转Streamlit可识别的视频字节流方案
你可以通过内存临时文件方案绕开磁盘落盘逻辑,全程在内存中完成帧序列到视频字节的转换,可直接传给st.video渲染。
方案1:基于OpenCV实现(无需额外安装依赖)
你现有的OpenCV栈可以直接适配,搭配Python内置的tempfile模块完成内存写入:
import tempfile import cv2 import numpy as np import streamlit as st vid = st.file_uploader( label="Upload Video", type=["mov", "mp4"] ) if st.button("Load"): v = VideoClassInAnotherFile(vid) frames: list[np.ndarray] = v.process() # 该函数通过opencv完成帧处理操作 # ========== 以下为TODO部分的实现 ========== height, width = frames[0].shape[:2] # 建议直接从原视频读取真实帧率替换硬编码25,避免播放速度异常 fps = 25 # MP4通用编码 fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 创建内存级临时文件,默认超过阈值才会落盘,可通过max_size参数调整 with tempfile.SpooledTemporaryFile(suffix='.mp4', delete=True) as temp_file: out = cv2.VideoWriter( temp_file.name if hasattr(temp_file, 'name') else None, fourcc, fps, (width, height) ) for frame in frames: # 如果你的帧处理逻辑中把BGR转成了RGB,需要解开下面注释转回OpenCV要求的BGR格式 # frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) out.write(frame) out.release() # 移动文件指针到开头读取完整字节 temp_file.seek(0) byte_data = temp_file.read() # ========== 实现结束 ========== st.video(byte_data)
Windows环境如果出现临时文件无权限访问的报错,可以把
SpooledTemporaryFile替换为tempfile.NamedTemporaryFile,新增参数delete=False,完成读取后手动调用os.unlink(temp_file.name)删除文件即可。
方案2:基于imageio实现(跨平台兼容性更好)
如果OpenCV方案存在编码、临时文件权限类兼容问题,推荐用封装了ffmpeg的imageio实现,代码更简洁:
- 先安装依赖:
pip install imageio-ffmpeg
- 替换TODO部分为如下代码:
from io import BytesIO import imageio.v3 as iio byte_data = iio.imwrite( "<bytes>", # 直接指定输出为字节 frames, fps=25, codec="h264", # 通用H.264编码,浏览器兼容性最好 format="mp4", # 如果帧为OpenCV原生BGR格式,新增下面参数 # pixelformat="bgr24" )
注意事项
- 需保证所有处理后的帧尺寸完全一致,否则会写入失败
- 优先选择H.264/mp4v编码,是所有主流浏览器都支持的格式,可被
st.video直接识别 - 帧率建议从原上传视频中读取后复用,避免播放速度和原视频不一致
内容的提问来源于stack exchange,提问作者Austin Ulfers
相关产品推荐
相关产品推荐

