0


Python flask 视频流返回问题 & RTSP断流问题解决

Python flask 视频流返回问题 & RTSP断流问题解决

参考【项目心得 の 二】在开发时如果有具体想法需提前和前端沟通,寻求方便的解决方案

1、视频流返回结果用GET,不要POST

今天与康哥对接接口时,发现一个问题:**前端(Vue)使用

POST

接口上传文件到后台(flask),我在后台处理后返回一个视频帧给前端,但是这时的前端界面上不能正常显示图片,然后让康哥通过

GET

接口测在线视频,这个是可以正常显示的**,主要原因是在线检测时接口用的是

GET

类型,并且是**后台通过图片生成器来更新前端的

image_url

中的图片**,是的前端的

img src

属性会根据后端链接的变化实现前端图片的更新;而

POST

请求只提交一次,不能获取实时的视频流

'''舱门检测: 基于图片/视频二进制文件/网络摄像头地址'''@manholeB.route('/predict_manhole', methods=['GET','POST'])defpredict_manhole():
    username ="wang"if(request.method =='POST'):#图片上传(type=0),视频上传(type=1)type=int(request.form.get("type"))
        frame = frameDetect_handler.handle_frame_with_type(username,request,type,manhole_detector)return Response(frame, mimetype='multipart/x-mixed-replace; boundary=frame')else:#网络摄像头路径(type=2)type=int(request.args.get("type"))
        status =int(request.args.get("status"))#是否开启摄像头
        frame = frameDetect_handler.handle_frame_with_type(username,request,type, manhole_detector)return Response(frame, mimetype='multipart/x-mixed-replace; boundary=frame')# return jsonify({'code': 400, 'msg': '操作失败:请使用post方法'})

这里的

handler.handle_frame_with_type()

返回的是视频每一帧的二进制图片。

defhandle_frame_with_type(self,username,request,type,detector, status=True):"""
        @param username: 哪个用户执行该操作
        @param type: 要检测的类型,0:图片,1:视频,2:摄像头, 并向视图返回处理后的结果, type=int
        @param handler: 检测器,舱门检测器,烟雾检测器,人脸检测器
        @param status: 是否开启摄像头:false-关闭,true-打开
        @return:
        """#清空用户之前的操作
        self.container_map.clearUserCamera(username)if(type== self.types['image']):return self.handle_img(request,detector)elif(type== self.types['video']):return self.handle_video(request,username,detector)elif(type== self.types['webCamera']):return self.handle_camera(request,username,detector,status)

其中

handle_video

为:

defhandle_video(self,request,username, detector):print("hello_video")
        fileStorage = request.files['videofile']
        buffer_video = fileStorage.read()#将二进制视频流保存成文件之后再用opencv读取 参考https://stackoverflow.com/questions/57865656/save-video-in-python-from-bytes
        TEMP_VIDEO_OUTPUT = os.path.join(rootPath,'temp.mp4')if os.path.isfile(TEMP_VIDEO_OUTPUT):
            os.remove(TEMP_VIDEO_OUTPUT)withopen(TEMP_VIDEO_OUTPUT,"wb")as out_file:# open for [w]riting as [b]inary
            out_file.write(buffer_video)
        camera = cv2.VideoCapture(TEMP_VIDEO_OUTPUT)#注册camera到container_map中
        self.container_map.register(username,camera)
        frame = gen_frames(camera,detector)return frame

解决方法

前端**通过将上传的图片文件封装在

formdata

中,并通过

POST

接口想要得到后台的图片处理结果**,由于

img

标签的

src

会随着

get

