I have 10 minute videos that I want to be able to stream from my Flask website. How do I do this so that the users don't have to download the entire video before it can play? I am currently running the app through the development server as it is only for a personal project. However, if running through an actual WSGI will fix the issue then I am willing to do so.
Asked
Active
Viewed 2,694 times
2 Answers
3
If it was a camera feed, you'd have to use generator-based code taking into consideration efficiency as in this demo. Here is the for streaming demo improved from here:
First you need to give out the video file in chunks using generators (the yield statement)
def get_chunk(filename, byte1=None, byte2=None):
filesize = os.path.getsize(filename)
yielded = 0
yield_size = 1024 * 1024
if byte1 is not None:
if not byte2:
byte2 = filesize
yielded = byte1
filesize = byte2
with open(filename, 'rb') as f:
content = f.read()
while True:
remaining = filesize - yielded
if yielded == filesize:
break
if remaining >= yield_size:
yield content[yielded:yielded+yield_size]
yielded += yield_size
else:
yield content[yielded:yielded+remaining]
yielded += remaining
Then stream the file on request:
@app.route('/')
def get_file():
filename = 'try2.mp4'
filesize = os.path.getsize(filename)
range_header = flask_request.headers.get('Range', None)
if range_header:
byte1, byte2 = None, None
match = re.search(r'(\d+)-(\d*)', range_header)
groups = match.groups()
if groups[0]:
byte1 = int(groups[0])
if groups[1]:
byte2 = int(groups[1])
if not byte2:
byte2 = byte1 + 1024 * 1024
if byte2 > filesize:
byte2 = filesize
length = byte2 + 1 - byte1
resp = Response(
get_chunk(filename, byte1, byte2),
status=206, mimetype='video/mp4',
content_type='video/mp4',
direct_passthrough=True
)
resp.headers.add('Content-Range',
'bytes {0}-{1}/{2}'
.format(byte1,
length,
filesize))
return resp
return Response(
get_chunk(),
status=200, mimetype='video/mp4'
)
Add the required headers using after_request
@app.after_request
def after_request(response):
response.headers.add('Accept-Ranges', 'bytes')
return response

Abdur-Rahmaan Janhangeer
- 570
- 4
- 20
-
-
The link under about the same if pretty reproductible, just rename the 'try.. ' file to your own – Abdur-Rahmaan Janhangeer Dec 19 '20 at 06:41
-
1Weird, I tried that before and it didn't work, but it worked now. Thanks for the help! – cubecubed Dec 19 '20 at 06:49
2
You need to process your videos into an adaptive bitrate format like Apple HLS and then host them like any other static asset. Something like S3. FFMPEG or AWS MediaConvert would work for processing. Then use a video player like video.js and point it at your .m3u8 manifest, and your set.
Disclaimer - I am employed by AWS which provides some of the services mentioned

Abdur-Rahmaan Janhangeer
- 570
- 4
- 20

smp
- 985
- 5
- 10