修改前代码:
# camera = cv2.VideoCapture(0) # camera = cv2.VideoCapture('rtsp://admin:admin@192.16.19.2:554/cam/realmonitor?channel=1&subtype=1') def gen_frames(): frame_count = 0 while True: camera = cv2.VideoCapture('rtsp://admin:admin@192.168.19.12:554/cam/realmonitor?channel=1&subtype=1') # size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)), int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))) success, frame = camera.read() # read the camera frame if not success: break else: 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') # concat frame one by one and show result @app.route('/mv') def mv_test(): return ''' <body><div class="container"> <div class="row"> <div class="col-lg-8 offset-lg-2"> <h3 class="mt-5">Live Streaming</h3> <img src="{}" width="1280px" height="720px"> <video src="{}" width="100%" type="video/mp4" controls autoplay="autoplay" muted="muted" loop playsinline='' controls="controls">您的浏览器不支持 video 标签 </video> </div> </div> </div> </body> '''.format(url_for('video_feed'), url_for('video_feed')) @app.route('/video_feed') def video_feed(): return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame') if __name__ == '__main__': app.run(port=5002)
这段代码,虽可以显示出画面,但掉帧严重,且会出现中断的情况,不能持久播放。
将代码封装到类中后,效果明显改善。且不中断,能持续播放。
具体的原因,还需要再思考一下。
这也是flask + opencv 实现视频转图片流,到网站前端显示的完整实现示例代码:
from flask import Flask, render_template, Response, url_for import cv2 import time class VideoCamera(object): # 搞成类的模式就不卡了, def __init__(self): # 通过opencv获取实时视频流 self.video = cv2.VideoCapture('rtsp://admin:hk888888@192.168.19.12:554/cam/realmonitor?channel=1&subtype=1') def __del__(self): self.video.release() def get_frame(self): success, image = self.video.read() # 在这里处理视频帧 cv2.putText(image, "hello", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0)) # # 因为opencv读取的图片并非jpeg格式,因此要用motion JPEG模式需要先将图片转码成jpg格式图片 ret, jpeg = cv2.imencode('.jpg', image) return jpeg.tobytes() app = Flask(__name__) @app.route('/') # 主页 def index(): # jinja2模板,具体格式保存在index.html文件中 return ''' <body><div class="container"> <div class="row"> <div class="col-lg-8 offset-lg-2"> <h3 class="mt-5">Live Streaming</h3> <img src="{}" width="1280px" height="720px" style="margin:50px auto"> </div> </div> </div> </body> '''.format(url_for('video_feed')) # <video src="{}" width="100%" type="video/mp4" controls autoplay="autoplay" muted="muted" loop playsinline='' controls="controls">您的浏览器不支持 video 标签 </video> def gen(camera): while True: start_t = time.time() frame = camera.get_frame() #print('{0}'.format(time.time()-start_t)) # 使用generator函数输出视频流, 每次请求输出的content类型是image/jpeg yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n') @app.route('/video_feed') # 这个地址返回视频流响应 def video_feed(): return Response(gen(VideoCamera()), mimetype='multipart/x-mixed-replace; boundary=frame') if __name__ == '__main__': app.run(host='0.0.0.0', debug=True, port=5000)