Python中如何利用Flask将OpenCV实时视频流输出到浏览器并解决性能问题

利用 flask 将 opencv 实时视频流输出到浏览器

  • 解决了所有问题,而且不消耗性能,使用了 yield 生成器,完美解决性能问题!
  • 还会继续贡献代码,链接在底部,大哥们如果喜欢记得给个 star 哦!
  • opencv 通过 webcam 可以获取本地实时视频流,但是如果需要将视频流共享给其他机器调用,就可以将利用 flask 框架构建一个实时视频流服务器,然后其他机器可以通过向这个服务器发送请求来获取这台机器上的实时视频流。

multipart 模式

  • 想要将后一次请求得到的图片覆盖到前一次从而达到动画的效果就需要使用在 response 的时候使用 multipart 模式。Multipart response 由以下几部分组成:包含 multipart content 类型的 header,分界符号分隔的各个 part,每个 part 都具有特定的 content 类型。multipart 视频流的结构如下:
	HTTP/1.1 200 OK
    Content-Type: multipart/x-mixed-replace; boundary=frame
--frame
Content-Type: image/jpeg

<jpeg data here>
--frame
Content-Type: image/jpeg

<jpeg data here>
...

在这里插入图片描述

这里解决了一次只能被一台机器查看的局限性

  • 问题已解决
  • 如果视频流一直存在的话,这个 app 能输出视频流的的客户端的数量和 web worker 的数量相同,在 debug 模式下,这个数量是 1,也就是说只有一个浏览器上能够看到视频流输出。如果要克服这种局限的话,使用基于协同网络服务的框架比如 gevent,可以用一个 worker 线程服务多个客户端。不过问题已经解决,可以使用各种姿势食用

已解决

  • 新增功能
  • 这里增加了登录与退出登录功能
  • 还增加了视频的录制
  • 还会```继续贡献代码完善项目``!!!
  • 地址 : Github 项目地址
  • 如果觉得小弟的项目不错,麻烦给个 star 喽!
  • 附上登录页面截图 在这里插入图片描述

Python中如何利用Flask将OpenCV实时视频流输出到浏览器并解决性能问题

8 回复

多谢捧场!!


要在Flask中通过OpenCV输出实时视频流到浏览器并保证性能,核心是使用生成器函数和multipart/x-mixed-replace响应。下面是一个完整可运行的示例:

from flask import Flask, Response
import cv2

app = Flask(__name__)

def generate_frames():
    # 打开摄像头
    camera = cv2.VideoCapture(0)
    
    while True:
        success, frame = camera.read()
        if not success:
            break
        
        # 压缩图像以减少传输数据量
        _, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 70])
        frame_bytes = buffer.tobytes()
        
        # 生成MJPEG格式的帧
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
    
    camera.release()

@app.route('/video_feed')
def video_feed():
    return Response(generate_frames(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/')
def index():
    return '''
    <html>
      <head>
        <title>实时视频流</title>
      </head>
      <body>
        <h1>实时视频流</h1>
        <img src="/video_feed" width="640" height="480">
      </body>
    </html>
    '''

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, threaded=True)

关键点说明:

  1. 生成器函数generate_frames()使用yield持续输出视频帧,避免阻塞主线程
  2. MJPEG格式:通过multipart/x-mixed-replace实现流式传输,浏览器会自动更新图像
  3. 图像压缩:使用JPEG压缩(质量70%)显著减少传输数据量
  4. 线程支持threaded=True确保并发请求处理

性能优化要点:

  • 调整cv2.imencode()的JPEG质量参数(70是个平衡点)
  • 考虑降低分辨率:在camera.read()后添加frame = cv2.resize(frame, (640, 480))
  • 对于高并发场景,可以考虑使用消息队列或WebSocket

一句话建议: 用生成器流式传输压缩后的JPEG帧是平衡性能和实时性的最佳方案。

欢迎大佬们过来查看!!

用 jpeg 流,这是何等奢侈的行为。。。

这是 flask 作者的教程写法套了个 ui ?

并不知道作者是谁。。。。。。。。。那里跟他的一样??

回到顶部