About Streaming Audio Files
Streaming audio files allows you to have quicker Time to First Byte (TTFB) and doesn't require downloading the entire file to start playing the track from the specified position. You can stream audio files using the StreamingHttpResponse
responses with a file iterator, as follows:
import re
import os
from wsgiref.util import FileWrapper
from django.http import StreamingHttpResponse
from django.conf import settings
RANGE_RE = re.compile(r"bytes\s*=\s*(\d+)\s*-\s*(\d*)", re.I)
def file_iterator(file_path, chunk_size=8192, offset=0, length=None):
with open(file_path, "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_audio(request):
path = str(settings.BASE_DIR / "data" / "music.mp3")
content_type = "audio/mp3"
range_header = request.META.get("HTTP_RANGE", "").strip()
range_match = RANGE_RE.match(range_header)
size = os.path.getsize(path)
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
) # The max volume of the response body is 8M per piece
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-Range"] = f"bytes {first_byte}-{last_byte}/{size}"
else:
response = StreamingHttpResponse(
FileWrapper(open(path, "rb")), content_type=content_type
)
response["Accept-Ranges"] = "bytes"
return response
Tips and Tricks Programming Development Django 4.2 Django 3.2 Django 2.2
Also by me
Django Paddle Subscriptions app
For Django-based SaaS projects.
Django GDPR Cookie Consent app
For Django websites that use cookies.