gpt4 book ai didi

django - Python-Django : Streaming video/mp4 file using HttpResponse

转载 作者:行者123 更新时间:2023-11-28 21:39:46 25 4
gpt4 key购买 nike

我正在使用 Python2.7、django==1.7uwsgi 将视频/mp4 文件流式传输到 iPhone 播放器。

我的代码如下:

def stream(request):
with open('/path/video.mp4', 'r') as video_file:
response = HttpResponse(video_file.read(), content_type='video/mp4')
response['Content-Disposition'] = 'inline; filename=%s' % 'video.mp4'
return response
video_file.close

当我使用一些小视频(小于 1MB)时,它在浏览器中播放,但在 iPhone 播放器中我有这个错误:

[uwsgi-http key: 127.0.0.1:8008 client_addr: 192.168.0.172 client_port: 14563] hr_write(): Broken pipe [plugins/http/http.c line 564]

当视频大小超过 5MB 时,它不会在两个(指浏览器和 iPhone 播放器)中流式传输并出现相同的错误。

我尝试通过使用 StreamHttpRespose 返回的 chunk chunk 来做到这一点,如下所示:

def read(chunksize=8192):
with open('/path/video.mp4', 'rb') as video_file:
byte = video_file.read(chunksize)
while byte:
yield byte

return StreamingHttpResponse(read(), content_type='video/mp4')

但是出现同样的错误:Broken pipe

仅供引用,我可以流式传输 pdf 和图像文件。此问题仅存在于 mp4 文件中。而且我将 content_type 更改为“video-mpeg”,浏览器下载了它,同时我想阻止文件下载。

你的想法是什么?任何解决方案!?

最佳答案

我遇到了同样的问题,在找到可行的解决方案之前进行了大量挖掘!

显然 Accept Ranges header 是 HTML5 视频控件工作所必需的 (https://stackoverflow.com/a/24977085/4264463)。因此,我们需要从 HTTP_RANGE 中解析请求的范围,并在响应中返回 Content-Range。传递给 StreamingHttpResponse 的生成器也需要返回基于此范围的内容(通过 offsetlength)。我发现下面的片段效果很好(来自 http://codegist.net/snippet/python/range_streamingpy_dcwatson_python ):

import os
import re
import mimetypes
from wsgiref.util import FileWrapper

from django.http.response import StreamingHttpResponse


range_re = re.compile(r'bytes\s*=\s*(\d+)\s*-\s*(\d*)', re.I)


class RangeFileWrapper(object):
def __init__(self, filelike, blksize=8192, offset=0, length=None):
self.filelike = filelike
self.filelike.seek(offset, os.SEEK_SET)
self.remaining = length
self.blksize = blksize

def close(self):
if hasattr(self.filelike, 'close'):
self.filelike.close()

def __iter__(self):
return self

def __next__(self):
if self.remaining is None:
# If remaining is None, we're reading the entire file.
data = self.filelike.read(self.blksize)
if data:
return data
raise StopIteration()
else:
if self.remaining <= 0:
raise StopIteration()
data = self.filelike.read(min(self.remaining, self.blksize))
if not data:
raise StopIteration()
self.remaining -= len(data)
return data


def stream_video(request, path):
range_header = request.META.get('HTTP_RANGE', '').strip()
range_match = range_re.match(range_header)
size = os.path.getsize(path)
content_type, encoding = mimetypes.guess_type(path)
content_type = content_type or 'application/octet-stream'
if range_match:
first_byte, last_byte = range_match.groups()
first_byte = int(first_byte) if first_byte else 0
last_byte = int(last_byte) if last_byte else size - 1
if last_byte >= size:
last_byte = size - 1
length = last_byte - first_byte + 1
resp = StreamingHttpResponse(RangeFileWrapper(open(path, 'rb'), offset=first_byte, length=length), status=206, content_type=content_type)
resp['Content-Length'] = str(length)
resp['Content-Range'] = 'bytes %s-%s/%s' % (first_byte, last_byte, size)
else:
resp = StreamingHttpResponse(FileWrapper(open(path, 'rb')), content_type=content_type)
resp['Content-Length'] = str(size)
resp['Accept-Ranges'] = 'bytes'
return resp

关于django - Python-Django : Streaming video/mp4 file using HttpResponse,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33208849/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com