You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单线程Flask实现多端口摄像头视频流推送方案问询

单线程Flask架构实现多摄像头分端口推流

核心思路

放弃多Flask实例的方案,用单线程Flask作为统一服务,搭配独立的摄像头处理线程,再通过反向代理实现不同端口对应不同摄像头流:

  • 摄像头线程负责拉流、处理帧,将最新处理后的帧存入线程安全的全局缓冲区
  • 单Flask服务提供不同路由对应每个摄像头的推流接口
  • 用反向代理(比如Nginx)把5000-5003端口分别映射到Flask的对应路由,实现用户访问不同端口看对应摄像头

代码实现

1. 摄像头处理与帧缓冲区

import cv2
import threading
from flask import Flask, Response

# 线程安全的帧缓冲区,key为摄像头ID,value为最新帧
frame_buffers = {
    "cam1": None,
    "cam2": None,
    "cam3": None,
    "cam4": None
}
buffer_locks = {
    "cam1": threading.Lock(),
    "cam2": threading.Lock(),
    "cam3": threading.Lock(),
    "cam4": threading.Lock()
}

def camera_worker(cam_id, rtsp_url):
    cap = cv2.VideoCapture(rtsp_url)
    if not cap.isOpened():
        print(f"Failed to open {cam_id} stream")
        return
    while True:
        ret, frame = cap.read()
        if not ret:
            print(f"{cam_id} stream disconnected, retrying...")
            cap.release()
            cap = cv2.VideoCapture(rtsp_url)
            continue
        # 这里替换成你的OpenCV图像处理逻辑
        processed_frame = frame
        
        # 线程安全更新缓冲区
        with buffer_locks[cam_id]:
            frame_buffers[cam_id] = processed_frame
    cap.release()

2. 单线程Flask服务

app = Flask(__name__)

def generate_frames(cam_id):
    while True:
        with buffer_locks[cam_id]:
            frame = frame_buffers[cam_id]
        if frame is None:
            continue
        # 编码为JPEG格式
        ret, buffer = cv2.imencode('.jpg', frame)
        if not ret:
            continue
        frame_bytes = buffer.tobytes()
        # 生成MJPEG流格式
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')

# 为每个摄像头定义推流路由
@app.route('/cam1/video')
def cam1_video():
    return Response(generate_frames("cam1"), mimetype='multipart/x-mixed-replace; boundary=frame')

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

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

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

if __name__ == '__main__':
    # 启动所有摄像头处理线程
    threading.Thread(target=camera_worker, args=("cam1", "rtsp://cam1_url"), daemon=True).start()
    threading.Thread(target=camera_worker, args=("cam2", "rtsp://cam2_url"), daemon=True).start()
    threading.Thread(target=camera_worker, args=("cam3", "rtsp://cam3_url"), daemon=True).start()
    threading.Thread(target=camera_worker, args=("cam4", "rtsp://cam4_url"), daemon=True).start()
    # 启动单线程Flask服务,监听5004端口(可自定义)
    app.run(host='0.0.0.0', port=5004, threaded=False)  # threaded=False确保单线程运行

3. Nginx反向代理配置

在Nginx配置文件中添加以下server块,实现不同端口映射到对应路由:

server {
    listen 5000;
    server_name 192.168.0.50;
    location / {
        proxy_pass http://127.0.0.1:5004/cam1/video;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

server {
    listen 5001;
    server_name 192.168.0.50;
    location / {
        proxy_pass http://127.0.0.1:5004/cam2/video;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

server {
    listen 5002;
    server_name 192.168.0.50;
    location / {
        proxy_pass http://127.0.0.1:5004/cam3/video;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

server {
    listen 5003;
    server_name 192.168.0.50;
    location / {
        proxy_pass http://127.0.0.1:5004/cam4/video;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

配置完成后重启Nginx,用户访问192.168.0.50:5000即可看到CAMERA1的流,以此类推。

方案优势

  1. 减少资源竞争:单线程Flask统一处理所有推流请求,避免多Flask实例同时占用CPU、内存导致的性能下降
  2. 帧复用优化:摄像头线程仅做一次图像处理,Flask直接复用缓冲区的帧编码推流,避免重复计算
  3. 线程安全保障:用Lock保护帧缓冲区的读写操作,避免多线程冲突导致的帧损坏

内容的提问来源于stack exchange,提问作者Vikrant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 23:50:22