-2

My django views.py generates an mp3 file on the server at ./speech.mp3 after user interaction. How do I play it on the user's browser? If I just play the mp3 file using python code in views.py, it'll only be played on the server PC, not the user's browser.

I'm thinking of 2 solutions:

Either I have to pass the mp3 to the user's browser through ajax

OR

upload it to a cloud service.

Not sure how to approach though.

index.js:

$.ajax({
      url: "/text_speech/",
      type: "POST",
      data: {text: $("#id_text").val(),
        voice: $("#id_voice").val(),
        speed: speed.slider("option", "value")},
      dataType: "json",
      success: function (response){
      },
      error: function(xhr,errmsg,err) {
      }
    });

views.py:

class text_speech(base.TemplateView):
    .....

    @staticmethod
    def post(request, *args, **kwargs):
        form = forms.input_form(request.POST)

        if form.is_valid():
            # process the data
            .....
         
            # Generate the mp3 file at ./speech.mp3
            amazon_polly.amazon_polly(....)

            return http.JsonResponse({}, status=200)
        else:
            return http.JsonResponse({}, status=400)
NoName
  • 9,824
  • 5
  • 32
  • 52
  • If the file is available through a URL, use an `audio` element and set the URL as the `src` property – Rory McCrossan Nov 10 '20 at 09:17
  • @RoryMcCrossan But the audio file is generated after the user has loaded and interacted with the page. So the mp3 exists on the server but not the browser. – NoName Nov 10 '20 at 09:21
  • In that case you need a way for the server to let the browser know when the file has been prepared and is ready for the browser to download. Are you using an AJAX request to create the MP3 file? If so, that becomes trivial. In any case, the solution is the same (play the file in an `audio` element), the issue you have is knowing when the file is available and its URL – Rory McCrossan Nov 10 '20 at 09:22
  • @RoryMcCrossan Yeah, that's why I posted this question lol – NoName Nov 10 '20 at 09:23
  • Then please post your AJAX code in the question too. – Rory McCrossan Nov 10 '20 at 09:23
  • Thanks, I added an answer for you. – Rory McCrossan Nov 10 '20 at 09:29

1 Answers1

0

To solve this issue you could return the URL to the audio file you create in the response of the AJAX request. Then you can create an audio element in the JS logic, setting that URL as the src. Something like this:

return http.JsonResponse({ audio_url: 'your-mp3-file-path-here.mp3' }, status=200)
$.ajax({
  url: "/text_speech/",
  type: "POST",
  data: {
    text: $("#id_text").val(),
    voice: $("#id_voice").val(),
    speed: speed.slider("option", "value")
  },
  dataType: "json",
  success: function(response) {
    let $audio = $('<audio />', { src: response.audio_url });
    $audio[0].play();
  },
  error: function(xhr, errmsg, err) {}
});

The one thing to note is that you will need to use separate URLs for every mp3 file, otherwise you'll run in to concurrency issues when you have multiple users requesting audio files at the same time.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • See, the problem here is that the mp3 file is generated after page load. That means the browser does not have the mp3 file when `collectstatic` ran. So just passing an url to a local path on the server wouldn't work. – NoName Nov 10 '20 at 09:35
  • Right, that's why this code operates after the AJAX call completes and the file has been created and is available for download. – Rory McCrossan Nov 10 '20 at 09:36
  • Okay, I will try it and report back. – NoName Nov 10 '20 at 09:36
  • `let $audio = $('' { src: response.audio_url });` is invalid code. – NoName Nov 10 '20 at 09:43