python - 使用 Flask 流式传输视频文件

标签 python flask

请帮我理解一下。

我正在尝试让 Flask 流式传输 .mp4 视频。我知道我可以使用 Response(generator_function())

但在浏览器中观看视频时不允许跳转到特定分钟​​。

所以我正在尝试使用 Range header 。这是我的尝试方式:

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 response

get_chunk 如果指定了字节,则生成从 byte1 到 byte2 的 block ,否则从 0 到文件大小( block 大小 = 1MB)。

但它不起作用。 我看到浏览器首先发送状态为 <200> 的请求。然后使用 <206>。请告诉我如何让它工作。

最佳答案

在开发服务器上,您需要启用 threaded=True 才能使视频流正常工作。

更新:

import os
import re

...


@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)

关于python - 使用 Flask 流式传输视频文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57314357/

相关文章:

javascript - 请求的资源 Flask+JQuery 上不存在 'Access-Control-Allow-Origin' header

python - 从 makefile 激活 Anaconda Python 环境

python - 访问字符串列表中的每个字符,避免嵌套 for 循环

python - 字段错误无法将关键字 'likes' 解析为字段。选择是 : id, name, page

python - 在 Windows bash 上 pip install flask 不起作用

python - Flask 和 SQLAlchemy 使用哪个 Forms 库

python - 从 Celery 任务登录到 Sentry

python - 在虚拟环境中的 Ubuntu 16.04 上将 Python 程序作为服务运行

python - 在 Redshift 中使用 Python 聚合 UDF

Python - 无法访问类中的变量