Django 中使用流响应处理视频的方法
作者:栖迟於一丘 发布时间:2021-01-12 20:55:13
标签:Django,流响应,视频
起步
利用 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
来源:http://www.hongweipeng.com/index.php/archives/1559/
0
投稿
猜你喜欢
- 问题:1.一个销售系统,设有各级代理商,每个代理商的表是这样设计的 数据库结构表1: 代理商资料表[id]
- 本文中我们将通过一个例子来介绍SQL Server 2005的一个Bug,首先,在建立同义词链接Oracle的时候,我们会使用下面的语句:C
- 初识项目打开VS2015,创建Web项目,选择ASP.NET Web Application,在弹出的窗口里选择ASP.NET 5 Webs
- 最近从某网站下载了一批文档,但是文件是用数字串命名的文档(很多图书馆都这样吧),现在我也下载完了这些文件,也有这些文件的列表,就是不能一个一
- 来看看javascript怎么实现自动点击超级链接吧,主要使用了js中的onclick事件。这里推荐大家看看这篇文章js鼠标事件大全。看了这
- 1、在给客户系统巡检时通过rman维护日志发现有rman维护日志报错:RMAN-06207: WARNING: 3 objects coul
- 下面这个例子描述的是在Godaddy-Linux托管帐户上使用JSP连接到某个MySQL数据库。 <%@ page
- --建递增序列CREATE SEQUENCE LZEAM_SP_LOOP_EQ_SEQ MINVALUE 1 INCREMENT BY 1
- 我们在浏览网页的时候偶尔会遇到一些陌生的网页交互行为,通常情况下它们并不会影响你的正常使用,之所以出现情况往往是因为,设计师在设计某个交互方
- 如果你正在负责一个基于SQL Server的项目,或者你刚刚接触SQL Server,你都有可能要面临一些数据库性能的问题,这篇文章会为你提
- 框架thinkphp 版本:3.2.3 内容:数据库操作1. 多表查找一条数据M('a表')->join("
- 在应用SA-FileUp时,必须确认用户已对目的路径有读、写、删除的权力。在多文件上传中,由于浏览器不支持SIZE= 属性,所以对多文件的情
- 内部存储格式:世纪、年、月、日、小时、分钟、秒默认格式是:DD-MON-RR。SYSDATE 返回当前的系统时间。SELECT S
- 准确地讲,Python没有专门处理字节的数据类型。但由于str既是字符串,又可以表示字节,所以,字节数组=str。而在C语言中,我们可以很方
- 为什么我把自己机子上的数据库备份文件往另一台机子上还原不成功?可能是你在Restore的对话框中选项不正确。Restore 有三个选项,分别
- 本文实例讲述了php基于websocket搭建简易聊天室实践。分享给大家供大家参考。具体如下:1、前言公司游戏里面有个简单的聊天室,了解了之
- check.asp 代码如下:<% '''''''''
- 解决方法:1。 改表法。可能是你的帐号不允许从远程登陆,只能在localhost。这个时候只要在localhost的那台电脑,登入mysql
- 1、设置web.config文件。以下为引用的内容:<system.web> ...... <globalization
- “模板化”——这也许是视觉设计师通常最不愿意听到的概念,先入为主的会产生“批量生产”、“体力活儿”、“限制思维”等概念,总之都比较负面。但为