You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Django向PHP/React.js前端实现视频流式传输的最佳方案

Django 实现数据库存储视频的流式播放方案

核心逻辑

浏览器原生支持通过 <video> 标签实现流式播放,但需要后端处理范围请求(Range Requests)——也就是允许浏览器分段请求视频数据,支持拖拽跳转、按需加载,而非一次性下载完整视频。以下是具体实现步骤:

1. 数据库模型确认

确保你的视频模型正确存储二进制数据及关键元信息:

from django.db import models

class Video(models.Model):
    title = models.CharField(max_length=255)
    video_file = models.BinaryField()  # 存储视频二进制内容
    content_type = models.CharField(max_length=100, default="video/mp4")  # 视频MIME类型
    updated_at = models.DateTimeField(auto_now=True)  # 用于缓存校验

2. 自定义流式视图(处理范围请求)

Django 默认视图不支持范围请求,需自定义视图解析请求头并返回分段数据:

from django.http import HttpResponse, HttpResponseNotModified, Http404
from django.views import View
from .models import Video
import re

class VideoStreamView(View):
    def get(self, request, video_id):
        try:
            video = Video.objects.get(pk=video_id)
        except Video.DoesNotExist:
            raise Http404("视频不存在")
        
        video_data = video.video_file
        content_type = video.content_type
        file_size = len(video_data)

        # 处理Range请求头
        range_header = request.META.get("HTTP_RANGE", "")
        if range_header:
            match = re.match(r"bytes=(\d+)-(\d*)", range_header)
            if not match:
                return HttpResponse(status=416)  # 请求范围无效
            
            start = int(match.group(1))
            end = int(match.group(2)) if match.group(2) else file_size - 1
            
            if start >= file_size:
                return HttpResponse(status=416)
            
            end = min(end, file_size - 1)
            chunk_size = end - start + 1

            response = HttpResponse(
                video_data[start:end+1],
                status=206,  # 返回部分内容
                content_type=content_type
            )
            response["Content-Range"] = f"bytes {start}-{end}/{file_size}"
            response["Content-Length"] = str(chunk_size)
        else:
            # 无Range请求时返回完整文件(大视频不推荐,建议强制触发范围请求)
            response = HttpResponse(video_data, content_type=content_type)
            response["Content-Length"] = str(file_size)
        
        # 缓存优化头
        response["Accept-Ranges"] = "bytes"
        response["Last-Modified"] = video.updated_at.strftime("%a, %d %b %Y %H:%M:%S GMT")
        return response

3. 配置URL路由

在项目/应用的 urls.py 中添加流式访问路由:

from django.urls import path
from .views import VideoStreamView

urlpatterns = [
    # ... 其他路由
    path("video/stream/<int:video_id>/", VideoStreamView.as_view(), name="video_stream"),
]

4. 前端播放实现

在HTML模板中使用原生 <video> 标签,指向流式视图接口:

<video controls width="800">
    <source src="{% url 'video_stream' video.id %}" type="{{ video.content_type }}">
    你的浏览器不支持HTML5视频播放。
</video>

关键注意事项

  • 性能优化:数据库存储大视频会严重拖慢数据库性能,建议后续迁移到对象存储服务,Django仅存储文件URL,流式请求直接由存储服务处理(大部分云存储原生支持范围请求)。
  • 格式兼容:优先使用MP4(H.264编码)格式,确保兼容绝大多数浏览器。
  • 权限控制:可在视图中添加登录验证、权限校验逻辑,比如判断用户是否有权限观看目标视频。
  • 错误处理:增加对视频损坏、MIME类型错误等场景的捕获,返回对应HTTP状态码。

内容的提问来源于stack exchange,提问作者Bello Shehu Ango

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 18:31:07