我正在尝试在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,则视频已正确加载。
我怎么能解决我的问题?
先感谢您!
你有两个选择:
from 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")
return Response(file("/root/media_assets/" + file["path"]), direct_passthrough=True)
我遇到了同样的问题,最终发现真正的问题是视频播放器客户端(至少在Objective-C iOS中)在响应中使用“范围”标题(你可以打印出Flask request.headers
来检查)。换句话说,流式传输实际上是使用HTTP中的“范围”支持实现的。
我在https://codeburst.io/the-taste-of-media-streaming-with-flask-cdce35908a50上跟踪了示例,Flask服务器代码需要使用“部分内容”(HTTP状态代码206)构建响应,并且需要处理请求中的“范围”标头。相关代码如下所示:
@app.after_request
def after_request(response):
response.headers.add('Accept-Ranges', 'bytes')
return response
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浏览器。