如何通过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
相关产品推荐
相关产品推荐

