Why a Voice‑Powered News Reader?
Imagine you’re cooking, jogging, or just want to give your eyes a break. A quick “Hey, read me the headlines” and you’re instantly up‑to‑date. Building a voice‑driven news reader is a fun way to explore text‑to‑speech (TTS), voice cloning, and the APIs that make them tick. In this guide we’ll stitch together a simple Python backend that pulls the latest stories from a news API, sends the text to ElevenLabs for lifelike speech, and streams the audio to a minimal web UI.
Pro tip: ElevenLabs’ neural TTS is known for natural prosody and supports custom voice cloning, making it perfect for a personal news companion.
What You’ll Need
| Component | Reason |
|---|---|
| Python 3.9+ | Core scripting language |
| Requests library | Call external APIs (news, ElevenLabs) |
| FastAPI (or Flask) | Tiny web server to serve audio files |
| HTML/JS | Simple front‑end to trigger playback |
| ElevenLabs API key | Convert text → high‑quality audio |
| NewsAPI.org (or any free news source) | Source of headline text |
All of these are free or have generous free tiers. Sign up for an ElevenLabs account using the affiliate link below to get your API key instantly:
👉 https://try.elevenlabs.io/kr07zfuqn1bp
1. Grab the Latest Headlines
We’ll use the free tier of NewsAPI.org. Sign up, grab a key, and store it in an environment variable called NEWS_API_KEY.
# news_fetcher.py
import os
import requests
NEWS_API_KEY = os.getenv("NEWS_API_KEY")
BASE_URL = "https://newsapi.org/v2/top-headlines"
def get_headlines(country="us", max_items=5):
params = {
"apiKey": NEWS_API_KEY,
"country": country,
"pageSize": max_items,
}
resp = requests.get(BASE_URL, params=params)
resp.raise_for_status()
data = resp.json()
# Return a simple list of title strings
return [article["title"] for article in data["articles"]]
Running get_headlines() now gives you a list like:
[
"NASA announces new moon mission",
"Stock markets rally after earnings season",
...
]
2. Turn Text into Speech with ElevenLabs
ElevenLabs offers a straightforward REST endpoint. The following curl example shows the raw request:
curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/EXAMPLE_VOICE_ID" \
-H "xi‑api‑key: YOUR_ELEVENLABS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Your headline goes here",
"voice_settings": {
"stability": 0.75,
"similarity_boost": 0.85
}
}' \
--output headline.mp3
Replace EXAMPLE_VOICE_ID with the ID of a default voice (e.g., en_us_001). The response is an MP3 file you can play directly.
Python Wrapper
If you prefer staying in Python, here’s a tiny helper:
# tts.py
import os
import requests
ELEVEN_API_KEY = os.getenv("ELEVENLABS_API_KEY")
VOICE_ID = "en_us_001" # default voice; you can clone your own later
def text_to_speech(text: str, output_path: str):
url = f"https://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}"
payload = {
"text": text,
"voice_settings": {"stability": 0.75, "similarity_boost": 0.85},
}
headers = {
"xi-api-key": ELEVEN_API_KEY,
"Content-Type": "application/json",
}
resp = requests.post(url, json=payload, headers=headers)
resp.raise_for_status()
with open(output_path, "wb") as f:
f.write(resp.content)
Now you can generate an audio file for each headline:
from news_fetcher import get_headlines
from tts import text_to_speech
headlines = get_headlines()
for i, title in enumerate(headlines):
text_to_speech(title, f"audio_{i}.mp3")
3. Voice Cloning (Optional but Cool)
ElevenLabs lets you upload a short voice sample (≈30 seconds) and receive a custom VOICE_ID. This is handy if you want the news read in your voice.
- Record a WAV/MP3 of yourself speaking naturally.
- Use the Create Voice endpoint:
curl -X POST "https://api.elevenlabs.io/v1/voices/add" \
-H "xi-api-key: YOUR_ELEVENLABS_API_KEY" \
-F "name=MyVoice" \
-F "files=@/path/to/voice_sample.wav"
The response contains a voice_id. Swap VOICE_ID in tts.py with that ID, and every article will now sound like you.
4. Serve the Audio via FastAPI
A lightweight API makes the front‑end feel snappy. We’ll bundle the headline fetch and TTS into a single endpoint that returns the MP3 data.
# server.py
import os
import uuid
from fastapi import FastAPI, Response
from news_fetcher import get_headlines
from tts import text_to_speech
app = FastAPI()
TMP_DIR = "./tmp"
os.makedirs(TMP_DIR, exist_ok=True)
@app.get("/news-audio")
def news_audio():
headlines = get_headlines()
# Concatenate all headlines into one paragraph
full_text = ". ".join(headlines) + "."
filename = f"{TMP_DIR}/{uuid.uuid4()}.mp3"
text_to_speech(full_text, filename)
with open(filename, "rb") as f:
audio_bytes = f.read()
# Clean up the temp file
os.remove(filename)
return Response(content=audio_bytes, media_type="audio/mpeg")
Run it with:
uvicorn server:app --reload
Visit http://localhost:8000/news-audio and you’ll hear the latest headlines spoken back to you.
5. Minimal Front‑End
A single HTML file can trigger the audio fetch and play it automatically.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Voice News Reader</title>
</head>
<body>
<h1>🗞️ Voice‑Powered News</h1>
<button id="readBtn">Read Latest Headlines</button>
<audio id="player" controls></audio>
<script>
const btn = document.getElementById('readBtn');
const player = document.getElementById('player');
btn.onclick = async () => {
btn.disabled = true;
btn.textContent = 'Fetching…';
const resp = await fetch('http://localhost:8000/news-audio');
const blob = await resp.blob();
player.src = URL.createObjectURL(blob);
player.play();
btn.textContent = 'Read Again';
btn.disabled = false;
};
</script>
</body>
</html>
Open the file in a browser, click Read Latest Headlines, and you’ll hear the news narrated by ElevenLabs’ high‑fidelity voice.
6. Polishing the Experience
- Cache audio: Store the generated MP3 for a few minutes to avoid repeated TTS calls (they count against your quota).
-
Add a language selector: Pass a
languageparam to NewsAPI and switch the ElevenLabs voice accordingly. - Error handling: Gracefully handle network hiccups and display fallback text.
7. Going Further
- Push notifications: Combine with a service worker to alert users when a new audio version is ready.
- Voice commands: Use the Web Speech API to let users say “Read me the tech news” and filter categories on the fly.
- Multi‑speaker podcasts: Clone multiple voices (e.g., one for sports, another for finance) to give each section a distinct personality.
Wrap‑Up & Call to Action
You now have a fully functional voice‑powered news reader that pulls fresh headlines, transforms them into natural‑sounding speech, and streams the result to any browser. The heavy lifting is done by ElevenLabs, whose neural TTS and voice cloning capabilities bring a human‑like feel to your app.
Ready to give your users (or yourself) a hands‑free news experience? Grab your ElevenLabs API key via the affiliate link below, spin up the code, and start experimenting with custom voices.
🚀 Try ElevenLabs today and make your news reader sound amazing: https://try.elevenlabs.io/kr07zfuqn1bp
Top comments (0)