使用Flask的视频流:
使用 Flask 的视图函数将后台线程从摄像头捕获的最新视频帧以 Motion-JPEG 流传输到 Web 浏览器。
问题描述:
当用户首次请求存在流式响应的URL界面
时,从摄像头捕获最新视频帧的后台线程就开始了,但之后它永远不会停止,即使你离开了这个url界面
,当用户再次请求这个url界面
时,后台会重新创建一个线程,尝试从摄像头捕获最新视频帧。
此时相机被多个线程同时访问(当请求不止一次发送到API时,多个线程开始读取摄像机),摄像头无法处理。另一方面,再次进入的这个url界面
请求的帧没有正确地接收到,并抛出错误:
[mpjpeg @ 0000017a86f524a0] Expected boundary '--' not found, instead found a line of 82 bytes
解决办法:
处理此后台线程的一种有效的方法是仅在有查看者的情况下使其运行,以便在没有人连接时可以关闭相机。
子线程
class RTSCapture(cv2.VideoCapture):
# ...
last_access = 0 # 最后一个url页面访问相机的时间
# ...
def recv_frame(self):
"""子线程读取最新视频帧方法"""
"""子线程存活时,此函数一直在while循环里,捕获最新视频帧"""
while self._reading and self.isOpened():
ok, frame = self.read()
# 如果没有任何url页面访问视屏帧
# 0.4 秒钟之后杀死线程,
if time.time()-self.last_access>= 0.4:
break
#self._cur_frame存放最新视频帧
if not ok: break
self._cur_frame = frame
self._reading = False
# 杀死线程
self.release()
def read2(self):
"""url页面获取子线程捕获的最新视频帧
返回结果格式与 VideoCapture.read() 一样
"""
frame = self._cur_frame
self._cur_frame = None
# 记录url页面访问相机的最新时间
self.video_last_access = time.time()
return frame is not None, frame
url网页访问相机
def gen(url):
rtscap = RTSCapture.create(url,"http://")
rtscap.start_read()
while rtscap.isStarted():
# read_latest_frame() 替代 read(),访问相机
ok, frame = rtscap.read2()
# 帧处理代码写这里
result_frame = rtscap.video(frame)
# 使用generator函数输出视频流, 每次请求输出的content类型是image/jpeg
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + result_frame + b'\r\n\r\n')
# ---------------