Why an Audiobook Generator?
If you’ve ever tried to turn a long‑form article, a novel, or a collection of blog posts into an audio format, you know the pain of finding a natural‑sounding TTS engine, handling chunking, and stitching the pieces together. With modern voice AI, you can automate the whole pipeline and produce a polished audiobook in minutes. In this post we’ll walk through building a simple Audiobook Generator that pulls text from a file, sends it to the ElevenLabs API, and assembles the resulting audio files into a single MP3.
Tip: The ElevenLabs platform offers a free tier that’s generous enough for hobby projects and rapid prototyping. Grab your API key here: https://try.elevenlabs.io/kr07zfuqn1bp.
What You’ll Need
| Item | Reason |
|---|---|
| Python 3.8+ | Easy HTTP client (requests) and audio handling (pydub). |
| An ElevenLabs API key | To access the TTS endpoint. |
| A text source (plain‑text, markdown, or PDF) | The content you want to narrate. |
ffmpeg installed |
Required by pydub to manipulate audio files. |
You can also replace Python with Node.js or plain curl if you prefer, but the example below sticks with Python for brevity.
Step 1: Grab Your ElevenLabs API Key
- Sign up (or log in) at the ElevenLabs developer portal: https://try.elevenlabs.io/kr07zfuqn1bp.
- Navigate to API Keys → Create new key.
- Copy the key; you’ll need it as an environment variable:
export ELEVENLABS_API_KEY="your_secret_key_here"
Step 2: Install the Dependencies
pip install requests pydub tqdm
# On macOS/Linux you may need to install ffmpeg via brew/apt:
# brew install ffmpeg # macOS
# sudo apt-get install ffmpeg # Ubuntu
Step 3: Chunk the Text
Audiobook‑style TTS works best when you feed the API reasonably sized chunks (≈ 2 000 characters). Too long and you risk hitting the request limit; too short and you waste time on extra HTTP calls.
import re
def chunk_text(text, max_len=2000):
# Split on paragraph boundaries first
paragraphs = text.split("\n\n")
chunks = []
current = ""
for para in paragraphs:
if len(current) + len(para) + 2 <= max_len:
current += para + "\n\n"
else:
chunks.append(current.strip())
current = para + "\n\n"
if current:
chunks.append(current.strip())
return chunks
Step 4: Call the ElevenLabs TTS Endpoint
Here’s a minimal wrapper that sends a chunk to ElevenLabs and returns the raw MP3 bytes.
import os
import requests
from tqdm import tqdm
ELEVEN_API_URL = "https://api.elevenlabs.io/v1/text-to-speech"
VOICE_ID = "EXAVITQu4vr4xnSDxMaL" # default “Rachel” voice �� change as you like
def synthesize(chunk, output_path):
headers = {
"xi-api-key": os.getenv("ELEVENLABS_API_KEY"),
"Content-Type": "application/json"
}
payload = {
"text": chunk,
"voice_settings": {
"stability": 0.75,
"similarity_boost": 0.75
}
}
resp = requests.post(
f"{ELEVEN_API_URL}/{VOICE_ID}",
json=payload,
headers=headers,
stream=True
)
resp.raise_for_status()
with open(output_path, "wb") as f:
for data in resp.iter_content(chunk_size=8192):
f.write(data)
def synthesize_all(chunks, out_dir="chunks"):
os.makedirs(out_dir, exist_ok=True)
for i, chunk in enumerate(tqdm(chunks, desc="Synthesizing")):
out_file = os.path.join(out_dir, f"part_{i:04d}.mp3")
synthesize(chunk, out_file)
Note: The
voice_settingsparameters let you tweak the output’s stability and similarity boost. Experiment to find the sweet spot for your material.
Step 5: Stitch the Audio Together
Once each chunk is saved as an MP3, we can concatenate them using pydub.
from pydub import AudioSegment
import glob
def merge_chunks(chunk_dir="chunks", output_file="audiobook.mp3"):
combined = AudioSegment.empty()
for mp3_path in sorted(glob.glob(os.path.join(chunk_dir, "part_*.mp3"))):
segment = AudioSegment.from_mp3(mp3_path)
combined += segment
combined.export(output_file, format="mp3")
print(f"✅ Audiobook saved as {output_file}")
Full Script in One Place
import os
import sys
from pathlib import Path
# ---- Configuration ----
TEXT_FILE = sys.argv[1] if len(sys.argv) > 1 else "book.txt"
OUTPUT_FILE = "my_audiobook.mp3"
# ------------------------
def main():
# 1️⃣ Load the source text
text = Path(TEXT_FILE).read_text(encoding="utf-8")
# 2️⃣ Chunk it
chunks = chunk_text(text)
# 3️⃣ Generate audio for each chunk
synthesize_all(chunks, out_dir="chunks")
# 4️⃣ Merge into final MP3
merge_chunks(chunk_dir="chunks", output_file=OUTPUT_FILE)
if __name__ == "__main__":
main()
Run it like:
python audiobook_generator.py my_novel.txt
You’ll end up with a single my_audiobook.mp3 ready for upload to your favorite podcast host, Audible, or personal library.
Optional: Voice Cloning for a Custom Narrator
ElevenLabs also lets you clone a voice from a short (~30 s) recording. If you have a brand voice or want to sound like a favorite author, follow the steps in the dashboard to upload the sample and retrieve a new VOICE_ID. Swap the VOICE_ID constant in the script with the cloned ID, and you’re good to go.
Using Curl (If You Prefer a Quick Test)
Sometimes you just want to verify the endpoint works without writing code. Here’s a one‑liner that sends a short sentence and saves the MP3:
curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/EXAVITQu4vr4xnSDxMaL" \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Hello, world! This is a quick test of the ElevenLabs API."}' \
--output hello.mp3
Replace EXAVITQu4vr4xnSDxMaL with your custom voice ID if you’ve cloned one.
Deploying as a Small Web Service
If you want to expose the generator as an API (e.g., to let users upload their own texts), Flask or FastAPI are perfect companions. Below is a tiny FastAPI endpoint that accepts raw text and returns the generated MP3 stream:
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
import io
app = FastAPI()
@app.post("/generate")
async def generate(text: str):
chunks = chunk_text(text)
# Store temporary audio in memory
buffer = io.BytesIO()
combined = AudioSegment.empty()
for i, chunk in enumerate(chunks):
# Re‑use the synthesize function but write to a BytesIO
audio_bytes = requests.post(
f"{ELEVEN_API_URL}/{VOICE_ID}",
json={"text": chunk},
headers={"xi-api-key": os.getenv("ELEVENLABS_API_KEY")},
).content
combined += AudioSegment.from_mp3(io.BytesIO(audio_bytes))
combined.export(buffer, format="mp3")
buffer.seek(0)
return StreamingResponse(buffer, media_type="audio/mpeg")
Deploy to Render, Fly.io, or any container platform, and you have a fully functional audiobook‑as‑a‑service.
Wrapping Up
Building an audiobook generator is surprisingly straightforward when you have a high‑quality TTS engine at your fingertips. With just a few lines of Python and the power of ElevenLabs (https://try.elevenlabs.io/kr07zfuqn1bp), you can:
- Turn any plain‑text source into a natural‑sounding narration.
- Control voice stability and similarity to match the mood of your content.
- Optionally clone a custom voice for brand‑specific audio.
All of this runs on modest hardware, and the free tier covers a decent amount of minutes per month—perfect for indie authors, educators, or anyone looking to add audio to their product.
🎧 Ready to give it a spin?
Grab your API key, clone the repo, and start turning words into sound. The ElevenLabs platform makes high‑fidelity voice synthesis accessible, so you can focus on the story, not the tech. Happy coding, and enjoy listening to the results! 🚀
Try ElevenLabs now: https://try.elevenlabs.io/kr07zfuqn1bp
Top comments (0)