1

Please help. What code would it take to make a simple text clock application with python and flask to demonstrate how flask streaming works? Ideally the app would show text time in place, overwriting on screen, from the once per second updating stream.

The clock stream is a simplified case of a real time text stream. The real underlying need is for a server to push out simultaneous video & text streams (no audio) like Miguel Grinberg's Video Streaming with Flask and to show both updates on screen on the client side. Miguel's video stream demo works. However I do not yet know how to get a simultaneous text stream to work.

I have tried the code below and there are some quirks:

  1. The html p element is just a place holder for text. It could be changed to anything that might work better.
  2. http://localhost:5000 shows '/time_feed' when I want it to instead show the time string contents of /time_feed.
  3. http://localhost:5000/time_feed shows nothing at all while the flask server is running. When the flask server is stopped all of the sudden a bunch of updates appear in the browser like:

    2018.11.01|20:29:272018.11.01|20:29:282018.11.01|20:29:292018.11.01|20:29:302018.11.01|20:29:312018.11.01|20:29:322018.11.01|20:29:33

I tried Streaming data with Python and Flask but do not understand how to apply either the javascript or jinga answers to my clock's code. I am new learning web and flask development.

app.py:

#!python3 Flask 
# streaming clock per http://flask.pocoo.org/docs/1.0/patterns/streaming

from flask import Flask, Response, render_template, url_for
from datetime import datetime
import time

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/time_feed')
def time_feed():
    def generate():
        while True:
            yield datetime.now().strftime("%Y.%m.%d|%H:%M:%S")
            time.sleep(1)
    return Response(generate(), mimetype='text')

if __name__ == '__main__':
    app.run(debug=True, threaded=True)

./templates/index.html:

<title>Clock</title>
<h1>Clock</h1>
<p>{{ url_for('time_feed') }}</p>
1
  • 1
    Using JS to poll like the accepted solution is correct in your case. But using another http client you could see your method works as well, like with curl: curl -vN "127.0.0.1:5000/time_feed" Commented Nov 8, 2019 at 22:01

2 Answers 2

3

in view you can avoid while and sleep in that example:

@app.route('/time_feed')
def time_feed():
    def generate():
        yield datetime.now().strftime("%Y.%m.%d|%H:%M:%S")  # return also will work
    return Response(generate(), mimetype='text') 

in template:

<p id="clock">Here will be date|time</p>

<script>
    var clock = document.getElementById("clock");

    setInterval(() => {
        fetch("{{ url_for('time_feed') }}")
        .then(response => {
                response.text().then(t => {clock.innerHTML = t})
            });
        }, 1000);  
</script>

in your example with video streem it is just trick, it is not solution for real video streaming, just because not provide audio. If you need for real video stream you need to use webRTC with Kurento-media-server for example. For python look on aiortc lib.

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you. That could work entirely client side. And I actually do have text data that is updating on the server that I need to push out to the client. Does this need to be combined with websockets to push text from the server or is there a way to do it with a stream? I will be pushing video and text from the server and no audio. Requirement is text must be in a seperate stream from the video.
yes you can use your method for stream video without audio, and use fetch (JS method) for update your string. With yeld functions or without.
@SpeedCoder5 you can use it without websockets, just fetch()
@SpeedCoder5 answer updated again. Yes, .text() it is promise function. It fixed.
Apparently i don't unserstand the question. My english is not well. For stream video via webRTC you shood use media server like Kurento or Janus. They allow you streaming video (from file on server, or RTP from Gstreamer or FFmpg, or RTSP from live IPcam) and they provide transport data-chanal (webRTC chanel to send/receive data like text and other). Both soluthions have "hello world" examples for simplify understanding. Note: Kurento is more frendly for Node.js users. I'm use Janus with flask. Hope it helps for you.
|
0

You totally misunderstand how it works. streaming doesn't mean it can transport data intermittently, but means it can transport huge data while don't need to load it all at the beginning.

So while using stream, you are still using just one request. This request is a whole one, your browser can only deal with the response after the whole data is transported. In your case, as you are using an infinite loop, your browser will just waiting for the data forever.

To achieve what you want, you have two options:

  1. Use js to keep sending request per second.
  2. Use websocket.

update

It turns out that some elements can work with special mimetype multipart/x-mixed-replace to achieve long polling. As I am not a front-end guy, maybe someone can supply or correct my answer.

3 Comments

Ok and thank you for helping. How does this flask video server stream different frames in real time using an infinite loop with yield?
Hum, I shouldn't answer this question... It is a totally front-end question while I am a backend guy... But basically the point is the mimetype, multipart/x-mixed-replace is a special mimetype. Although it works with img element, I believe it doesn't work with all elements. Or at least won't work with p, as there isn't a logic for p to pull data.
Not true, clients can read and output the data from a Response directly and don't have to wait before it is finished. With curl for example: curl -vN "127.0.0.1:5000/time_feed"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.