如何在烧瓶路由中接收网络摄像头视频流?

Posted

技术标签:

【中文标题】如何在烧瓶路由中接收网络摄像头视频流?【英文标题】:How to receive a webcam video stream in flask route? 【发布时间】:2019-09-18 12:04:09 【问题描述】:

我正在开发一个具有客户端(html&js)和服务器(flask)的应用程序 客户端将打开网络摄像头(HTML5 api)-> 向服务器发送视频流-> 服务器将返回其他带有 json/文本流的流

我不想做池化。

我正在研究有关视频流的内容,但我发现的每篇文章和互联网示例都使用 OpenCV 的网络摄像头或本地视频,并且确实获取了实时网络摄像头的视频并发送到服务器。

这是我找到的主要示例

服务器:


    from flask import Flask, render_template, Response
    import cv2

    app = Flask(__name__)

    camera = cv2.VideoCapture(0)  # I can't use a local webcam video or a local source video, I must receive it by http in some api(flask) route

    def gen_frames():  # generate frame by frame from camera
        while True:
            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('/video_feed')
    def video_feed():
        """Video streaming route. Put this in the src attribute of an img tag."""
        return Response(gen_frames(),
                        mimetype='multipart/x-mixed-replace; boundary=frame')


    @app.route('/')
    def index():
        """Video streaming home page."""
        return render_template('index.html')


    if __name__ == '__main__':
        app.run(host='0.0.0.0')

客户: camera.js

          //--------------------
          // GET USER MEDIA CODE
          //--------------------
              navigator.getUserMedia = ( navigator.getUserMedia ||
                                 navigator.webkitGetUserMedia ||
                                 navigator.mozGetUserMedia ||
                                 navigator.msGetUserMedia);

          var video;
          var webcamStream;

          function startWebcam() 
            if (navigator.getUserMedia) 
               navigator.getUserMedia (

                  // constraints
                  
                     video: true,
                     audio: false
                  ,

                  // successCallback
                  function(localMediaStream) 
                      video = document.querySelector('video');
                     video.src = window.URL.createObjectURL(localMediaStream);
                     webcamStream = localMediaStream;
                  ,

                  // errorCallback
                  function(err) 
                     console.log("The following error occured: " + err);
                  
               );
             else 
               console.log("getUserMedia not supported");
              
          


          //---------------------
          // TAKE A SNAPSHOT CODE
          //---------------------
          var canvas, ctx;

          function init() 
            // Get the canvas and obtain a context for
            // drawing in it
            canvas = document.getElementById("myCanvas");
            context = canvas.getContext('2d');
          

          function snapshot() 
             // Draws current image from the video element into the canvas
            context.drawImage(video, 0,0, canvas.width, canvas.height);
            webcamStream.stop();
            var dataURL = canvas.toDataURL('image/jpeg', 1.0);
            document.querySelector('#dl-btn').href = dataURL;

            $.ajax(
              type: "POST",
              contentType: false,
              cache: false,
              processData: false,
              async: false,
              url: "/upload",
              data:  
                imgBase64: dataURL
              
            ).done(function(o) 
              console.log('saved'); 
      // If you want the file to be visible in the browser 
      // - please modify the callback in javascript. All you
      // need is to return the url to the file, you just saved 
      // and than put the image in your browser.
    );

          

index.html

    <!DOCTYPE html>
    <html>

      <head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> 
      <script src="camera.js"></script> 

      </head>
      <body onload="init();">
        <h1>Take a snapshot of the current video stream</h1>
       Click on the Start WebCam button.
         <p>
        <button onclick="startWebcam();">Start WebCam</button>
        <button type="submit" id="dl-btn" href="#" download="participant.jpeg" onclick="snapshot();">Take Snapshot</button> 
        </p>
        <video onclick="snapshot(this);" width=400 height=400 id="video" controls autoplay></video>
      <p>

            Screenshots : <p>
          <canvas  id="myCanvas"  ></canvas>  
      </body>
    </html>

另一个问题是我无法使用快照进行池化,我需要将视频流发送到服务器以在那里处理帧。

有人知道如何将 WebCam 视频流发送到烧瓶吗?

tks

【问题讨论】:

【参考方案1】:

您可能应该在流生成器周围使用stream_with_context 来流式传输您的响应。您无法返回常规响应,因为有任何东西告诉客户端不要关闭连接。

https://flask.palletsprojects.com/en/1.1.x/api/#flask.stream_with_context

【讨论】:

【参考方案2】:

嘿,这可能会帮助你在烧瓶中播放视频

#!/usr/bin/env python
from flask import Flask, render_template, Response
from camera import Camera

app = Flask(__name__)

@app.route('/')
def index():
return render_template('index.html')

def gen(camera):
while True:
    frame = camera.get_frame()
    yield (b'--frame\r\n'
           b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

    @app.route('/video_feed')
    def video_feed():
    return Response(gen(Camera()),
                mimetype='multipart/x-mixed-replace; boundary=frame')

    if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

【讨论】:

以上是关于如何在烧瓶路由中接收网络摄像头视频流?的主要内容,如果未能解决你的问题,请参考以下文章

如何在立体声的同一窗口中并排显示 2 个网络摄像头视频?

如何最有效地向服务器发送连续的帧流

如何从相机(或网络摄像头)在 python 中捕获视频(和音频)

译如何使用Vue捕获网络摄像头视频

如何使用 Java 从网络摄像头获取视频和音频流?

如何在 iOS 和 macOS 上的 Safari 中使用网络摄像头录制视频?