如何在Flask中流式传输10分钟视频?实现无需全量下载即可播放
嘿,这个需求我之前做项目的时候刚好碰到过,其实核心就是让你的Flask应用支持HTTP范围请求(Range Requests)——这是浏览器实现流式播放的关键,而Flask自带的开发服务器默认不处理这个逻辑,所以换WSGI服务器是必要的,下面给你一步步捋清楚怎么做:
核心原理:为什么开发服务器不行?
浏览器要实现“边看边加载”,会向服务器发送带Range头的请求,指定要获取视频的某一段内容(比如从第1000字节到第5000字节)。但Flask的开发服务器只是用来调试的轻量服务,它会直接返回整个视频文件,不会处理Range请求,所以用户必须等完整视频下载完才能播放。
而生产级的WSGI服务器(比如Gunicorn、uWSGI)本身支持HTTP标准的范围请求处理,再配合我们在Flask里的逻辑,就能实现流式播放。
第一步:让Flask支持范围请求
你可以手动实现范围请求的处理逻辑,也可以用现成的扩展,这里给你一个手动实现的示例(更灵活,不用依赖额外包):
from flask import Flask, request, Response import os app = Flask(__name__) # 替换成你的视频文件路径 VIDEO_FILE = "./static/videos/your_10min_video.mp4" def parse_range_header(range_header, file_size): """解析Range请求头,计算要返回的字节范围""" if not range_header: return 0, file_size - 1 # 拆分Range头(格式类似:bytes=0-1024) range_part = range_header.strip().split("=")[1] start_str, end_str = range_part.split("-") start = int(start_str) if start_str else 0 end = int(end_str) if end_str else file_size - 1 # 处理超出文件大小的情况 if end >= file_size: end = file_size - 1 return start, end @app.route("/stream-video") def stream_video(): file_size = os.path.getsize(VIDEO_FILE) range_header = request.headers.get("Range") start, end = parse_range_header(range_header, file_size) content_length = end - start + 1 # 读取视频对应片段 with open(VIDEO_FILE, "rb") as f: f.seek(start) video_segment = f.read(content_length) # 设置响应头,告诉浏览器这是分段内容 headers = { "Content-Range": f"bytes {start}-{end}/{file_size}", "Accept-Ranges": "bytes", "Content-Length": str(content_length), "Content-Type": "video/mp4", } # 返回206 Partial Content响应 return Response(video_segment, status=206, headers=headers) if __name__ == "__main__": # 开发服务器仅用于测试,生产环境别用! app.run(debug=True)
第二步:部署到WSGI服务器
推荐用Gunicorn,它简单易用,是Flask生产部署的常用选择:
- 安装Gunicorn:
pip install gunicorn
- 启动服务(假设你的Flask app文件名为
app.py):
# 4个工作进程,绑定到5000端口 gunicorn --workers 4 --bind 0.0.0.0:5000 app:app
如果你的视频访问量比较大,建议再配合Nginx做反向代理,Nginx处理静态文件的效率比Flask高很多,甚至可以让Nginx直接托管视频文件,Flask只处理动态逻辑。给你一个简单的Nginx配置示例:
server { listen 80; server_name your-domain.com; # 动态请求转发给Gunicorn location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 让Nginx直接托管视频文件,自动处理范围请求 location /videos { root /path/to/your/static/folder; add_header Accept-Ranges bytes; add_header Content-Type video/mp4; } }
额外注意事项
- 视频格式:确保你的视频是MP4(H.264编码)这种支持流式播放的格式,AVI等格式不支持分段加载。
- 文件权限:确保WSGI服务器进程(比如Gunicorn的运行用户)有读取视频文件的权限。
- 测试验证:部署后用浏览器访问
/stream-video,拖动进度条,如果能直接跳转到对应位置播放,就说明成功了。
内容的提问来源于stack exchange,提问作者cubecubed
相关产品推荐
相关产品推荐