请求的更新而进行图片更新,所以分步解决:

  • POST接口将上传的文件保存到本地,并向前台返回带本地文件路径(file_path) 的图片/视频处理的GET接口路由(由于前端浏览器缓存问题,相同的GET地址会优先读取浏览器缓存中的数据,因此需要在GET链接上加上时间戳!!!)。'''舱门检测: 基于图片/视频二进制文件/网络摄像头地址'''@manholeB.route('/predict_manhole', methods=['GET','POST'])defpredict_manhole(): username ="wang"if(request.method =='POST'):#图片上传(type=0),视频上传(type=1)type=int(request.form.get("type")) file_path = temp_save_path file_path = frameDetect_handler.handle_frame_with_type(username,request,type,manhole_detector, file_path)#完成图片、视频上传到本地 timeStamp =str(time.mktime(time.localtime(time.time()))) data ="http://"+ ip +":"+ port +"/get_manhole_frame?type="+str(type)+"&file_path="+ file_path +"&timeStamp="+ timeStamp #返回文件访问路径return jsonify({'data': data})else:#网络摄像头路径(type=2)type=int(request.args.get("type")) frame = frameDetect_handler.handle_frame_with_type(username,request,type, manhole_detector)return Response(frame, mimetype='multipart/x-mixed-replace; boundary=frame')
  • GET接口会利用file_path参数,获取刚才前端上传的文件,通过图片生成器向前端返回图片'''predict_manhole POST请求返回的路由,用于给前端发送二进制视频流'''@manholeB.route('/get_manhole_frame', methods=['GET'])defget_manhole_frame(): username ="wang" file_path = request.args.get("file_path")type=int(request.args.get("type")) frame = frameDetect_handler.handle_frame_with_type(username, request,type, manhole_detector, file_path)# 完成图片、视频上传到本地return Response(frame, mimetype='multipart/x-mixed-replace; boundary=frame')# return jsonify({'finish' : True}) #已经检测完毕
handle_frame_with_type()

通过判断接口是

POST

还是

GET

,如果是

POST

完成文件上传,如果是

GET

则完成指定文件的检测,代码修改如下:

defhandle_frame_with_type(self,username,request,type,detector,file_path):"""
        @param username: 哪个用户执行该操作
        @param type: 要检测的类型,0:图片,1:视频,2:摄像头, 并向视图返回处理后的结果, type=int
        @param handler: 检测器,舱门检测器,烟雾检测器,人脸检测器
        @param file_path: frame写入的文件路径
        """#清空用户之前的操作
        self.container_map.clearUserCamera(username)if(type== self.types['image']):if(request.method =='POST'):#post请求进行文件上传操作return self.upload_img(request,file_path)elif(request.method =='GET'):# GET请求返回视频帧return self.handle_img(detector, file_path)elif(type== self.types['video']):if(request.method =='POST'):# post请求进行文件上传操作return self.upload_video(request,file_path)elif(request.method =='GET'):# GET请求返回视频帧return self.handle_video(username, detector, file_path)elif(type== self.types['webCamera']):return self.handle_camera(request,username,detector)

2、RTSP容易出现断流,可以设置定时器来重新创建连接

这里利用帧数求余(抽帧)来重新尝试创建连接

'''检测网络摄像头中的视频流'''defgen_frames_with_webCamera(username, container_map, webCamera_url, detector, frameDraw=1):
    camera = cv2.VideoCapture(webCamera_url)
    frame_count =0whileTrue:
        frame_count +=1# 空转且设置较低容错,避免断流if(camera.isOpened()==Falseand(frame_count % frameDraw ==0)):if(container_map.getCamera_fromUser(username)!=None):#用户将camera置为空,则无需重新创建camera
                camera = cv2.VideoCapture(webCamera_url)else:break# 一帧帧循环读取摄像头的数据# 将读取视频帧的任务交给videoStream类来处理(决定是返回单帧frame,还是count帧frames)
        success, frame = camera.read()if success and(frame_count % frameDraw ==0):# 抽帧处理
            container_map.register(username,camera)
            frame = cv2.resize(frame,(640,480))
            frame = detector.detect(frame)# frame = cv2.resize(frame, (640, 480))# 将每一帧的数据进行编码压缩,存放在memory中
            ret,buffer= cv2.imencode('.jpg', frame)

            frame =buffer.tobytes()# 使用yield语句,将帧数据作为响应体返回,content-type为image/jpegprint("webCamera detected...")yield(b'--frame\r\n'+b'Content-Type: image/jpeg\r\n\r\n'+ frame +b'\r\n')
    camera.release()
标签: flask python 后端

本文转载自: https://blog.csdn.net/qq_33934427/article/details/127360844
版权归原作者 王小希ww 所有, 如有侵权,请联系我们删除。

“Python flask 视频流返回问题 & RTSP断流问题解决”的评论:

还没有评论