Django 中使用流响应处理视频
source link: http://www.hongweipeng.com/index.php/archives/1559/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
起步
利用 html5 的 <video>
标签可以播放:
<video width="320" height="240" controls> <source src="/static/video/demo.mp4" type="video/mp4"> 您的浏览器不支持Video标签。 </video>
但是这样的方式,视频中的进度条无法使用,而且以静态文件方式返回的话,后台的程序会占用大量的内存。
使用响应流的方式能很好的解决这两个问题。
StreamingHttpResponse
大多数 Django 响应使用 HttpResponse
。这意味着响应的主体内置在内存中,并以单件形式发送到 HTTP 客户端。而如果用 StreamingHttpResponse
的方式则可以以 chunks
(部分块)的方式返回。一个很简单的例子就是:
from django.http import StreamingHttpResponse def hello(): yield 'Hello,' yield 'there!' def test(request): return StreamingHttpResponse(hello)
根据 WSGI
协议中的,当服务器调用时,应用程序对象必须返回一个可迭代的,产生零个或多个字节串。因此我们可以通过给服务器提供生成器来完成流响应的功能。
常见的使用 StreamingHttpResponse
是一些大文件的下载等,利用它还能完成断点续传的功能。
视频流
使用视频流时可以从请求头部中获得起始字节数。
这字段似乎是浏览器自动提供的,因为html代码中,我只需要改下视频的 src
的从静态地址变成路由方式而已。对于响应体而言,也要提供响应体返回的块的一个范围:
Content-Range
分别表示了 起始字节号-终止字节号/文件总字节
,该响应体的内容包含了文件该范围内的内容。处理视频流的代码如下:
import re import os from wsgiref.util import FileWrapper from django.http import StreamingHttpResponse def file_iterator(file_name, chunk_size=8192, offset=0, length=None): with open(file_name, "rb") as f: f.seek(offset, os.SEEK_SET) remaining = length while True: bytes_length = chunk_size if remaining is None else min(remaining, chunk_size) data = f.read(bytes_length) if not data: break if remaining: remaining -= len(data) yield data def stream_video(request, path): """将视频文件以流媒体的方式响应""" range_header = request.META.get('HTTP_RANGE', '').strip() range_re = re.compile(r'bytes\s*=\s*(\d+)\s*-\s*(\d*)', re.I) 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 = first_byte + 1024 * 1024 * 8 # 8M 每片,响应体最大体积 if last_byte >= size: last_byte = size - 1 length = last_byte - first_byte + 1 resp = StreamingHttpResponse(file_iterator(path, 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
Recommend
-
2
使用Django Cache引发的Bug处理 两年前写过一篇文章Django开发中使用Cache缓存提升10倍效率用来解决任务系统执行任务慢的问题,也就是在这个...
-
8
频率组件 频率组件类似于 权限组件 ,它判断是否给予请求通过。频率 指示临时状态,并用于控制客户端可以向API发出的请求的速率。 与权...
-
24
本篇文章讲述响应的处理,关于请求的处理可以看我第一篇文章 链接地址: https://segmentfault.com/a/11... 前期准备 使用环境
-
7
StatusCodePagesMiddleware中间件与ExceptionHandlerMiddleware中间件类似,它们都是在后续请求处理过程中“出错”的情况下利用一个错误处理器来接收针对当前请求的处理。它们之间的差异在于对“错误”的认定上:ExceptionHandlerMiddleware中间件所谓的错误就是抛...
-
1
Go http handler统一响应&异常处理 uuid · 3天之前 · 183 次点击 · 预计阅读时间 5 分钟 ·...
-
3
asp.net core发布至今已经将近6年了,很多人对于这一块还是有些陌生,或者说没接触过;接触过的,对于asp.net core整个启动过程,监听过程,以及请求过程,响应过程也是一知半解,可能有的同学在面试中有被问过整个的启动过程;对此,有个想法就是针对...
-
2
1、请求处理参数 1.1 请求参数 @RequestParam 1.1.1 不使用 @RequestParam 注解 请求参数处理,不使用参数注解: 1.如果
-
2
springboot 请求响应处理流程Tomcat 会把请求委托到org.springframework.web.servlet.DispatcherServlet#doServiceprotected void doService(HttpServletRequest request, HttpServletResponse response) thr...
-
0
2345浏览器上网出现未响应问题如何处理?最近不少用户反馈在使用2345浏览器上网的时候出现没有响应,然后一直卡顿在一个页面的情况。遇到这个现象将导致用户无法成功访问或者搜索需要的内容,体验非常糟糕。那么我们如何解决这个问...
-
4
作者:the5fire | 标签: Django Django源码解析 ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK