I have a programm, that starts many processes and gets videoframes from one of them. The frames are in a multiprocessing queue and I can access them in the main program at any time.
Now I want to implement a flask webserver, that runs as a seperate process, started by the main process.
The server currently looks like this:
from flask import Flask, render_template, Response
class FlaskAppWrapper(object):
def __init__(self, app, **configs):
self.app = app
self.configs(**configs)
self.frame = None
def configs(self, **configs):
for config, value in configs:
self.app.config[config.upper()] = value
def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None, methods=['GET'], *args, **kwargs):
self.app.add_url_rule(endpoint, endpoint_name, handler, methods=methods, *args, **kwargs)
def run(self, **kwargs):
self.app.run(**kwargs)
def index():
return render_template('index.html')
def gen(self):
while True:
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + self.frame + b'\r\n\r\n')
def video_feed(self):
return Response(self.gen(),
mimetype='multipart/x-mixed-replace; boundary=frame')
def run_webserver():
flask_app = Flask(__name__)
app = FlaskAppWrapper(flask_app)
app.add_endpoint('/index', 'index', app.index, methods=['GET'])
app.add_endpoint('/video_feed', 'video_feed', app.video_feed, methods=['GET'])
app.run(host='0.0.0.0',port='5000', debug=True)
In theory I only need to apply the new frame to the self.frame
value and it should work. But I dont know how to update the self.frame
, because if the app runs it blocks the process.
You might use a seperate thread to read framse from the multiprocessing queue and update self.frame
import threading
from queue import Queue
from flask import Flask, render_template, Response
class FlaskAppWrapper(object):
def __init__(self, app, **configs):
self.app = app
self.configs(**configs)
self.frame = None
self.frame_queue = Queue()
self.thread = threading.Thread(target=self._update_frame)
self.thread.daemon = True
self.thread.start()
def configs(self, **configs):
for config, value in configs:
self.app.config[config.upper()] = value
def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None, methods=['GET'], *args, **kwargs):
self.app.add_url_rule(endpoint, endpoint_name, handler, methods=methods, *args, **kwargs)
def run(self, **kwargs):
self.app.run(**kwargs)
def index(self):
return render_template('index.html')
def gen(self):
while True:
frame = self.frame_queue.get()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
def video_feed(self):
return Response(self.gen(),
mimetype='multipart/x-mixed-replace; boundary=frame')
def _update_frame(self):
while True:
frame = self.get_frame_from_queue()
self.frame = frame
def get_frame_from_queue(self):
# logic for getting a frame from the multiprocessing queue here
return frame
def run_webserver():
flask_app = Flask(__name__)
app = FlaskAppWrapper(flask_app)
app.add_endpoint('/index', 'index', app.index, methods=['GET'])
app.add_endpoint('/video_feed', 'video_feed', app.video_feed, methods=['GET'])
app.run(host='0.0.0.0', port='5000', debug=True)