|
import time |
|
import requests |
|
import pathlib |
|
from io import BytesIO |
|
from flask import Flask, request, render_template, send_file |
|
from pydub import AudioSegment |
|
|
|
|
|
app = Flask(__name__) |
|
|
|
|
|
ELEVENLABS_API_URL = "https://api.elevenlabs.io/v1/text-to-speech" |
|
HEADERS = {"User-Agent": "TTSApp"} |
|
CACHE_DIR = pathlib.Path("/tmp/audio_cache") |
|
CACHE_DIR.mkdir(parents=True, exist_ok=True) |
|
|
|
|
|
ALL_VOICES = { |
|
"Brian": "nPczCjzI2devNBz1zQrb", |
|
"Alice": "Xb7hH8MSUJpSbSDYk0k2", |
|
"Will": "bIHbv24MWmeRgasZH58o", |
|
} |
|
|
|
|
|
def split_sentences(text): |
|
return text.split(". ") |
|
|
|
|
|
def generate_audio(text, voice): |
|
if voice not in ALL_VOICES: |
|
return {"error": f"Invalid voice '{voice}'"} |
|
|
|
filename = CACHE_DIR / f"{int(time.time())}.mp3" |
|
sentences = split_sentences(text) |
|
|
|
audio_chunks = [] |
|
for sentence in sentences: |
|
response = requests.post( |
|
f"{ELEVENLABS_API_URL}/{ALL_VOICES[voice]}", |
|
headers=HEADERS, |
|
json={"text": sentence, "model_id": "eleven_multilingual_v2"}, |
|
timeout=20 |
|
) |
|
if response.ok: |
|
audio_chunks.append(BytesIO(response.content)) |
|
|
|
|
|
combined_audio = AudioSegment.empty() |
|
for chunk in audio_chunks: |
|
chunk_audio = AudioSegment.from_file(chunk, format="mp3") |
|
combined_audio += chunk_audio |
|
|
|
combined_audio.export(filename, format="mp3") |
|
return filename.as_posix() |
|
|
|
|
|
@app.route("/", methods=["GET", "POST"]) |
|
def home(): |
|
if request.method == "POST": |
|
text = request.form["text"] |
|
voice = request.form.get("voice", "Brian") |
|
audio_file = generate_audio(text, voice) |
|
return send_file(audio_file, as_attachment=True) |
|
|
|
return """ |
|
<h1>Text-to-Speech Generator</h1> |
|
<form method="post"> |
|
<label>Text:</label><br> |
|
<textarea name="text" rows="4" cols="50" required></textarea><br> |
|
<label>Voice:</label> |
|
<select name="voice"> |
|
<option value="Brian">Brian</option> |
|
<option value="Alice">Alice</option> |
|
<option value="Will">Will</option> |
|
</select><br><br> |
|
<button type="submit">Generate & Download</button> |
|
</form> |
|
""" |
|
|
|
if __name__ == "__main__": |
|
app.run(debug=True, host="0.0.0.0", port=5000) |
|
|