In this article we demonstrate an easy way to stream images to the browser and iterate between them with a specific interval.
Table of Contents
- Introduction
- Reading the images
- Streaming images
- Index page
- Whole code
Introduction
We will use Python3 for this task and Flask in order to serve the HTML page and the images to the browser.
We will use the following three images from pexels and all-free-download in order to create our slideshow.
Reading the images
First, we need to read a list of images from our local computer. All images are placed inside a folder named images and is in the same directory as the python program.
import os
def get_all_images():
image_folder = 'images'
images = [img for img in os.listdir(image_folder)
if img.endswith(".jpg") or
img.endswith(".jpeg") or
img.endswith("png")]
return images
An instance from the PyCharm debugger after we call get_all_images() will be like this:
Streaming Images
For the streaming part we will define an HTTP GET endpoint using Flask and we will return a Response object with an image as content. In order the client to get different images continuously, we will use the multipart/x-mixed-replace which is a single HTTP request response model. The client should remain connected to the server the whole time the streaming process happens, otherwise a reconnection is required.
from flask import Flask, Response
app = Flask(__name__)
@app.route('/slideshow')
def slideshow():
return Response(gen(),
mimetype='multipart/x-mixed-replace; boundary=frame')
Inside the gen() function we will use the yield keyword in order to return the images. Inside the function we can use a while true in order to constantly reading a new image from disk. We would like the get_all_images() function to be inside the loop in case some images are added to the folder at runtime.
The images will be transmitted to the client at every 5 seconds. This interval can be easily altered in time.sleep() function.
Finally, using the help of an index variable we keep track which image from the array we had displayed in the latest iteration.
import time
def gen():
i = 0
while True:
images = get_all_images()
image_name = images[i]
im = open('images/' + image_name, 'rb').read()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + im + b'\r\n')
i += 1
if i >= len(images):
i = 0
time.sleep(5)
Index Page
Next, we want a starting HTTP endpoint that serves a simple HTML page to the browser. Using Flask this would look like this:
@app.route('/')
def index():
return "<html><head></head><body><h1>slideshow</h1><img src='/slideshow' style='width: 90%; height: 90%;'/>" \
"</body></html>"
As we can see from the above code we set the src of the image to the endpoint that streams the images. This way the browser will create a permanent connection with the client in order to stream the images creating a simple slideshow.
Whole Code
from flask import Flask, Response
import os
import time
app = Flask(__name__)
def gen():
i = 0
while True:
images = get_all_images()
image_name = images[i]
im = open('images/' + image_name, 'rb').read()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + im + b'\r\n')
i += 1
if i >= len(images):
i = 0
time.sleep(5)
def get_all_images():
image_folder = 'images'
images = [img for img in os.listdir(image_folder)
if img.endswith(".jpg") or
img.endswith(".jpeg") or
img.endswith("png")]
return images
@app.route('/slideshow')
def slideshow():
return Response(gen(),
mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index():
return "<html><head></head><body><h1>slideshow</h1><img src='/slideshow' style='width: 90%; height: 90%;'/>" \
"</body></html>"
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)