pythondjangoraspberry-pi

Playing an audio file on server from Django


I have a Raspberry Pi that I have hooked up to a door chime sensor, so it plays different sounds as people enter the building. Right now, I just made a short script to play those sounds from whatever is in a directory, and it works fine.

I decided that it might be easier to upload sounds and organize their play order, if I setup a web server, and since I tend to use Django for all web servers, I thought I could get it to work. I know it's a pretty big hammer for such a small nail, but I use it regularly, so it's easy for me to use.

This code, when I put it in the Django InteractiveConsole, plays just fine. When I try to call it from a PUT request in a view, it won't play the sound, but it also doesn't throw any errors. This is the case both on my computer and the Raspberry Pi.

>>> import vlc
>>> media_player = vlc.MediaPlayer()
>>> media = vlc.Media("/home/pi/chime/media/clips/clip1.mp3")
>>> media_player.set_media(media)
>>> media_player.play()

Is there something that would prevent these kinds of calls from running in a django view? Is there a way to work around it?

EDIT: Django code example

class ClipsList(View):
    template_name = "clips/clip_list.html"

    # Ensure we have a CSRF cooke set
    @method_decorator(ensure_csrf_cookie)
    def get(self, request):
        ctx = {
            'object_list': Clip.objects.all().order_by('order'),
        }
        return render(self.request, self.template_name, context=ctx)

    # Process POST AJAX Request
    def post(self, request):
        if request.headers.get('x-requested-with') == 'XMLHttpRequest':
            try:
                # Parse the JSON payload
                data = json.loads(request.body)[0]
                # Loop over our list order. The id equals the question id. Update the order and save
                for idx, row in enumerate(data):
                    pq = Clip.objects.get(pk=row['id'])
                    pq.order = idx + 1
                    pq.save()

            except KeyError:
                HttpResponse(status="500", content="Malformed Data!")

            return JsonResponse({"success": True}, status=200)
        else:
            return JsonResponse({"success": False}, status=400)

    def put(self, request, pk):
        if request.headers.get('x-requested-with') == 'XMLHttpRequest':
            try:
                data = json.loads(request.body)
                clip = Clip.objects.get(pk=pk)
                media_player = vlc.MediaPlayer()
                media = vlc.Media(os.path.join(settings.BASE_DIR, str(clip.file)))
                media_player.set_media(media)
                media_player.play()
                sleep(3)
                media_player.stop()

            except KeyError:
                HttpResponse(status="500", content="Malformed Data!")
            return JsonResponse({"success": True}, status=200)
        else:
            return JsonResponse({"success": False}, status=400)

Solution

  • Based on some questions I was asked, I realized that I had used BASE_DIR instead of MEDIA_ROOT for the directory of the clips. This fixed the problem on the development computer, but when served with Apache, it still wouldn't work until I added the www-data user to the audio, pulse, and pulse-access groups.