pythonhtmlflaskgtts

HTML Audio file generated with gtts and flask doesnt't play


I am making a blog post generating bot with images and I thought it will be cool if I ad a text to speech feature with gTTS, but I am having troubles making unique file names and to play the audio in the HTML.Can somebody help me?

Here is my Python code:

from flask import Flask , render_template, redirect , request
import openai
from gtts import gTTS


openai.api_key = 'OPENAI_API_KEY'

app = Flask(__name__)


@app.route('/', methods=['POST', 'GET'])
def index():
  audio = ""
  content = ""  # Initialize content with a default value
  images = []   # Initialize images as an empty list
  if request.method == 'POST':
    prompT = request.form.get("prompt")
    numberimages = request.form.get("numimg")
    content = generate_comp(prompT)
    audio = texttospeech(content)
    images = generate_dalle_image(prompT, numberimages)
  return render_template('index.html', content=content, images=images, audio=audio)


def generate_comp(promp):
  compleation = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
          {"role": "system", "content": "You are a helpful blog post writing assistant."},
          {"role": "user", "content": promp},
          ],
  max_tokens=300
  )
  return compleation.choices[0].message.content
 



def generate_dalle_image(prompt, num_images):
    response = openai.Image.create(
        model="image-alpha-001",  # DALL-E model for image generation
        prompt=prompt,
        n=int(num_images)
    )
    image_url = response['data'][0]['url']
    return image_url


def texttospeech(text):
  tts = gTTS(text)
  tts.save('audio-1.mp3')
  sfile = 'audio-1.mp3'





app.run(host="0.0.0.0", port=5000, debug=True)

And my HTML code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>🏦blog.AI</title>
    <style>
body{
    background-color: #242942;
}
form{
    display:flex;
    justify-content: center;
}
input[type="text"], input[type = "number"]{
    background-color: #40424b;
    padding: 10px 15px;
    border-radius: 10px;
    border:0;
    margin-right:10px;
}
input[type="text"]::placeholder{
    color: #919191;
}
input[type="submit"]{   
    background-color: #20c92e;
    margin-left: 5px;
    border-radius: 10px;
    border:0;
}
input[type="number"]::placeholder{
    color: #919191;
}


h2,h4{
    font-family: 'Ubuntu', sans-serif;
    color: #ffffff;
}
h1{
    font-family: 'Ubuntu', sans-serif;
    color: #ffffff;
}
input[type="submit"]:hover{
    background-color: #1c6822;  
}
    </style>
</head>
<body>
  <h1>🤖⌨️🖨️</h1>  
    <form action="#" method="post">
<input name="prompt" type="text" placeholder= "The Middle Ages....." >
<input name="numimg" type="number" placeholder="Images" >
<input type="submit" value="Generate">
    </form>
<h1>Post:</h1>
<h4>{{content}}</h4>
<h2>🖼️Images📷:</h2>
<img src="{{images}}" width="200" height="200">
<audio controls autoplay>
    <source src="audio-1.mp3" type="audio/mpeg"/>
    Doesnt't work
</audio>
</body>
</html>

I tried making many audio files for every blog post theme with an if statement but it didn't work.Can somebody help me with both of these issues.I also tried aving the file as a wav file but it didn't work either.


Solution

  • Your texttospeech function does not return anything, but you're trying to pass a value (I assume the file name) into the audio variable in your index function. In your case, I would generate a random string as a file name and return that from your text to speech function like so:

    Add this to your imports

    import os
    import random
    import string
    

    And change your texttospeech function to this:

    def random_string(l):
        return "".join([random.choice(string.ascii_lowercase) for i in range(l)])
    
    def texttospeech(text):
        tts = gTTS(text)
        file_name = random_string(10)
        tts.save(file_name + '.mp3')
        return file_name
    

    Then you can use the audio value you passed to the template to reference the source of the audio file.

    To get the file from the server, you need to create an additional route taking the file name as an input.

    @app.route("/download_audio/<file_name>")
    def download_result(file_name):
    
        #Prevents the user from accessing other directories
        if "." in file_name or "/" in file_name:
            return "Invalid file name", 404
    
        if os.path.exists(file_name + ".mp3"):
            return flask.send_file(file_name + ".mp3")
        return "Not found", 404
    

    I strongly recommend to save the audio files in a separate directory, so you can clean them up more easily.