DEV Community

VoiceDeveloper
VoiceDeveloper

Posted on

How to Host an AI Podcast Platform on Bluehost

Why a Voice‑AI Podcast Platform?

Podcasting is exploding, but producing high‑quality audio still takes a lot of time and equipment. With modern text‑to‑speech (TTS) and voice‑cloning services you can turn a markdown script into a fully‑produced episode in minutes. In this guide we’ll walk through:

  1. Generating lifelike narration with ElevenLabs.
  2. Stitching together intro/outro music, ads, and the AI‑generated speech.
  3. Deploying the whole thing on Bluehost, the cheap‑and‑cheerful host that makes a Python/Flask app feel like a one‑click install.

By the end you’ll have a tiny web service that accepts a podcast script (or a URL to a markdown file) and returns a downloadable MP3 ready for publishing.


What You’ll Need

Item Reason
ElevenLabs API key – sign up at https://try.elevenlabs.io/kr07zfuqn1bp Gives you access to state‑of‑the‑art TTS and voice cloning.
Python 3.9+ Core language for the demo.
Flask (or FastAPI) Minimal web framework to expose a REST endpoint.
FFmpeg Concatenates audio segments and normalises volume.
Bluehost account – get one at https://bluehost.sjv.io/5k0d52 Provides the cheap, easy‑to‑use hosting environment for our app.
Git (optional) For version control and quick deployment.

1. Hooking Into ElevenLabs

ElevenLabs offers a straightforward REST API. Below is a minimal Python wrapper that sends a text payload and streams back an MP3 file.

import os
import requests

ELEVEN_API_KEY = os.getenv("ELEVEN_API_KEY")
BASE_URL = "https://api.elevenlabs.io/v1"

def generate_speech(text: str, voice_id: str = "default") -> bytes:
    """
    Calls ElevenLabs TTS and returns raw MP3 bytes.
    """
    endpoint = f"{BASE_URL}/text-to-speech/{voice_id}"
    headers = {
        "xi-api-key": ELEVEN_API_KEY,
        "Content-Type": "application/json",
        "Accept": "audio/mpeg"
    }
    payload = {
        "text": text,
        "model_id": "eleven_monolingual_v1",
        "voice_settings": {"stability": 0.75, "similarity_boost": 0.85}
    }

    response = requests.post(endpoint, json=payload, headers=headers)
    response.raise_for_status()
    return response.content
Enter fullscreen mode Exit fullscreen mode

Tip: If you want a custom cloned voice, create it in the ElevenLabs dashboard and replace voice_id with the ID you receive.

You can test the function locally:

export ELEVEN_API_KEY=your_key_here
python - <<'PY'
from __main__ import generate_speech
audio = generate_speech("Hello, this is a test of ElevenLabs text‑to‑speech.")
open("test.mp3", "wb").write(audio)
print("Saved test.mp3")
PY
Enter fullscreen mode Exit fullscreen mode

Play test.mp3 to hear the result. The quality is comparable to a human narrator, and the API is priced per character, making it cheap for short‑form podcasts.


2. Building the Podcast Generator

Our Flask app will accept a JSON payload like:

{
  "title": "AI Podcast 101",
  "script_url": "https://example.com/episode1.md",
  "intro_music_url": "https://example.com/intro.mp3",
  "outro_music_url": "https://example.com/outro.mp3"
}
Enter fullscreen mode Exit fullscreen mode

The flow:

  1. Download the markdown script.
  2. Convert the markdown to plain text (using markdown2).
  3. Call generate_speech for the main body.
  4. Download intro/outro MP3s.
  5. Concatenate everything with ffmpeg.

Full Flask Example

# app.py
import os, subprocess, tempfile, requests, markdown2
from flask import Flask, request, send_file, jsonify

app = Flask(__name__)

ELEVEN_API_KEY = os.getenv("ELEVEN_API_KEY")
if not ELEVEN_API_KEY:
    raise RuntimeError("Set ELEVEN_API_KEY env var")

# Re‑use the generate_speech function from earlier
from __main__ import generate_speech  # assume same file for brevity

def download(url: str) -> bytes:
    r = requests.get(url)
    r.raise_for_status()
    return r.content

def concat_audios(parts: list[bytes]) -> bytes:
    """
    Takes a list of raw MP3 bytes, writes them to temp files,
    and returns a single concatenated MP3 using ffmpeg.
    """
    with tempfile.TemporaryDirectory() as td:
        paths = []
        for i, data in enumerate(parts):
            p = os.path.join(td, f"part{i}.mp3")
            open(p, "wb").write(data)
            paths.append(p)

        list_file = os.path.join(td, "list.txt")
        open(list_file, "w").write("\n".join([f"file '{p}'" for p in paths]))

        out_path = os.path.join(td, "out.mp3")
        cmd = [
            "ffmpeg", "-y", "-f", "concat", "-safe", "0",
            "-i", list_file, "-c", "copy", out_path
        ]
        subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return open(out_path, "rb").read()

