Skip to content

Instantly share code, notes, and snippets.

@agutoli
Last active April 19, 2020 23:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agutoli/d3cef2ce4a25ed8390ff1592ef0ce3a0 to your computer and use it in GitHub Desktop.
Save agutoli/d3cef2ce4a25ed8390ff1592ef0ce3a0 to your computer and use it in GitHub Desktop.
Example of Flask server video streaming
import os
import sys
import re
import mimetypes
from flask import Flask, render_template, request, send_file, Response
app = Flask(__name__)
filename = '/Users/agutoli/Downloads/test1.mp4'
def send_file_partial(file, filename):
"""
Simple wrapper around send_file which handles HTTP 206 Partial Content
:param file - io.BytesIO object
:param filename
:return - flask response object
"""
size = os.path.getsize(file.name)
range_header = request.headers.get('Range', None)
if not range_header:
return send_file(file, attachment_filename=filename, conditional=True)
byte1, byte2 = 0, None
m = re.search('(\d+)-(\d*)', range_header)
g = m.groups()
if g[0]:
byte1 = int(g[0])
if g[1]:
byte2 = int(g[1])
length = size - byte1
if byte2 is not None:
length = byte2 - byte1 + 1
file.seek(byte1)
data = file.read(length)
response = Response(data,
206,
mimetype=mimetypes.guess_type(filename)[0],
direct_passthrough=True)
response.headers.add('Content-Range', 'bytes {0}-{1}/{2}'.format(byte1, byte1 + length - 1, size))
response.headers.add('Accept-Ranges', 'bytes')
return response
@app.route('/')
def index():
return render_template('index.html')
@app.route('/myvideo.mp4')
def video():
size = os.path.getsize(filename)
with open(filename, 'rb') as file:
return send_file_partial(file, file.name)
if __name__ == '__main__':
app.run(debug=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment