[Python] Webcam Streaming with Flask
Apr. 19, 2021In this post, we will go through the steps to setup a webcam stream to your browser. This can act as the starting point for other projects such as motion detection, or object recognition.
We are going to use Flask, a micro web framework to facilitate live streaming from your webcam. Install Flask:
pip install flask
pip install imutils
Create the directory templates and the file index.html. This is where you will embed the video stream. Then create webcam_streaming.py, this will be your Flask app.
First, in order to capture the video stream from the webcam, we will use the module imutils and its VideoStream class. We initialize a VideoStream object and start the the streaming process
from imutils.video import VideoStream
vs = VideoStream(src=0).start()
time.sleep(2.0)
Next, we define the route to our index.html that will serve the video stream.
@app.route("/")
def index():
return render_template("index.html")
And here is our capture, generate method for reading in each frame of the video stream. This is also where you can execute image processing methods such as motion detection, or object recognition.
def capture(frame_count):
global vs, output_frame, lock
while True:
frame = vs.read()
frame = imutils.resize(frame, width=400)
with lock:
output_frame = frame.copy()
def generate():
global output_frame, lock
while True:
with lock:
if output_frame is None:
continue
(flag, encoded_image) = cv2.imencode(".jpg", output_frame)
if not flag:
continue
yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +
bytearray(encoded_image) + b'\r\n')
We read the next frame from our webcam with vs.read(). We also resize the frame in order to increase the performance, since smaller frame means less data that need processing.
It is often here that other image processing steps are implemented. For example, one of the most common operation is to convert the frame from RGB to a Gray scale. And then this processed frame is then passed as input to the algorithm such as performing motion detection. In our code, we simply assign the input frame to our output_frame after resizing.
The next method, generate is a JPEG generator. It grabs the output_frame, then encode the frame as a JPEG image. We are using JPEG compression to reduce load on the network and ensure faster transmission of frames. The flag is to check if compression is successful, otherwise we ignore the error frame and continue.
Finally, we serve the encoded JPEG frame as a byte array that can be consumed by a web browser.
The next route to “/video_feed” serves the JPEG frame generated from the generate method at the URL endpoint http://your_ip/video_feed.
@app.route("/video_feed")
def video_feed():
return Response(generate(),
mimetype="multipart/x-mixed/replace boundary=frame")
The final code block handles parsing command line arguments and lauching the Flask app:
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--ip", type=str, required=True, help="local ip address")
parser.add_argument("-o", "--port", type=int, required=True, help="port number of the server")
args = vars(parser.parse_args())
t = threading.Thread(target=capture, args=(
args["frame_count"],))
t.daemon = True
t.start()
app.run(host=args["ip"], port=args["port"], debug=True, threaded=True, use_reloader=False)
The index.html structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Webcam Stream</title>
</head>
<body>
<h1>Webcam Stream with Flask and OpenCV</h1>
<img src="{{ url_for('video_feed') }}" />
</body>
</html>
Open up a terminal and execute the following command:
python webcam_streaming.py -i 0.0.0.0 --port 5000