pallets/flask

Streaming data to multiple clients

Chris230291 opened this issue · 3 comments

I'm not sure if this is a bug in flask or just what is to be expected.

In the following example, if 1 VLC client connects, the stream plays back smoothly.
If 2 or more clients connect, all streams fail to play back smoothly/properly.
As soon as the client connections goes back down to 1, the stream starts to playback properly.

import subprocess
from flask import (
    Flask,
    Response,
)

app = Flask(__name__)

stream = None


@app.route("/play", methods=["GET"])
def channel():
    def createStream(ffmpegcmd):
        global stream
        print("create stream")
        stream = subprocess.Popen(
            ffmpegcmd,
            stdin=subprocess.DEVNULL,
            stdout=subprocess.PIPE,
            stderr=subprocess.DEVNULL,
        )

    def streamData():
        print("stream data")
        try:
            while True:
                chunk = stream.stdout.read(1024)
                if len(chunk) == 0:
                    break
                yield chunk
        except:
            pass

    if not stream:
        link = "https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8"

        ffmpegcmd = [
            "ffmpeg",
            "-re",
            "-i",
            link,
            "-map",
            "0",
            "-codec",
            "copy",
            "-f",
            "mpegts",
            "pipe:",
        ]

        createStream(ffmpegcmd)

    return Response(streamData(), mimetype="application/octet-stream")


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8001, debug=True)

This example code is only used to reproduce the issue.
Can anyone explain why it behaves like this?

Environment:

  • Python version: 3.11.4
  • Flask version: 2.3.2

The problem is you've used a global variable stream to manage the stream for both clients, so one client will interfere with the other as they both access it. In general, you cannot use global variables in web applications for this reason. The quick fix here would be to remove the global variable and use only local/nonlocal variables within the function, although you may want to think about a better structure for this as you continue.

Thanks for the reply.
Is there a way I can serve multiple clients with a single subprocess/instance of ffmpeg using flask?
The idea is to only have a single connection to the source server and restream it internally.
I understand ffmpeg can do this on its own, but I would like to do it in flask if possible.

The answer is likely yes, but that's outside the scope of what we can help with here. This issue tracker is for issues with the project itself. If you have questions, you can ask on our Discord or our GitHub Discussions.