视频流
# 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>