DEV Community

VoiceDeveloper
VoiceDeveloper

Posted on

Deploy a Voice Cloning Demo App: From Code to Live Website

Why Voice Cloning is the Next Big Thing

If you’ve been tinkering with text‑to‑speech (TTS) for a while, you’ve probably noticed a shift from generic, robotic voices to hyper‑realistic, personalized speech. Voice cloning lets you generate audio that sounds exactly like a specific person—perfect for podcasts, audiobooks, or even interactive assistants. The good news? You can spin up a demo in a single afternoon and push it live with a cheap, reliable host.

In this walkthrough I’ll show you how to:

  1. Grab an API key from ElevenLabs – the service that delivers studio‑grade voice cloning.
  2. Write a tiny Flask app that accepts text, calls the ElevenLabs API, and streams back an MP3.
  3. Deploy the app to a live website using Bluehost, the easy, affordable way to get your voice AI online.

Grab your own ElevenLabs API key here: https://try.elevenlabs.io/kr07zfuqn1bp.

When you’re ready for hosting, head over to Bluehost: https://bluehost.sjv.io/5k0d52.


1. Set Up the ElevenLabs Account

ElevenLabs offers a free tier that includes a handful of minutes of cloned speech each month—enough to test a demo. After you sign up:

  1. Navigate to Dashboard → API Keys.
  2. Click Create new key and copy the string; you’ll need it in your code.

Tip: Store the key in an environment variable (ELEVENLABS_API_KEY) instead of hard‑coding it. This keeps your credentials safe and makes deployment painless.


2. Build the Clone‑Demo Backend

We’ll use Python 3 and Flask because they’re lightweight and perfect for a quick prototype. The only external dependency is requests for the HTTP call to ElevenLabs.

# Create a virtual environment (optional but recommended)
python3 -m venv venv
source venv/bin/activate

# Install Flask and requests
pip install Flask requests
Enter fullscreen mode Exit fullscreen mode

app.py

import os
from flask import Flask, request, jsonify, send_file
import requests
from io import BytesIO

app = Flask(__name__)

ELEVEN_API_KEY = os.getenv("ELEVENLABS_API_KEY")
VOICE_ID = "EXAVITQu4vr4xnSDxMaL"  # Default “Rachel” voice – replace with your cloned voice ID

ELEVEN_ENDPOINT = f"https://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}"

HEADERS = {
    "xi-api-key": ELEVEN_API_KEY,
    "Content-Type": "application/json"
}

@app.route("/speak", methods=["POST"])
def speak():
    data = request.get_json()
    text = data.get("text", "")
    if not text:
        return jsonify({"error": "No text provided"}), 400

    payload = {
        "text": text,
        "model_id": "eleven_monolingual_v1",
        "voice_settings": {"stability": 0.75, "similarity_boost": 0.85}
    }

    response = requests.post(ELEVEN_ENDPOINT, json=payload, headers=HEADERS, stream=True)
    if response.status_code != 200:
        return jsonify({"error": "ElevenLabs API failure", "details": response.text}), 502

    # Stream the MP3 back to the client
    audio_bytes = BytesIO(response.content)
    return send_file(audio_bytes, mimetype="audio/mpeg", as_attachment=False, download_name="output.mp3")

if __name__ == "__main__":
    # For local testing only; production will be served by the web server
    app.run(host="0.0.0.0", port=5000, debug=True)
Enter fullscreen mode Exit fullscreen mode

What the code does

  • Accepts a JSON payload like { "text": "Hello, world!" }.
  • Calls ElevenLabs with the supplied text, using the voice you cloned (replace VOICE_ID with your own).
  • Streams the resulting MP3 back to the caller, so the front‑end can play it instantly.

You can test it locally with curl:

curl -X POST http://127.0.0.1:5000/speak \
  -H "Content-Type: application/json" \
  -d '{"text":"Welcome to my voice cloning demo!"}' \
  --output demo.mp3
Enter fullscreen mode Exit fullscreen mode

If demo.mp3 plays, you’re ready for the next step.


3. Add a Simple Front‑End

A single HTML page is enough to showcase the demo. Save this as templates/index.html (Flask will auto‑discover it).

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Voice Clone Demo</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 600px; margin: 2rem auto; }
    textarea { width: 100%; height: 120px; }
    button { padding: 0.5rem 1rem; margin-top: 0.5rem; }
    audio { width: 100%; margin-top: 1rem; }
  </style>
