# Serving a growing audio file with Django

I would like to serve a growing audio file (raw PCM audio for now) with the possibility of seeking. I tried to manage it with Apache, but in the end wasn't able to achieve what I wanted.

Now I managed to come up with a solution within Django that seems to work quite nicely. Basically I created a view that delivers a part of the file and then sends a response with status code 206 and Content-Range header.

### DJANGO VIEW

MAX_CHUNK_SIZE = 32000
MAX_WAV_LENGTH = 4294967303
BYTES_PER_SECOND = 32000

def get_audio(request, file_name):

# get offset
pos = int(request.GET.get("pos", 0))
offset = pos * BYTES_PER_SECOND

# get range
r = request.META["HTTP_RANGE"]
start = int(r.replace("bytes=", "").split("-")[0])
start_o = start + offset

# in case this is the first request, a wave header is added
if start == 0:
length = 44
else:
data = ""
length = 0
start_o -= 44

file_path = join(settings.STREAMS_DIR, file_name)

# wait up to 10 seconds if the end of the file is reached
# (in case it grows more)
for _ in range(10):
size = getsize(file_path)
if size - start_o > 0:
break
else:
sleep(1)

length += min(MAX_CHUNK_SIZE, size - start_o)

# if the length is zero (if end of file is reached and there is
# nothing more to server), set the total length to the actual
# served length
if length == 0:
total = size - offset + 44
# else, set the total length to the maximum possible wav length
# so that the browsers know that it has to send subsequent requests
else:
total = MAX_WAV_LENGTH

# get the actual data from the raw audio file
with open(file_path, "rb") as f:
f.seek(start_o)

# send response with use of Content-Range
resp = HttpResponse(data, content_type="audio/x-wav", status=206)
resp["Content-Range"] = "bytes " + str(start) + "-" + str(start + length) + "/" + str(total)
return resp


In the browser, I can then simply request my audio like in the following way, to make it play from any point:

var fileName = "xyz.wav";
var start = 25; //seconds
audio = new Audio();
audio.src = "/getAudio/" + fileName + "?pos=" + start;
audio.play();


As I said, this all seems to work pretty well. But I would like to know this is a valid approach that I can use in production or if there are some major problems that I am not aware of.

• The one issue would be performance. Unless the sample is quite small I'd say you shouldn't send raw PCM anyway. Have you looked at streaming media servers (Icecast and friends), that would be what you want for production IMO. – ferada Oct 28 '15 at 15:30
• @ferada I'm using wave files for now, just to test the basics. Later I would indeed switch to something like mp3 or ogg. I must admit that I didn't look too much into icecast until now but I was under the impression that it's purpose is live streaming and not so much streaming of static files (especially if they are growing in size). But I will check it out. – basilikum Oct 29 '15 at 13:43
• Right, the "growing file" part lead me to believe that it would fit. Nevermind. – ferada Oct 29 '15 at 14:12

• Serving static files is implemented in Django, including HTTP range parsing. However the one method I found only works in debug mode. Still, I'd try to reuse django.utils.http.parse_http_range and django.http.response.PartialHttpResponse if possible, so that not all of the data is read into memory at once.