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 Numpy的数组array和矩阵matrix详解
Apr 04 Python
Windows 64位下python3安装nltk模块
Sep 19 Python
一行代码让 Python 的运行速度提高100倍
Oct 08 Python
python微信公众号之关注公众号自动回复
Oct 25 Python
pycharm恢复默认设置或者是替换pycharm的解释器实例
Oct 29 Python
pandas中apply和transform方法的性能比较及区别介绍
Oct 30 Python
解决Python3 被PHP程序调用执行返回乱码的问题
Feb 16 Python
python绘制地震散点图
Jun 18 Python
python读取ini配置文件过程示范
Dec 23 Python
pandas实现excel中的数据透视表和Vlookup函数功能代码
Feb 14 Python
python,Java,JavaScript实现indexOf
Sep 09 Python
Python学习之包与模块详解
Mar 19 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
如何将一个表单同时提交到两个地方处理
2006/10/09 PHP
基于ubuntu下nginx+php+mysql安装配置的具体操作步骤
2013/04/28 PHP
PHP生成二维码与识别二维码的方法详解【附源码下载】
2019/03/07 PHP
Swoole扩展的6种模式深入详解
2021/03/04 PHP
表单的一些基本用法与技巧
2006/07/15 Javascript
js滚动条多种样式,推荐
2007/02/05 Javascript
Javascript 跨域访问解决方案
2009/02/14 Javascript
JavaScript中用字面量创建对象介绍
2014/12/31 Javascript
js下拉选择框与输入框联动实现添加选中值到输入框的方法
2015/08/17 Javascript
如何在Angular.JS中接收并下载PDF
2016/11/26 Javascript
100行代码理解和分析vue2.0响应式架构
2017/03/09 Javascript
加载 vue 远程代码的组件实例详解
2017/11/20 Javascript
对VUE中的对象添加属性
2018/09/18 Javascript
Vuex 单状态库与多模块状态库详解
2018/12/11 Javascript
Nuxt.js实现一个SSR的前端博客的示例代码
2019/09/06 Javascript
vue 数据遍历筛选 过滤 排序的应用操作
2020/11/17 Javascript
[02:10]探秘浦东源深体育馆 DOTA2 Supermajor不见不散
2018/05/17 DOTA
Python抓取Discuz!用户名脚本代码
2013/12/30 Python
使用python实现strcmp函数功能示例
2014/03/25 Python
Python中的单继承与多继承实例分析
2018/05/10 Python
Python实现监控键盘鼠标操作示例【基于pyHook与pythoncom模块】
2018/09/04 Python
实例详解python函数的对象、函数嵌套、名称空间和作用域
2019/05/31 Python
python机器学习库xgboost的使用
2020/01/20 Python
django的模型类管理器——数据库操作的封装详解
2020/04/01 Python
使用OpenCV对车道进行实时检测的实现示例代码
2020/06/19 Python
MAC平台基于Python Appium环境搭建过程图解
2020/08/13 Python
香港草莓网土耳其网站:Strawberrynet TR
2017/03/02 全球购物
印度在线购买电子产品网站:Croma
2020/01/02 全球购物
高中毕业自我鉴定范文
2013/10/02 职场文书
电大毕业生自我鉴定
2014/04/10 职场文书
主题班会演讲稿
2014/05/22 职场文书
2014单位领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
单位委托书格式范本
2014/09/29 职场文书
2014年服务员工作总结
2014/11/18 职场文书
联谊会开场白
2015/06/01 职场文书
使用python绘制横竖条形图
2022/04/21 Python