跳转底部

视频流

# urls.py
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^video/', views.video),
    url(r'^test/', views.test),
]

#views.py
from django.shortcuts import render
from django.http import StreamingHttpResponse

def hello():
  yield 'Hello,'
  yield 'there!'

def test(request):
  return StreamingHttpResponse(hello()) # 这里面传的是一个可迭代对象


import re
import os
import mimetypes
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):   # 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)  # 根据由url给出的文件名或URL猜测文件的类型。返回值是一个元组(type, encoding)
  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)
    # print(111)  通过打印可以看到走的是视频流
  else:
    # 不是以视频流方式的获取时,以生成器方式返回整个文件,节省内存
    resp = StreamingHttpResponse(FileWrapper(open(path, 'rb')), content_type=content_type)
    resp['Content-Length'] = str(size)
    # print(2222)
  resp['Accept-Ranges'] = 'bytes'
  return resp

def video(request):
    return stream_video(request,r'D:\desk\python\project\day111\test_stream\media\575ed05ec95db.mp4')

# 当浏览器请求大文件时,浏览器的请求头会有个Range字段,表示请求的起始字节到终止字节,我们就是通过request拿到这个数据,并通过这个数改变响应的字节流
# 在html页面中的video src地址不应再写静态文件的地址了,要写url地址,即向服务器发请求的地址
# 也可以使用这种方法传大文件,并且这样支持断点续传
# 处理视频流的代码后续最好单独写个文件,然后引用


# html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>

<video width="320" height="240" controls>
    <source src="http://127.0.0.1:8000/video/" type="video/mp4">
    您的浏览器不支持Video标签。
</video>
</body>
</html>

  

posted on 2018-11-13 15:49  afly666  阅读(655)  评论(0编辑  收藏  举报

导航

回到顶部