Why Add AI Narration to Your Blog?
If you’ve ever scrolled through a long article and thought, “I wish I could listen to this while I’m cooking or jogging,” you’re not alone. Voice‑enabled content is exploding—think podcasts, audiobooks, and even AI‑generated narrations that turn any text into a natural‑sounding voice. Adding an audio version of each post can:
- Boost SEO (Google likes rich media)
- Increase accessibility for visually‑impaired readers
- Keep visitors on your site longer, which improves engagement metrics
- Open a new channel for content distribution (e.g., you can embed the audio in newsletters or social posts)
In this post I’ll walk you through a complete, end‑to‑end setup that lets you automatically generate a spoken version of every new blog entry, host it on a cheap but reliable platform, and embed the audio player right in your article. The stack is intentionally simple:
| Component | What it does | Why we like it |
|---|---|---|
| ElevenLabs | State‑of‑the‑art text‑to‑speech (TTS) and voice cloning | Natural, expressive voices; generous free tier; easy HTTP API |
| Python | Glue code that pulls the latest post, calls the TTS API, and uploads the MP3 | Quick to prototype, widely available |
| Bluehost | Shared hosting that supports Python scripts (via SSH) and static site hosting | Affordable, one‑click WordPress install, and a friendly UI for beginners |
TL;DR – Use ElevenLabs for the narration, write a small Python script to fetch your post and generate an MP3, then push the file to a Bluehost site where you embed a simple HTML5 player.
1. Get Your ElevenLabs API Key
Head over to the ElevenLabs sign‑up page: https://try.elevenlabs.io/kr07zfuqn1bp. After confirming your email you’ll land on the dashboard where you can create an API key. Keep this key secret—treat it like a password.
Tip: Store the key in an environment variable (
ELEVENLABS_API_KEY) rather than hard‑coding it. This keeps your repo clean and prevents accidental leaks.
2. Set Up a Basic Python Project
Create a new folder for the project and initialize a virtual environment:
mkdir voice-blog
cd voice-blog
python3 -m venv .venv
source .venv/bin/activate
pip install requests python-dotenv
Create a .env file (make sure you add it to .gitignore) and paste your API key:
ELEVENLABS_API_KEY=your_api_key_here
Install python-dotenv so the script can read it automatically.
3. Pull the Latest Blog Post
For this tutorial I’ll assume you’re using a static Markdown‑based blog (e.g., Jekyll, Hugo, or a simple Markdown folder). The script below reads the most recent .md file, strips the front‑matter, and returns the raw text.
import os
import glob
import re
from pathlib import Path
def get_latest_post():
md_files = sorted(Path("posts").glob("*.md"), key=os.path.getmtime, reverse=True)
if not md_files:
raise FileNotFoundError("No markdown files found in ./posts")
latest = md_files[0]
with open(latest, "r", encoding="utf-8") as f:
content = f.read()
# Remove YAML front‑matter if present
cleaned = re.sub(r"^---.*?---\s*", "", content, flags=re.DOTALL)
return cleaned.strip(), latest.stem # returns (text, slug)
text, slug = get_latest_post()
print(f"Generating narration for: {slug}")
Feel free to replace the file‑system logic with a WordPress REST call or any CMS API you prefer.
4. Call ElevenLabs to Generate Speech
ElevenLabs provides a straightforward /v1/text-to-speech/{voice_id} endpoint. Below is a minimal curl‑style request wrapped in Python using requests.
import requests
import json
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv("ELEVENLABS_API_KEY")
VOICE_ID = "EXAVITQu4vr4xnSDxMaL" # default “Rachel” voice – change as you like
def synthesize(text, output_path):
url = f"https://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}"
headers = {
"xi-api-key": API_KEY,
"Content-Type": "application/json"
}
payload = {
"text": text,
"model_id": "eleven_multilingual_v2",
"voice_settings": {
"stability": 0.75,
"similarity_boost": 0.85
}
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
# The API returns raw audio bytes (MP3)
with open(output_path, "wb") as out_file:
out_file.write(response.content)
print(f"Saved audio to {output_path}")
audio_file = f"public/audio/{slug}.mp3"
synthesize(text, audio_file)
Why ElevenLabs? Their voices sound genuinely human, they support multiple languages out of the box, and the API is fast enough for on‑the‑fly generation. You can experiment with different voice IDs or even upload a custom voice clone if you have a sample of your own speaking style. Check out the full docs at https://try.elevenlabs.io/kr07zfuqn1bp.
5. Deploy the Audio Files on Bluehost
If you already have a WordPress blog on Bluehost, simply drop the generated MP3 into the wp-content/uploads folder via FTP or the file manager. For static sites, the public/audio folder we used above maps directly to a public URL.
Quick deployment steps
- Create a Bluehost account – use the affiliate link for a discount: https://bluehost.sjv.io/5k0d52.
- In the Bluehost dashboard, enable SSH Access (found under “Advanced → SSH Access”). This lets you run the Python script directly on the server if you prefer.
- Upload your
public/audiodirectory (or just the new MP3) using the File Manager or an SFTP client. - Make sure the file permissions are set to
644so the browser can fetch it.
Pro tip: Set up a cron job in Bluehost’s “Cron Jobs” UI to run the script nightly. That way every new post automatically gets an audio version without manual intervention.
6. Embed the Player in Your Blog Post
Now that the MP3 lives at something like https://yourdomain.com/audio/my‑post.mp3, you can embed a native HTML5 player directly in the Markdown file (or via a WordPress block).
<audio controls preload="none" style="width: 100%;">
<source src="https://yourdomain.com/audio/{{ slug }}.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
If you’re using a static site generator, replace {{ slug }} with the appropriate variable syntax (e.g., {{ .Slug }} for Hugo). The player will appear right beneath the article title, giving readers a one‑click way to listen.
7. Automate the Whole Pipeline (Optional)
For a fully hands‑off workflow you can combine everything into a single script and trigger it via a webhook whenever you push a new post to Git. Here’s a high‑level view:
#!/usr/bin/env bash
# 1. Pull latest changes
git pull origin main
# 2. Run the Python generator
source .venv/bin/activate
python generate_narration.py
# 3. Upload the MP3 via rsync (Bluehost supports SSH)
rsync -avz public/audio/ user@yourdomain.com:/home/username/public_html/audio/
Add the script to a GitHub Action or a Bluehost cron job, and you’ve got a self‑maintaining voice‑enabled blog.
8. Troubleshooting Common Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
401 Unauthorized from ElevenLabs |
Wrong or missing API key | Verify ELEVENLABS_API_KEY in .env and that the environment variable is loaded |
| Audio file is garbled or silent | Incorrect voice_settings or model ID |
Try the default settings or test with the ElevenLabs playground first |
| MP3 not loading on the page | File not uploaded or wrong URL | Double‑check the path you used in the <audio> tag matches the location on Bluehost |
| Cron job never runs | Wrong path to Python binary | Use the full path (/home/username/.venv/bin/python) in the cron entry |
9. Scaling Up
If your blog starts receiving thousands of daily reads, consider:
- Caching the generated MP3s on a CDN (Bluehost CDN add‑on works well).
- Batch processing – generate narrations in bulk during off‑peak hours.
- Custom voice cloning – ElevenLabs lets you train a voice on your own recordings, giving your brand a unique sound.
10. Wrap‑Up & Next Steps
You now have a functional pipeline:
- Write a post →
- Python script pulls the markdown →
- ElevenLabs turns the text into an MP3 →
- The file lands on a Bluehost‑hosted site →
- Readers click the embedded player and listen.
Give it a spin! The combination of ElevenLabs for high‑quality AI narration and Bluehost for low‑cost, hassle‑free hosting makes voice‑enabled blogging accessible to anyone with a laptop.
Ready to make your blog talk?
Start by signing up for ElevenLabs here: https://try.elevenlabs.io/kr07zfuqn1bp and grab a reliable, affordable hosting plan at Bluehost: https://bluehost.sjv.io/5k0d52. Happy coding, and enjoy the sound of your own words!
Top comments (0)