</head>
<body>
  <h1>🔊 Voice Clone Demo</h1>
  <p>Type something and hear it spoken in a cloned voice powered by <a href="https://try.elevenlabs.io/kr07zfuqn1bp">ElevenLabs</a>.</p>

  <textarea id="text" placeholder="Enter text here..."></textarea><br>
  <button id="speakBtn">Speak</button>

  <audio id="player" controls hidden></audio>

  <script>
    document.getElementById('speakBtn').addEventListener('click', async () => {
      const txt = document.getElementById('text').value.trim();
      if (!txt) return alert('Please enter some text');

      const res = await fetch('/speak', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ text: txt })
      });

      if (!res.ok) {
        const err = await res.json();
        return alert('Error: ' + err.error);
      }

      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const player = document.getElementById('player');
      player.src = url;
      player.hidden = false;
      player.play();
    });
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Add a route in app.py to serve the page:

@app.route("/", methods=["GET"])
def index():
    return app.send_static_file("templates/index.html")
Enter fullscreen mode Exit fullscreen mode

Now python app.py will spin up a local web UI at http://localhost:5000.


4. Deploy to Bluehost – No Docker, No Headaches

Bluehost isn’t just for WordPress; they also provide shared Linux hosting with SSH access, which is perfect for a Flask app when you use Passenger (a lightweight WSGI server). Here’s why Bluehost shines for this use‑case:

  • One‑click SSL – your voice demo will be served over HTTPS automatically.
  • Affordable plans – start at under $5/month and you get a domain, email, and 50 GB of storage.
  • Straightforward file manager – upload your code via FTP or the built‑in file manager; no complex CI pipelines required.

Step‑by‑step deployment

  1. Create a Bluehost account (use this link for the discount): https://bluehost.sjv.io/5k0d52
  2. In the Bluehost dashboard, enable SSH access (found under Advanced �� SSH Access).
  3. Open an SSH session:
   ssh yourusername@yourdomain.com
Enter fullscreen mode Exit fullscreen mode
  1. Clone or upload your project. If you have a Git repo:
   git clone https://github.com/yourname/voice-clone-demo.git
   cd voice-clone-demo
Enter fullscreen mode Exit fullscreen mode
  1. Create a virtual environment on the server (Bluehost’s shared PHP environment also supports Python):
   python3 -m venv venv
   source venv/bin/activate
   pip install -r requirements.txt   # Flask, requests
Enter fullscreen mode Exit fullscreen mode
  1. Add your ElevenLabs API key to the environment:
   echo 'export ELEVENLABS_API_KEY="YOUR_KEY_HERE"' >> ~/.bashrc
   source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode
  1. Tell Passenger how to run the app – create a passenger_wsgi.py file in the project root:
   from app import app as application
Enter fullscreen mode Exit fullscreen mode
  1. Point your domain to the folder: In the Bluehost File Manager, place the project inside public_html/voice-demo/. Then, in Advanced → Domains, set the document root for your sub‑domain (e.g., demo.yourdomain.com) to that folder.

  2. Restart Passenger (simply touch the tmp/restart.txt file):

   mkdir -p tmp
   touch tmp/restart.txt
Enter fullscreen mode Exit fullscreen mode

That’s it! Visit https://demo.yourdomain.com and you should see the UI, ready to generate cloned speech on the fly.


5. Tweaking for Production

  • Rate limiting – protect your API key by adding a simple Flask‑Limiter or Cloudflare rule.
  • Caching – store generated MP3s for repeated sentences to cut down on API calls.
  • Custom domain – Bluehost makes it trivial to bind a custom domain, giving your demo a professional look.

6. What You’ve Learned

  • How to call ElevenLabs’ voice‑cloning endpoint from Python.
  • Building a minimal Flask service that streams audio.
  • Deploying a Python web app on a shared host with Bluehost, without needing a full VPS.

Both tools keep the focus on developer productivity: ElevenLabs handles the heavy‑lifting of high‑quality TTS, while Bluehost removes the friction of server management.


Next Steps

Ready to turn this demo into a full‑blown product? Consider:

  • Adding user authentication so each person can upload their own voice sample.
  • Integrating with a front‑end framework like React for a richer UI.
  • Using a job queue (e.g., Redis + RQ) for longer audio generation tasks.

Give it a spin! Grab your free ElevenLabs API key at https://try.elevenlabs.io/kr07zfuqn1bp and launch the demo on Bluehost with https://bluehost.sjv.io/5k0d52. Happy cloning!

Top comments (0)