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

如何通过Flask利用localStorage切换Python项目中的OpenCV摄像头

解决方案

要实现通过localStorage切换摄像头,核心是把前端选中的摄像头索引传递给Flask后端,让gen_frame使用该索引初始化视频捕获。以下是具体修改步骤:

1. 修改Flask路由与gen_frame函数

让video_feed路由接收摄像头索引参数,并传递给gen_frame:

修改attendance_taker.py中的gen_frame

def gen_frame(camera_index=0):
    # 传入camera_index参数,默认使用0号摄像头
    cap = cv2.VideoCapture(int(camera_index)) 
    face_recognizer = Face_Recognizer()

    try:
        while True:
            success, frame = cap.read()
            if not success:
                break

            face_recognizer.process(frame)

            ret, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
    finally:
        # 确保摄像头资源被释放
        cap.release()

修改app.py中的路由

from flask import request  # 需要导入request模块

@app.route('/video_feed')
def video_feed():
    # 从查询参数中获取摄像头索引,默认0
    camera_index = request.args.get('camera', 0)
    return Response(gen_frame(camera_index), mimetype='multipart/x-mixed-replace; boundary=frame')

2. 修改前端JavaScript逻辑

在切换摄像头时更新video标签的src(带上摄像头索引参数),同时保留localStorage存储逻辑:

window.addEventListener("DOMContentLoaded", function () {
    var webcamSelect = document.getElementById("webcamSelect");
    var videoElement = document.getElementById("videoFeed"); // 对应HTML中的video标签id

    // 更新视频流的函数
    function updateVideoFeed(cameraIndex) {
        videoElement.src = `/video_feed?camera=${cameraIndex}`;
    }

    webcamSelect.addEventListener("change", function () {
        var selectedWebcamIndex = this.selectedIndex;
        localStorage.setItem("selectedWebcamIndex", selectedWebcamIndex);
        updateVideoFeed(selectedWebcamIndex);
    });

    navigator.mediaDevices
        .enumerateDevices()
        .then((devices) => {
            var videoDevices = devices.filter(
                (device) => device.kind === "videoinput",
            );
            videoDevices.forEach((device, index) => {
                var option = document.createElement("option");
                option.value = index;
                option.text = device.label || `Webcam ${index + 1}`;
                webcamSelect.appendChild(option);
            });

            var selectedWebcamIndex = localStorage.getItem("selectedWebcamIndex");
            if (selectedWebcamIndex) {
                webcamSelect.selectedIndex = selectedWebcamIndex;
                updateVideoFeed(selectedWebcamIndex);
            } else {
                // 默认加载0号摄像头
                updateVideoFeed(0);
            }
        })
        .catch((error) => {
            console.error("Error enumerating devices:", error);
        });
});

3. 前端HTML对应标签

确保页面中有用于渲染视频流和选择摄像头的元素:

<video id="videoFeed" autoplay muted></video>
<select id="webcamSelect"></select>

关键说明

  • 前端通过修改video的src,将摄像头索引作为查询参数传递给Flask路由
  • Flask路由接收参数后,传递给gen_frame初始化对应摄像头
  • 每次切换摄像头时会重新创建VideoCapture实例,确保使用新设备索引
  • 添加finally块释放摄像头资源,避免资源泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 00:31:03