2

I'm trying to make a camera server that shows multiple video process streaming results through Chrome browser using Flask, OpenCV.

Problem

It can handle 6 request at most with a single browser, but I need to process more than 60 camera requests.

Things I've tried.

At first I thought CPU couldn't handle more than 6 inputs but when I request it from another browser(chrome,Firefox,Edge etc), it can handle more simultaneously. So hardware seems not to be a problem. It's somehow limiting the requests per browser. So every single browser could handle only 6 at most.

If I request more than 6 it starts processing the first 6 request and wait till one of them finishes then starts next requests. I think it's because Flask app handles process synchronously.

I've tried with thread=True options with Flask, and with gunicorn for async process. but there is no difference.

gunicorn video:app -w 81 --threads 81 -k gevent --worker-connections 1000

I have no idea why it's limited to 6 requests only. is it possible to solve this?

Here is a sample code for the project.

video.py

import cv2
from flask import Flask,request, Response


def loadVideo(video):
    cap = cv2.VideoCapture(video)

    if cap.isOpened(): # try to get the first frame
        rval, frame = cap.read()
    else:
        rval = False


    IMG_SIZE = 640
    while(1):
        rval, image = cap.read()
        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))  

        if rval==True:
            orig = image.copy()
            frame = cv2.blur(image, (3,3))

            yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n'+ cv2.imencode('.jpg', frame)[1].tostring() + b'\r\n')

        elif rval==False:
                break
    end = time.time()
    cap.release()

app = Flask(__name__)

@app.route('/')
def hello():
    return "Server Established!"

@app.route('/detect',methods = ['GET'])
def detect():
    try:
        if request.method == 'GET':
            src = request.args.get('src')
            return Response(loadVideo(src),
        mimetype = "multipart/x-mixed-replace; boundary=frame")
    except Exception as e:
        return e


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=3999, threaded=True)
  • Just an idea, but how about using some software that is more focused on video streaming like VLC? – Klaus D. Nov 26 '19 at 11:50
  • Have you already tried specifying `processes=xx` instead of `threaded=True`? Even if it won't work properly you maybe get a useful log out of it. – raphael_mav Nov 26 '19 at 11:56
  • Did you try to run the app, and not using flask server in debug mode? something like gunicorn and multiple workers for instance. – gittert Nov 26 '19 at 11:57
  • @KlausD.Well I can't because I have to use it for my web client server – Yoonseok Choi Nov 27 '19 at 00:51
  • @raphael_mav you mean this? `app.run(debug=False, host='0.0.0.0', port=3999, threaded=False, processes=20)` well didn't work for this – Yoonseok Choi Nov 27 '19 at 00:54
  • @gittert Yes I've tried with debug mode false, and already tried with gunicorn and didn't work – Yoonseok Choi Nov 27 '19 at 00:54
  • @Yoonseok Choi - `app.run(debug=False, host='0.0.0.0', port=3999, processes=20)`. I'd try this without he threaded=False argument ;) – raphael_mav Nov 27 '19 at 08:38

2 Answers2

3

It's browser's TCP connection is limited to 6 only.

reference

How to solve this

Firefox can be configured from within about:config, filter on network.http for various settings; network.http.max-persistent-connections-per-server is the one to change.

ref

But as it's browser's problem I may use different approach like creating same server with different port.

  • THANK YOU!! Lost a day debugging this trying to figure out why flask/guncorn/gevent won't take more than 6 connections! For chrome as a workaround we had multiple flask servers and iframes on a single page to show more than 6 video streams. – jahackbeth Jul 09 '21 at 11:00
0

I suggest use uwsgi and scale with workers/processes.

uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2

Jan
  • 46
  • 5