Django 中使用流响应处理视频的方法


Posted in Python onJuly 20, 2018

起步

利用 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 是一些大文件的下载等,利用它还能完成断点续传的功能。

视频流

使用视频流时可以从请求头部中获得起始字节数。

Django 中使用流响应处理视频的方法

这字段似乎是浏览器自动提供的,因为html代码中,我只需要改下视频的 src 的从静态地址变成路由方式而已。对于响应体而言,也要提供响应体返回的块的一个范围:

Django 中使用流响应处理视频的方法

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用python获取CPU和内存信息的思路与实现(linux系统)
Jan 03 Python
python解析中国天气网的天气数据
Mar 21 Python
python实现堆栈与队列的方法
Jan 15 Python
浅谈python多线程和队列管理shell程序
Aug 04 Python
Python在图片中添加文字的两种方法
Apr 29 Python
python opencv之SURF算法示例
Feb 24 Python
用python做游戏的细节详解
Jun 25 Python
Python字符串大小写转换拼接删除空白
Sep 19 Python
手把手教你Python yLab的绘制折线图的画法
Oct 23 Python
Python 格式化输出_String Formatting_控制小数点位数的实例详解
Feb 04 Python
Django REST framwork的权限验证实例
Apr 02 Python
从0到1使用python开发一个半自动答题小程序的实现
May 12 Python
Python实现手写一个类似django的web框架示例
Jul 20 #Python
python 实现求解字符串集的最长公共前缀方法
Jul 20 #Python
python实现求两个字符串的最长公共子串方法
Jul 20 #Python
Django基础知识与基本应用入门教程
Jul 20 #Python
opencv python 2D直方图的示例代码
Jul 20 #Python
Linux下python制作名片示例
Jul 20 #Python
Python爬虫的两套解析方法和四种爬虫实现过程
Jul 20 #Python
You might like
PHP IPV6正则表达式验证代码
2010/02/16 PHP
PHP用SAX解析XML的实现代码与问题分析
2011/08/22 PHP
php计算指定目录下文件占用空间的方法
2015/03/13 PHP
JQuery 选择器、过滤器介绍
2011/02/14 Javascript
jquery 层次选择器siblings与nextAll的区别介绍
2013/08/02 Javascript
输入自动提示搜索提示功能的使用说明:sugggestion.txt
2013/09/02 Javascript
javascript中Object使用详解
2015/01/26 Javascript
js实现跨域的几种方法汇总(图片ping、JSONP和CORS)
2015/10/25 Javascript
node-http-proxy修改响应结果实例代码
2016/06/06 Javascript
JS简单实现点击复制链接的方法
2016/08/03 Javascript
百度地图API之百度地图退拽标记点获取经纬度的实现代码
2017/01/12 Javascript
AngularJS 防止页面闪烁的方法
2017/03/09 Javascript
JavaScript算法教程之sku(库存量单位)详解
2017/06/29 Javascript
JS数组操作之增删改查的简单实现
2017/08/21 Javascript
ES6/JavaScript使用技巧分享
2017/12/14 Javascript
js实现点击展开隐藏效果(实例代码)
2018/09/28 Javascript
基于vue实现一个神奇的动态按钮效果
2019/05/15 Javascript
VUE项目实现主题切换的多种方法
2020/11/26 Vue.js
python数据结构之图深度优先和广度优先实例详解
2015/07/08 Python
numpy.delete删除一列或多列的方法
2018/04/03 Python
Python解决八皇后问题示例
2018/04/22 Python
matplotlib subplots 调整子图间矩的实例
2018/05/25 Python
tensorflow学习教程之文本分类详析
2018/08/07 Python
Python 实现「食行生鲜」签到领积分功能
2018/09/26 Python
详解pandas中MultiIndex和对象实际索引不一致问题
2019/07/23 Python
python如何实现不用装饰器实现登陆器小程序
2019/12/14 Python
Python 通过监听端口实现唯一脚本运行方式
2020/05/05 Python
Django websocket原理及功能实现代码
2020/11/14 Python
BeautifulSoup中find和find_all的使用详解
2020/12/07 Python
纯css3实现走马灯效果
2014/12/26 HTML / CSS
周仰杰(JIMMY CHOO)法国官方网站:闻名世界的鞋子品牌
2019/09/27 全球购物
ASOS西班牙官网:英国在线时尚和美容零售商
2020/01/10 全球购物
如何处理简单的PHP错误
2015/10/14 面试题
会议开幕致辞怎么写
2016/03/03 职场文书
nginx实现发布静态资源的方法
2021/03/31 Servers
python 通过使用Yolact训练数据集
2021/04/06 Python