Learn how to use Dash Bio for next-gen sequencing & quality control. 🧬 Register for the Oct 27 webinar.

Concurrent web video streaming with Dash (and Flask)

I’m trying to achieve something similar to this : Does Dash support opencv video from webcam?

I want to be able to stream videos from a server to clients, but having an individual video stream for each user, not a shared one. Is there a way to do that with Plotly Dash ?

Thank you

Hi @Clockzarb, Dash is meant to work well with concurrent sessions as long as you don’t use global variables (see https://dash.plot.ly/sharing-data-between-callbacks, “Why global variables will break you app”). So if you have a dropdown or input component to choose the URL of the stream it should work well. Did you give it a try? You can check it by opening two different browsers on your local machine for example.

Implementing Streaming With Flask

Flask provides native support for streaming responses through the use of generator functions. A generator is a special function that can be interrupted and resumed. Consider the following function:

def gen():
    yield 1
    yield 2
    yield 3

This is a function that runs in three steps, each returning a value. Describing how generator functions are implemented is outside the scope of this article, but if you are a bit curious the following shell session will give you an idea of how generators are used:

>>> x = gen()
>>> x
<generator object gen at 0x7f06f3059c30>
>>> next(x)
>>> next(x)
>>> next(x)
>>> next(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

You can see in this simple example that a generator function can return multiple results in sequence. Flask uses this characteristic of generator functions to implement streaming.

The example below shows how using streaming it is possible to generate a large data table, without having to assemble the entire table in memory:

from flask import Response, render_template
from app.models import Stock

def generate_stock_table():
    yield render_template('stock_header.html')
    for stock in Stock.query.all():
        yield render_template('stock_row.html', stock=stock)
    yield render_template('stock_footer.html')

def stock_table():
    return Response(generate_stock_table())

In this example, you can see how Flask works with generator functions. A route that returns a streamed response needs to return a Response object that is initialized with the generator function. Flask then takes care of invoking the generator and sending all the partial results as chunks to the client.

For this particular example if you assume Stock.query.all() returns the result of a database query as an iterable, then you can generate a potentially large table one row at a time, so regardless of the number of elements in the query the memory consumption in the Python process will not grow larger and larger due to having to assemble a large response string.

Otherwise, you should create your own video streaming platform with specific plugins for different business modules here find out the top global service provider to make with advanced features here https://hackernoon.com/how-to-create-a-video-on-demand-website-like-netflix-youtube-f238fbcd5e09

Hope it will be useful for on demand project developers and content distributors