FileResponse
或 StreamingHttpResponse
,结合视频文件路径或生成器实现。
在 Django 中处理视频流响应,主要涉及到前端标签的使用、后端视图的编写以及相关配置等方面,以下是详细的步骤和代码示例:
使用video
标签结合video.js
库来播放视频,通过设置source
标签的src
属性指向后端提供的流媒体接口。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Video Streaming</title> <link href="https://vjs.zencdn.net/7.15.4/video-js.css" rel="stylesheet"> <script src="https://vjs.zencdn.net/7.15.4/video.min.js"></script> </head> <body> <video id="example_video" width="100%" height="50%" class="video-js vjs-default-skin " controls poster="" style="display: inline-block;"> <source src="/stream_video/?path={{path}}" type="video/mp4"> </video> <script> var player = videojs('example_video'); </script> </body> </html>
其中src
属性的值/stream_video/?path={{path}}
是关键,这里的path
是播放视频的模板接收从视图传过来的视频文件名称,用于实现播放不同视频。
1、URL 路由配置:在urls.py
文件中配置对应的 URL 路由,将前端请求的路径与后端视图函数关联起来。
from django.urls import path from . import views urlpatterns = [ path('stream_video/', views.stream_video, name='stream_video'), ]
2、视图函数编写:在views.py
文件中编写处理视频流响应的视图函数stream_video
,该函数主要实现以下功能:
获取请求头中的HTTP_RANGE
字段,用于支持视频的断点续传。
根据HTTP_RANGE
解析出请求的视频字节范围。
读取视频文件并按照请求的字节范围生成响应内容。
使用StreamingHttpResponse
将响应内容以流的方式返回给客户端。
具体代码如下:
import os import re from django.http import StreamingHttpResponse from wsgiref.util import FileWrapper from mimetypes import guess_type def stream_video(request): # 获取请求头中的 HTTP_RANGE 字段 range_header = request.META.get('HTTP_RANGE', '').strip() # 正则表达式匹配 HTTP_RANGE 字段的格式 range_re = re.compile(r'bytess*=s*(d+)s*-s*(d*)', re.I) range_match = range_re.match(range_header) # 获取请求的视频文件路径参数 path = request.GET.get('path') # 获取视频文件的绝对路径 folder_path = os.getcwd().replace('\', '/') # 根据实际情况修改文件夹路径 path = os.path.join(folder_path, path) # 获取视频文件的大小 size = os.path.getsize(path) # 获取视频文件的 MIME 类型和编码方式 content_type, encoding = guess_type(path) content_type = content_type or 'application/octet-stream' # 创建文件迭代器函数,用于读取视频文件的指定字节范围 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 # 根据 HTTP_RANGE 字段判断是否是部分请求 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 * 10 if last_byte >= size else int(last_byte) 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'] = f'bytes {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
1、文件存储路径:确保视频文件存储在服务器上可访问的位置,并且在folder_path
中正确指定了视频文件所在的文件夹路径,如果需要将视频文件存储在项目外的文件夹中,需要在settings.py
中进行相应的配置,如设置FILES_DIR
等。
2、性能优化:对于大型视频文件或高并发的视频流请求,可以考虑对服务器进行性能优化,如使用缓存、负载均衡等技术,以提高视频流的响应速度和稳定性。
3、安全性:在处理视频流响应时,要注意对用户请求的合法性进行验证,防止反面请求对服务器造成安全风险,如限制请求的来源 IP、验证用户身份等。