Requirements describe

For some applications, when we have a need to play video, we tend to use Nginx proxy static resources that you can just configure in your Nginx configuration file and the disadvantage of doing that is that when you load a lot of data, We’re too perfectionist to allow this to happen, so we’re going to do streaming in API style.

Depend on the environment

Python: 3.72.
Django: 2.17.
Copy the code

Realize the source

#! /usr/bin/python3
# _*_ Coding: UTF-8 _*_
import mimetypes
import os
import re
from wsgiref.util import FileWrapper

from django.http import StreamingHttpResponse
from rest_framework.views import APIView


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


class StreamVideoPlayViewSet(APIView) :
    def get(self, request, *args, **kwargs) :
        """ Respond to a video file in streaming mode """
        path = R 'This is the path to your dynamically built media file'
        range_re = re.compile(r'bytes\s*=\s*(\d+)\s*-\s*(\d*)', re.I)
        range_match = range_re.match(request.META.get('HTTP_RANGE'.' ').strip())
        size, (content_type, encoding) = os.path.getsize(path), 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 per slice, the maximum volume of the response body
            if last_byte >= size: last_byte = size - 1
            length = last_byte - first_byte + 1
            response = StreamingHttpResponse(file_iterator(path, offset=first_byte, length=length), status=206, content_type=content_type)
            response['Content-Length'], response['Content-Range'] = str(length), 'bytes %s-%s/%s' % (first_byte, last_byte, size)
        else:
            Return the entire file as a generator instead of a video stream, saving memory
            response = StreamingHttpResponse(FileWrapper(open(path, 'rb')), content_type=content_type)
            response['Content-Length'] = str(size)
        response['Accept-Ranges'] = 'bytes'
        return response

Copy the code