seminar-2020 icon indicating copy to clipboard operation
seminar-2020 copied to clipboard

GET / 응답으로 동영상 스트리밍 하기

Open ghost opened this issue 3 years ago • 4 comments

김정환 님의

https://chocolate-waffle-good.shop/

를 보고 그의 재치와 지혜에 깊은 감명을 받았습니다.

그래서 저의 GET / 을 그에게 바칩니다.

https://waffle-backend-gglifer.shop

/

다른 사람들도 각자 좋아하는 영상으로 스트리밍하면 재밌을 것 같아

코드를 공유합니다

/

# waffle-rookies-18.5-backend-2/waffle_backend/waffle_backend/views.py

from django.http import HttpResponse

import os
import re
import mimetypes
from wsgiref.util import FileWrapper
from django.http.response import StreamingHttpResponse
from django.conf import settings

range_re = re.compile(r'bytes\s*=\s*(\d+)\s*-\s*(\d*)', re.I)

class RangeFileWrapper(object):
    def __init__(self, filelike, blksize=8192, offset=0, length=None):
        self.filelike = filelike
        self.filelike.seek(offset, os.SEEK_SET)
        self.remaining = length
        self.blksize = blksize

    def close(self):
        if hasattr(self.filelike, 'close'):
            self.filelike.close()

    def __iter__(self):
        return self

    def __next__(self):
        if self.remaining is None:
            data = self.filelike.read(self.blksize)
            if data:
                return data
            raise StopIteration()
        else:
            if self.remaining <= 0:
                raise StopIteration()
            data = self.filelike.read(min(self.remaining, self.blksize))
            if not data:
                raise StopIteration()
            self.remaining -= len(data)
            return data

def ping(request):
    path = os.path.join(settings.BASE_DIR, 'waffle_backend', 'rock_you.mp4')
    range_header = request.META.get('HTTP_RANGE', '').strip()
    range_match = range_re.match(range_header)
    size = os.path.getsize(path)
    content_type, encoding = 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 = int(last_byte) if last_byte else size - 1
        if last_byte >= size:
            last_byte = size - 1
        length = last_byte - first_byte + 1
        response = StreamingHttpResponse(RangeFileWrapper(open(path, 'rb'), offset=first_byte, length=length),
                                         status=206, content_type=content_type)
        response['Content-Length'] = str(length)
        response['Content-Range'] = 'bytes %s-%s/%s' % (first_byte, last_byte, size)
    else:
        response = StreamingHttpResponse(FileWrapper(open(path, 'rb')), content_type=content_type)
        response['Content-Length'] = str(size)
    response['Accept-Ranges'] = 'bytes'
    return response

Notice

waffle-rookies-18.5-backend-2/waffle_backend/waffle_backend/views.py 파일과 같은 위치에 rock_you.mp4 동영상 파일을 넣었습니다.

Screen Shot 2020-11-15 at 12 18 48 AM

Reference

https://stackoverflow.com/questions/33208849/python-django-streaming-video-mp4-file-using-httpresponse

ghost avatar Nov 14 '20 15:11 ghost

오 흥미롭네요

YeonghyeonKO avatar Nov 14 '20 15:11 YeonghyeonKO

한 가지 남기자면, 일반적으로 settings의 값을 가져올 때는 해당 경로를 직접 import 하기보다

from django.conf import settings

를 이용하여 settings.BASE_DIR 같은 식으로 값을 사용하는 것이 좋습니다!

이런 팁 공유 넘 좋습니다 🚀

davin111 avatar Nov 14 '20 15:11 davin111

오오 동영상 넣는것은 생각도 못했습니다ㅋㅋㅋ 흥미롭네요ㅎㅎ

canoneod avatar Nov 14 '20 15:11 canoneod

백엔드장님의 조언 바로 반영했습니다 👍

ghost avatar Nov 14 '20 15:11 ghost