
当 raspberry pi 上的摄像头显示“device or resource busy”错误时,通常是因为摄像头资源被先前未正常终止的进程独占;本文提供快速诊断、强制释放及预防性配置方法,确保 picamera2 流式服务稳定运行。
当 raspberry pi 上的摄像头显示“device or resource busy”错误时,通常是因为摄像头资源被先前未正常终止的进程独占;本文提供快速诊断、强制释放及预防性配置方法,确保 picamera2 流式服务稳定运行。
该错误(RuntimeError: Failed to acquire camera: Device or resource busy)并非代码逻辑缺陷,而是典型的硬件资源抢占问题:Picamera2 在初始化时无法获取摄像头控制权,说明底层 libcamera 或 vcsm 驱动已被另一个进程(如残留的 picamera2 实例、raspistill、libcamera-hello 或未优雅退出的 Flask 应用)持续占用。
✅ 快速诊断与释放摄像头
首先检查是否有活跃的摄像头相关进程:
# 查看占用 /dev/vchiq 或摄像头设备的进程 sudo lsof /dev/vchiq sudo lsof /dev/video* # (若启用了 legacy camera stack) # 或更通用的方式:查找 libcamera/picamera2 相关进程 ps aux | grep -i "camera\|libcamera\|picamera2"
若发现残留进程(如 python3 main.py 或 libcamera-hello),直接终止:
sudo pkill -f "picamera2\|libcamera\|main.py" # 或根据 PID 精确终止(替换为实际 PID) sudo kill -9 <pid></pid>
⚠️ 注意:sudo pkill 是有效手段,但避免频繁使用 sudo reboot——虽然重启总能解决,但掩盖了资源管理问题,不利于开发调试。
?️ 修复你的代码:关键修正点
原始代码存在多处严重问题,导致资源泄漏和初始化失败:
- 变量名错误:with Picamera2() as kamera: 声明了 kamera,但后续却使用未定义的 camera;
- 缺少 start() 调用:Picamera2 必须显式调用 .start() 才能启用摄像头;
- capture_array() 用法错误:该方法不返回生成器,且不支持流式 JPEG 编码;应改用 start_and_capture_bytes() 或更推荐的 encode() + request 流式模式;
- 未配置图像编码器与输出格式:直接 capture_array(..., "jpeg") 不适用,需配置 VideoEncoder 或使用 encode()。
✅ 推荐修正后的最小可行流式服务(兼容 Picamera2 v0.5+):
import io
from picamera2 import Picamera2
from flask import Flask, Response
app = Flask(__name__)
camera = None # 全局单例,避免重复初始化
def generate_frames():
global camera
if camera is None:
camera = Picamera2()
config = camera.create_video_configuration(
main={"size": (640, 480)},
controls={"FrameRate": 18}
)
camera.configure(config)
camera.start()
try:
while True:
buffer = io.BytesIO()
camera.capture_file(buffer, format="jpeg")
buffer.seek(0)
frame = buffer.read()
yield b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + frame + b"\r\n"
except GeneratorExit:
pass # 客户端断开,安全退出
finally:
# 可选:此处不 stop,因需复用;由应用退出时统一清理
pass
@app.route("/v")
def videofeed():
return Response(generate_frames(), mimetype="multipart/x-mixed-replace; boundary=frame")
@app.teardown_appcontext
def cleanup(exception):
global camera
if camera is not None:
camera.stop()
camera.close()
camera = None
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, threaded=True, debug=False)
? 预防再次发生:最佳实践
- 始终使用 app.teardown_appcontext 或 atexit 清理资源,确保异常退出时摄像头被释放;
- 禁用系统级冲突服务:检查是否启用了 raspi-config 中的 Legacy Camera Interface(sudo raspi-config → Interface Options → Camera → Disable);
- 验证摄像头硬件连接:运行 libcamera-hello --list-cameras 确认设备识别正常;
-
升级固件与驱动:
sudo apt update && sudo apt full-upgrade -y sudo rpi-update # 谨慎使用,仅在必要时
? 总结:Device or resource busy 的本质是资源生命周期管理缺失。通过正确启动/停止流程、进程清理与代码健壮性增强,可 100% 规避该问题——无需重启,即可让摄像头随时响应新请求。











