使用Flask提供.mp4文件并在Objective-C应用程序上播放会导致管道断裂而无法播放

问题描述 投票:0回答:2

我正在尝试在iOS应用程序上播放由Flask Web应用程序提供的视频。虽然我可以播放任何使用“传统”网络服务器(如Apache)的视频,但我无法播放Flask提供的视频。这是相关代码:

Objective-C的

NSURL *videoURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@",videourltemp]];
AVPlayer *player = [AVPlayer playerWithURL:videoURL];

playerViewController.player = player;
[self.view addSubview:playerViewController.view];
[self.navigationController pushViewController:playerViewController animated:YES];

蟒蛇

from flask import Response, ...

def get_img(imgid):
    # private code hidden - file["path"] contains the path relative to /root/media_assets directory

    return Response(open("/root/media_assets/" + file["path"], "rb"), mimetype="video/mp4")

旁注:如果我尝试从浏览器访问我的URL,则视频已正确加载。

我怎么能解决我的问题?

先感谢您!

python objective-c video flask avplayer
2个回答
0
投票

你有两个选择:

  1. 打开文件并以块的形式读取它,而不是将其作为单个blob读取,就像在代码中一样。例如:https://stackoverflow.com/a/24318158/1955346from flask import stream_with_context, Response @app.route('/stream_data') def stream_data(): def generate(): with open("/root/media_assets/" + file["path"], "rb") as f: while True: chunk = ... # read each chunk or break if EOF yield chunk return Response(stream_with_context(generate()), mimetype="video/mp4")
  2. 使用How do I stream a file using werkzeug?的直接方法: return Response(file("/root/media_assets/" + file["path"]), direct_passthrough=True)

0
投票

我遇到了同样的问题,最终发现真正的问题是视频播放器客户端(至少在Objective-C iOS中)在响应中使用“范围”标题(你可以打印出Flask request.headers来检查)。换句话说,流式传输实际上是使用HTTP中的“范围”支持实现的。

我在https://codeburst.io/the-taste-of-media-streaming-with-flask-cdce35908a50上跟踪了示例,Flask服务器代码需要使用“部分内容”(HTTP状态代码206)构建响应,并且需要处理请求中的“范围”标头。相关代码如下所示:

  1. 在Flask app after_request中添加“Accept-Ranges”,以便客户端知道支持“range”:
@app.after_request
def after_request(response):
    response.headers.add('Accept-Ranges', 'bytes')
    return response
  1. 在为函数提供mp4文件的函数中,假设文件路径为“full_path”:
    file_size = os.stat(full_path).st_size
    start = 0
    length = 10240  # can be any default length you want

    range_header = request.headers.get('Range', None)
    if range_header:
        m = re.search('([0-9]+)-([0-9]*)', range_header)  # example: 0-1000 or 1250-
        g = m.groups()
        byte1, byte2 = 0, None
        if g[0]:
            byte1 = int(g[0])
        if g[1]:
            byte2 = int(g[1])
        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)

    rv = Response(chunk, 206, mimetype='video/mp4', content_type='video/mp4', direct_passthrough=True)
    rv.headers.add('Content-Range', 'bytes {0}-{1}/{2}'.format(start, start + length - 1, file_size))
    return rv

在我的测试中,上面的Flask代码适用于iOS objective-C客户端以及适用于.mp4文件的Chrome,Firefox浏览器。

© www.soinside.com 2019 - 2024. All rights reserved.