Why a Voice‑Powered News Reader?
Reading the morning headlines while you’re commuting, cooking, or hitting the gym can be a real productivity boost. With modern text‑to‑speech (TTS) engines, you can turn any article into natural‑sounding speech in just a few lines of code. In this tutorial we’ll build a voice‑powered news reader that:
- Pulls the latest headlines from a news API.
- Sends each article’s text to ElevenLabs, a state‑of‑the‑art TTS service.
- Streams the resulting audio back to your device (or saves it for later).
By the end you’ll have a reusable Python script you can extend into a desktop app, a CLI tool, or even a voice‑assistant skill.
Pro tip: ElevenLabs offers high‑quality voice cloning, so you can give your news reader a unique personality (or even mimic your own voice). Grab a free trial here: https://try.elevenlabs.io/kr07zfuqn1bp
1. Prerequisites
| What you need | Why |
|---|---|
| Python 3.9+ | Clean syntax and great async support |
requests library |
Simple HTTP calls to the news and TTS APIs |
| An API key for a news source (e.g., NewsAPI.org) | To fetch the latest articles |
| An ElevenLabs API key | To generate speech from text |
Install the Python dependencies:
pip install requests tqdm
tqdm is optional but gives us a nice progress bar when we download multiple audio files.
2. Fetching the Latest Headlines
We’ll use the free tier of NewsAPI.org. Sign up, grab your API key, and store it in an environment variable called NEWS_API_KEY.
import os
import requests
NEWS_ENDPOINT = "https://newsapi.org/v2/top-headlines"
COUNTRY = "us" # change to your preferred country code
def get_headlines():
params = {
"apiKey": os.getenv("NEWS_API_KEY"),
"country": COUNTRY,
"pageSize": 5 # limit to 5 articles for a quick demo
}
resp = requests.get(NEWS_ENDPOINT, params=params)
resp.raise_for_status()
data = resp.json()
return [(article["title"], article["description"] or "") for article in data["articles"]]
The function returns a list of (title, description) tuples. Feel free to adjust pageSize or add keywords to tailor the feed.
3. Setting Up ElevenLabs TTS
ElevenLabs makes it straightforward to turn text into speech via a REST endpoint. First, sign up at the affiliate link and copy your ElevenLabs API key into an environment variable called ELEVENLABS_API_KEY.
3.1 Choose a Voice
ElevenLabs provides a catalog of voices. For this tutorial we’ll use the default Bella voice, but you can swap in any voice ID you like.
DEFAULT_VOICE_ID = "EXAVITQu4vr4xnSDxMaL" # Bella (public demo voice)
3.2 The TTS Request
The API expects a JSON payload with the text and a few optional parameters (stability, similarity boost, etc.). Here’s a thin wrapper:
import json
from pathlib import Path
ELEVEN_ENDPOINT = "https://api.elevenlabs.io/v1/text-to-speech"
def synthesize(text: str, output_path: Path, voice_id: str = DEFAULT_VOICE_ID):
url = f"{ELEVEN_ENDPOINT}/{voice_id}"
headers = {
"xi-api-key": os.getenv("ELEVENLABS_API_KEY"),
"Content-Type": "application/json"
}
payload = {
"text": text,
"voice_settings": {
"stability": 0.75,
"similarity_boost": 0.75
}
}
response = requests.post(url, headers=headers, data=json.dumps(payload), stream=True)
response.raise_for_status()
# Stream the MP3 to disk
with open(output_path, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
Note: If you want to clone your own voice, check ElevenLabs’ voice‑cloning docs – the same endpoint works once you upload a few minutes of reference audio.
4. Putting It All Together
Now we’ll combine the news fetcher and the TTS function. For each article we’ll create a short script like:
“Title: … Summary: …”
and save the resulting MP3 in a output/ folder.
from tqdm import tqdm
from pathlib import Path
OUTPUT_DIR = Path("output")
OUTPUT_DIR.mkdir(exist_ok=True)
def main():
headlines = get_headlines()
for idx, (title, desc) in enumerate(tqdm(headlines, desc="Generating audio")):
# Build a concise script for the TTS engine
script = f"Title: {title}. Summary: {desc}"
# Clean up file name
safe_title = "".join(c if c.isalnum() else "_" for c in title)[:30]
out_file = OUTPUT_DIR / f"{idx+1}_{safe_title}.mp3"
synthesize(script, out_file)
print("\nAll done! 🎉 Find your audio files in the 'output' folder.")
if __name__ == "__main__":
main()
Run the script:
python news_reader.py
You should see a progress bar while the audio files are being generated. When it finishes, open any MP3 file – you’ll hear a crisp, natural voice reading the headlines.
5. Going Further
5.1 Add Voice Cloning
If you have a few minutes of your own voice recorded, ElevenLabs lets you create a custom voice ID. Replace DEFAULT_VOICE_ID with the new ID and the rest of the code stays the same. Imagine a news reader that sounds exactly like you!
5.2 Play Audio on the Fly
Instead of writing to disk, you can stream the audio directly to a player like pydub or playsound. Here’s a quick example with playsound:
from playsound import playsound
import io
def synthesize_stream(text: str, voice_id: str = DEFAULT_VOICE_ID):
url = f"{ELEVEN_ENDPOINT}/{voice_id}"
headers = {"xi-api-key": os.getenv("ELEVENLABS_API_KEY")}
resp = requests.post(url, headers=headers, json={"text": text}, stream=True)
resp.raise_for_status()
audio_bytes = io.BytesIO(resp.content)
playsound(audio_bytes) # playsound can accept a file‑like object on some platforms
5.3 Deploy as a Serverless Function
Wrap the whole flow in an AWS Lambda or Cloudflare Worker and expose a /news endpoint that returns an MP3 stream. That way any device with an HTTP client can request a fresh audio briefing.
6. Debugging Tips
| Issue | Likely Cause | Fix |
|---|---|---|
401 Unauthorized from ElevenLabs |
Wrong or missing API key | Double‑check ELEVENLABS_API_KEY env var |
| Empty audio file | Text too short (ElevenLabs requires > 10 characters) | Ensure you send a non‑empty string; you can prepend “News update:” |
| Rate‑limit errors from NewsAPI | Exceeded free tier quota | Reduce pageSize or add caching |
7. Wrap‑Up
You now have a functional voice‑powered news reader built with just a few Python libraries and the powerful ElevenLabs TTS engine. From here you can:
- Add a UI with
TkinterorStreamlit. - Integrate with smart speakers (Alexa, Google Home) using their respective SDKs.
- Personalize the voice with cloning so the app truly feels like yours.
Ready to give your app a human touch? Try ElevenLabs today and hear the difference for yourself: https://try.elevenlabs.io/kr07zfuqn1bp
Happy coding! 🚀
Top comments (0)