@app.route("/generate", methods=["POST"])
def generate():
    data = request.json
    script_md = download(data["script_url"]).decode()
    script_text = markdown2.markdown(script_md, strip=True)  # strip HTML tags

    # 1️⃣ Intro
    intro = download(data["intro_music_url"])
    # 2️⃣ Main narration
    narration = generate_speech(script_text)
    # 3️⃣ Outro
    outro = download(data["outro_music_url"])

    final_mp3 = concat_audios([intro, narration, outro])

    return send_file(
        io.BytesIO(final_mp3),
        mimetype="audio/mpeg",
        as_attachment=True,
        download_name=f"{data['title']}.mp3"
    )

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
Enter fullscreen mode Exit fullscreen mode

Dependencies

pip install flask requests markdown2
# ffmpeg must be installed on the system (apt-get install ffmpeg or brew install ffmpeg)
Enter fullscreen mode Exit fullscreen mode

Run locally with python app.py and POST a JSON payload to http://localhost:5000/generate. You’ll receive a ready‑to‑publish MP3.


3. Deploying to Bluehost

Why Bluehost?

  • Affordability – shared plans start under $5/month.
  • One‑click Python apps – the cPanel “Setup Python App” wizard creates a virtualenv, installs your requirements.txt, and maps a URL to a WSGI entry point.
  • Built‑in SSL – your podcast endpoint is automatically served over HTTPS, which is required for many browsers and API calls.

All of this can be done without touching a VPS console, making Bluehost the easy, affordable way to spin up a voice‑AI service.

Step‑by‑Step Deployment

  1. Create a Bluehost account – sign up via https://bluehost.sjv.io/5k0d52.
  2. In the Bluehost dashboard, go to Advanced → Python™ (Setup).
  3. Click Create Application:
  • Python version: 3.10 (or latest available).
  • App directory: ~/my-podcast.
  • App startup file: app.py.
  • WSGI file: flask_app.wsgi (Bluehost will generate it).
  1. Upload your project files (or clone from Git) into ~/my-podcast.
  2. Add a requirements.txt:
   Flask
   requests
   markdown2
Enter fullscreen mode Exit fullscreen mode
  1. Back in the Python app UI, click Enter Virtual Environment and run:
   pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode
  1. Install ffmpeg – Bluehost shared plans include ffmpeg via the package manager. If not, you can compile a static binary and place it in your app folder; the Flask code calls ffmpeg by name, so as long as it’s in the PATH it works.
  2. Set an environment variable for your ElevenLabs key:
   echo "export ELEVEN_API_KEY=your_key_here" >> ~/.bashrc
   source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode
  1. Hit Reload on the Python app page. Your endpoint will now be reachable at something like https://yourdomain.com/generate.

Testing on Bluehost

curl -X POST https://yourdomain.com/generate \
  -H "Content-Type: application/json" \
  -d '{
        "title": "AI Podcast 101",
        "script_url": "https://raw.githubusercontent.com/yourrepo/episode1.md",
        "intro_music_url": "https://example.com/intro.mp3",
        "outro_music_url": "https://example.com/outro.mp3"
      }' \
  --output episode1.mp3
Enter fullscreen mode Exit fullscreen mode

If the download succeeds, you’ve just built a fully‑hosted AI podcast generator with a few lines of code!


4. Going Further

  • Voice cloning – use ElevenLabs’ /voices endpoint to upload a few minutes of your own voice and generate a custom voice_id.
  • Dynamic ads – pull ad copy from a CMS, generate a short spot, and splice it in automatically.
  • Batch processing – schedule a cron job (Bluehost supports cron via cPanel) that reads a folder of markdown scripts and spits out a whole season at once.

All of these extensions sit on the same Flask base; you only need to add a few more routes or background workers.


Wrap‑Up & Call to Action

You now have a practical, production‑ready pipeline:

  1. Write a script in markdown.
  2. Let ElevenLabs (https://try.elevenlabs.io/kr07zfuqn1bp) turn it into natural‑sounding speech.
  3. Deploy the simple Flask service on Bluehost (https://bluehost.sjv.io/5k0d52) and expose a one‑click API for anyone on your team.

Give it a spin, tweak the voice settings, and start publishing AI‑generated episodes without ever stepping into a recording studio.

Ready to build? Grab your ElevenLabs API key and a Bluehost account today, and watch your podcast ideas come to life in seconds. Happy coding!

Top comments (0)