Flask Response with socketIO and eventlet leads to dropped responses?

Viewed 168

I am experimenting with the code found in Miguel's tutorial on streaming jpg images with flask. part1 part2

I tried to add socketIO to the example. but I found that it leads to heavy lagging even if a monkey patch is used. I boiled down the problem to this short example seen below. If I start the socketio instance then I see in the terminal that the generator provides consecutive frames at a regular interval, but in the browser only about every second image shows up. If I use app.run(...) then everything works fine. Using socketio with async_mode="threading" also fixes the streaming.

What am I missing?

templates/index.html

<html>
  <head>
    <title>Video Streaming Demonstration</title>
  </head>
  <body>
    <h1>Video Streaming Demonstration</h1>
    <img src="{{ url_for('video_feed') }}">
  </body>
</html>

app_experient.py

import eventlet
eventlet.monkey_patch()

from importlib import import_module
import os
from flask import Flask, render_template, Response

import time
print("is_monkey_patched(time):", eventlet.patcher.is_monkey_patched(time))

from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)#, async_mode="threading")


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


def gen():
    """Video streaming generator function."""
    imgs = [open(f + '.jpg', 'rb').read() for f in ['1', '2', '3', '4', '5', '6', '7']]

    while True:
        time.sleep(1)
        i = int(time.time()) % 7
        frame = imgs[i]
        print("gen yielding", i)
        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():
    """Video streaming route. Put this in the src attribute of an img tag."""
    return Response(gen(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')


if __name__ == '__main__':
    # app.run(host='0.0.0.0', threaded=True)#, debug=True)
    socketio.run(app, host='0.0.0.0')#, debug=True)
1 Answers

I'm not sure what the issue is, but it appears to be somehow related to the use of the eventlet web server. Switching to the eventlet worker that comes with Gunicorn appears to solve the problem.

I first installed Gunicorn:

pip install gunicorn

Then started your application as follows:

gunicorn -b :5000 -k eventlet app_experiment:app
Related