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通过opencv实现批量剪切图片
Nov 13 Python
Python三种遍历文件目录的方法实例代码
Jan 19 Python
Python解析命令行读取参数--argparse模块使用方法
Jan 23 Python
Python画柱状统计图操作示例【基于matplotlib库】
Jul 04 Python
python实现抠图给证件照换背景源码
Aug 20 Python
浅谈Django2.0 加xadmin踩的坑
Nov 15 Python
Python谱减法语音降噪实例
Dec 18 Python
在spyder IPython console中,运行代码加入参数的实例
Apr 20 Python
keras 读取多标签图像数据方式
Jun 12 Python
Python将字典转换为XML的方法
Aug 01 Python
Python用K-means聚类算法进行客户分群的实现
Aug 23 Python
Python Pandas常用函数方法总结
Jun 15 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
某大型网络公司应聘时的笔试题目附答案
2008/03/27 PHP
深入解析PHP中逗号与点号的区别
2013/08/05 PHP
thinkphp中ajax与php响应过程详解
2014/12/08 PHP
php清除和销毁session的方法分析
2015/03/19 PHP
PHP中number_format()函数的用法讲解
2019/04/08 PHP
jquery ajax 检测用户注册时用户名是否存在
2009/11/03 Javascript
Jquery弹出层插件ThickBox的使用方法
2014/12/09 Javascript
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
2015/01/01 NodeJs
JavaScript引用类型和基本类型详解
2016/01/06 Javascript
微信小程序中hidden不生效原因的解决办法
2017/04/26 Javascript
JavaScript实现简单的星星评分效果
2017/05/18 Javascript
Angular学习笔记之集成三方UI框架、控件的示例
2018/03/23 Javascript
React手稿之 React-Saga的详解
2018/11/12 Javascript
详解ES7 Decorator 入门解析
2019/02/18 Javascript
「中高级前端面试」JavaScript手写代码无敌秘籍(推荐)
2019/04/08 Javascript
JavaScript中this的全面解析及常见实例
2019/05/14 Javascript
[01:14]DOTA2亚洲邀请赛小组赛赛前花絮
2017/03/27 DOTA
python打开网页和暂停实例
2014/09/30 Python
python使用fileinput模块实现逐行读取文件的方法
2015/04/29 Python
python正则表达式之作业计算器
2016/03/18 Python
LRUCache的实现原理及利用python实现的方法
2017/11/21 Python
Python中摘要算法MD5,SHA1简介及应用实例代码
2018/01/09 Python
Python根据指定日期计算后n天,前n天是哪一天的方法
2018/05/29 Python
Linux下远程连接Jupyter+pyspark部署教程
2019/06/21 Python
Python中判断子串存在的性能比较及分析总结
2019/06/23 Python
TensorFlow实现简单的CNN的方法
2019/07/18 Python
Anaconda使用IDLE的实现示例
2020/09/23 Python
python实现猜拳游戏项目
2020/11/30 Python
社区学习十八大感想
2014/01/22 职场文书
会计专业大学生求职信范文
2014/01/28 职场文书
前厅收银主管岗位职责
2014/02/04 职场文书
违反工作纪律检讨书
2014/02/15 职场文书
个人自我鉴定总结
2014/03/25 职场文书
承诺书样本
2014/08/30 职场文书
考勤制度通知
2015/04/25 职场文书
Python OpenCV超详细讲解调整大小与图像操作的实现
2022/04/02 Python