Por favor, ayúdame a entender un momento.
Estoy tratando de hacer que Flask transmita video .mp4. Sé que puedo usar Response(generator_function())
Pero no permite saltar a un minuto específico mientras ve un video en el navegador.
Así que estoy tratando de usar el encabezado Range . Así es como lo pruebo:
app = Flask(__name__) def get_chunk(byte1=None, byte2=None): filesize = os.path.getsize('try2.mp4') yielded = 0 yield_size = 1024 * 1024 if byte1 is not None: if not byte2: byte2 = filesize yielded = byte1 filesize = byte2 with open('try2.mp4', '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 @app.route('/') def get_file(): filesize = os.path.getsize('try2.mp4') 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(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' ) @app.after_request def after_request(response): response.headers.add('Accept-Ranges', 'bytes') return responseget_chunk produce fragmentos de byte1 a byte2 si se especifican estos bytes, y de 0 a tamaño de archivo en caso contrario (tamaño de fragmento = 1 MB).
Pero no funciona. Veo que, en primer lugar, el navegador envía una solicitud con el estado <200>. Y luego con <206>. Por favor, aconséjeme cómo hacer que funcione.
En el servidor de desarrollo, debe habilitar threaded=True para que la transmisión de video funcione correctamente.
Actualizado:
@app.after_request def after_request(response): response.headers.add('Accept-Ranges', 'bytes') return response def get_chunk(byte1=None, byte2=None): full_path = "try2.mp4" file_size = os.stat(full_path).st_size start = 0 if byte1 < file_size: start = byte1 if byte2: length = byte2 + 1 - byte1 else: length = file_size - start with open(full_path, 'rb') as f: f.seek(start) chunk = f.read(length) return chunk, start, length, file_size @app.route('/video') def get_file(): range_header = request.headers.get('Range', None) byte1, byte2 = 0, None if range_header: 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]) chunk, start, length, file_size = get_chunk(byte1, byte2) resp = Response(chunk, 206, mimetype='video/mp4', content_type='video/mp4', direct_passthrough=True) resp.headers.add('Content-Range', 'bytes {0}-{1}/{2}'.format(start, start + length - 1, file_size)) return resp if __name__ == '__main__': app.run(threaded=True)