-
-
Notifications
You must be signed in to change notification settings - Fork 948
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Docs recipe: stream media with range request #1857
Comments
Hi 👋, Thanks for using Falcon. The large amount of time and effort needed to Please consider helping us secure the future of the Falcon framework with a Thank you for your support! |
Relates to: #349 |
Hi Johan, As already briefly discussed on Gitter, someone needs to dig deeper into this and understand what is going on. It would be great to add recipes/articles/tutorials to our docs illustrating how to perform these tasks, even though doing that directly from a Python app server is probably not the most optimal way. Maybe something in the DIY spirit along the lines of that blog post mentioned on #349, or uWSGI's Fun with Perl, Eyetoy and RaspberryPi. So that people can start tinkering 🙂 |
i made a few test after, and it look likes there's a problem with size. This could be related But as it's for my work, i'll do more testing monday. |
Hi again, I hacked together a simple proof-of-concept that does play reasonably smoothly in Firefox and Chrome. I called my mini-app import os
import falcon
CHUNK_SIZE = io.DEFAULT_BUFFER_SIZE * 16
class FileWrapper:
def __init__(self, filename):
self._fobj = open(filename, 'rb')
self._stream_start = None
self._stream_size = None
def __iter__(self):
self._fobj.seek(self._stream_start)
remaining = self._stream_size
while remaining > 0:
chunk_size = min(CHUNK_SIZE, remaining)
yield self._fobj.read(chunk_size)
remaining -= chunk_size
def get_file_size(self):
return os.fstat(self._fobj.fileno()).st_size
def stream(self, start, size):
self._stream_start = start
self._stream_size = size
return self
def close(self):
self._fobj.close()
class Stream:
def on_get(self, req, resp):
media_file = FileWrapper('/tmp' + req.path)
start = 0
size = full_size = media_file.get_file_size()
if req.range:
start, end = req.range
if end < 0:
end = full_size - 1
size = end - start + 1
resp.content_range = (start, end, full_size)
resp.status = falcon.HTTP_206
resp.content_length = size
resp.content_type = 'video/webm'
resp.stream = media_file.stream(start, size)
app = falcon.API()
app.add_route('/tears_of_steel_1080p.webm', Stream()) I ran with Edit: it works fine using |
Many thanks! Will do testing and let you know. |
@belese Slightly off-topic, but if you're interested to dig deeper into how client disconnects are handled across different WSGI app servers, see also this comment (by me): #1483 (comment) . And browsers do disconnect the ongoing streaming request if you seek further away from the current position, and issue a new range request. |
I've just test your code in my app, and yes it's just working fine! i still have a canceled request in chrome, but video is playing fine. 687 | http://10.1.12.2/api/stream/687 | GET | (canceled) | | media | Other | 0 B | 46 ms Edit : About cancelling, it's seems ok for chrome while caching media.. |
@belese Adding to my previous responses, if you are interested in further streamlining the browser interaction, you might benefit from generating an |
@vytas7 Thanks for info. In my case, it's circular movie record from a security camera. i guess 99.9% of them will never be seen. But i had to have a preview in browser. And with you snippet, for 5 minutes records length, there's very few bufferring time which is already perfect for my use case. But in future, if could be an enhancement (lot of other work for now), I let you know what i've changed. And again, many thanks for your support. |
Closing this since range support has been added natively to static routes as per #1858. |
Hello,
i'm tryning to stream mp4 video, with range request support.but i cannot manage to make it work with resp.stream.
This code work :
but this will load all file in memory, which is not an option.
if i change the 2 last line with
resp.set_stream(stream,size)
,i've got an error
i'm using uwsgi with nginx as reverse proxy. Not sure it's related to falcon, but i don't have any clue where to look at.
Any idea?
Thanks
Johan
Ps : i know it's not optimal to use falcon for this, but i cannot expose real video path to client (in real in come from a db). and performance are not really a problem in my case.
Edit :
Here's the chrome requests when it don't work.
The text was updated successfully, but these errors were encountered: