Technology
Create a Voice-Powered News Reader App
Source: Dev Community|
6 min read
Why a Voice‑Powered News Reader? Reading the headlines while you’re on a commute, cooking, or just resting your eyes can be a game‑changer. With a few APIs and a little JavaScript or Python, you can turn any RSS feed or news service into an on‑demand audio companion. The heavy lifting—converting clean text into natural‑sounding speech—can be handled by modern TTS platforms, and ElevenLabs (https://try.elevenlabs.io/kr07zfuqn1bp) is currently one of the most realistic voice‑cloning services out there. In this guide we’ll stitch together: A news source (e.g., NewsAPI) A backend that fetches the articles and calls ElevenLabs for speech A lightweight front‑end that streams the audio to the user By the end you’ll have a minimal but functional “read me the news” app that you can extend into a full‑blown product. Prerequisites What you need Why Python 3.9+ (or Node.js) To run the backend that talks to the news API and ElevenLabs NewsAPI key (free tier works) Provides JSON headlines and snippets ElevenLabs API key Generates high‑quality audio from text Basic HTML/JS knowledge To build the front‑end player If you don’t have a NewsAPI key yet, sign up at https://newsapi.org/. For ElevenLabs, grab an API key from the dashboard after you sign up via the affiliate link above. 1. Pulling the Latest Headlines Let’s start with a tiny Python script that grabs the top headlines for a given topic. We’ll keep the response lean—just the title and a short description—so the generated audio stays under a minute per article. # news_fetcher.py import os import requests NEWS_API_KEY = os.getenv("NEWSAPI_KEY") BASE_URL = "https://newsapi.org/v2/top-headlines" def get_headlines(country="us", category="technology", limit=5): params = { "apiKey": NEWS_API_KEY, "country": country, "category": category, "pageSize": limit, } resp = requests.get(BASE_URL, params=params) data = resp.json() articles = [ { "title": a["title"], "description": a["description"] or "", for a in data["articles"] ] return articles if __name__ == "__main__": for art in get_headlines(): print(f"🗞️ {art['title']}\n{art['description']}\n") Save this as news_fetcher.py, export your keys (export NEWSAPI_KEY=…), and run it. You should see a list of headlines printed to the console. 2. Turning Text into Speech with ElevenLabs ElevenLabs offers a straightforward REST endpoint. Below is a minimal wrapper that sends a piece of text and receives a presigned URL to the generated audio file. # tts_client.py ELEVEN_API_KEY = os.getenv("ELEVENLABS_KEY") BASE_URL = "https://api.elevenlabs.io/v1" def generate_speech(text, voice_id="EXAVITQu4vr4xnSDxMaL"): """ voice_id = default "Rachel" voice. You can replace it with any cloned voice you own. endpoint = f"{BASE_URL}/text-to-speech/{voice_id}" headers = { "xi-api-key": ELEVEN_API_KEY, "Content-Type": "application/json", payload = { "text": text, "model_id": "eleven_monolingual_v1", "voice_settings": {"stability": 0.75, "similarity_boost": 0.75}, resp = requests.post(endpoint, json=payload, headers=headers, timeout=30) # The API returns raw MP3 bytes; we’ll stream them back to the client. return resp.content Note: The default voice is “Rachel”. If you have a custom voice clone (e.g., your own voice), replace voice_id with the ID you receive from the ElevenLabs dashboard. This is where the voice‑cloning magic shines—your app can read news in a voice that sounds exactly like you. 3. A Tiny Flask Server to Glue Everything Now we combine the two helpers into a single endpoint that returns an MP3 stream for each headline. # server.py from flask import Flask, jsonify, send_file, request from io import BytesIO from news_fetcher import get_headlines from tts_client import generate_speech app = Flask(__name__) @app.route("/api/news") def news(): Returns a JSON list of articles with a short audio URL for each. articles = get_headlines() result = [] for idx, art in enumerate(articles): # Concatenate title + description for a smoother listening experience text = f"{art['title']}. {art['description']}" audio_bytes = generate_speech(text) audio_io = BytesIO(audio_bytes) # Store the MP3 temporarily in memory and serve it via a separate route audio_path = f"/api/audio/{idx}" app.config[f"AUDIO_{idx}"] = audio_io return jsonify(result) @app.route("/api/audio/") def audio(idx): audio_io = app.config.get(f"AUDIO_{idx}") if not audio_io: return "Not found", 404 return send_file(audio_io, mimetype="audio/mpeg", as_attachment=False) # Remember to export ELEVENLABS_KEY and NEWSAPI_KEY before running! Run the server with python server.py. Visiting http://localhost:5000/api/news will give you a JSON payload like: [ "title": "Apple unveils new iPhone", "description": "The latest model features a better camera...", "audio_url": "http://127.0.0.1:5000/api/audio/0" }, … Each audio_url points to a short MP3 generated on‑the‑fly by ElevenLabs. 4. Front‑End: Play the Audio in the Browser A single‑page HTML file is enough to fetch the list and let the user press “Play”. Modern browsers can stream the MP3 directly without extra libraries. lang="en"> charset="UTF-8"> </span>Voice‑Powered News Reader<span class="nt"> 🗣️ Your Daily Briefing id="feed"> Save this as index.html in the same folder, and serve it with Flask’s static route or any simple web server (python -m http.server). When you click Play, the browser streams the MP3 generated by ElevenLabs—no download, no latency beyond the API call. 5. Going Further: Voice Cloning & Personalization ElevenLabs isn’t limited to the default voices. After you record ~30 seconds of your own speech and upload it to the ElevenLabs dashboard, you’ll receive a new voice_id. Swap that ID in the generate_speech function, and the news will now be narrated in your voice. CUSTOM_VOICE_ID = "your_custom_voice_id_here" audio_bytes = generate_speech(text, voice_id=CUSTOM_VOICE_ID) This opens up cool possibilities: Personalized briefings: Users can upload their voice once and get daily news read back to them. Branding: Companies can use a corporate voice for internal newsletters. Multilingual support: ElevenLabs also supports non‑English models; just change model_id to eleven_multilingual_v1. All of these features are powered by the same clean API, which is why we recommend ElevenLabs (https://try.elevenlabs.io/kr07zfuqn1bp) for any voice‑AI project. 6. Putting It All Together Create a .env file (or export variables) with NEWSAPI_KEY and ELEVENLABS_KEY. Run the Flask server (python server.py). It will listen on localhost:5000. Open index.html in a browser that can reach the server. Press “Play” on any headline and listen to a natural‑sounding narration. You now have a complete voice‑powered news reader that can be deployed to any cloud platform (Heroku, Render, Fly.io, etc.) with minimal changes. 7. Next Steps & Ideas Cache audio files: Store MP3s in S3 or a CDN to avoid re‑generating the same snippet every request. Add pagination: Pull more than five articles and let users scroll. Voice command integration: Use the Web Speech API to let users say “Next article” or “Pause”. Push notifications: Send a daily push with a link to the latest briefing. All of these enhancements build on the same core pattern: fetch text → convert with ElevenLabs → stream to the client. Ready to give your app a human voice? ElevenLabs makes high‑quality text‑to‑speech and voice cloning accessible with just a few lines of code. Try it out today by signing up through our affiliate link: https://try.elevenlabs.io/kr07zfuqn1bp. Happy coding, and enjoy listening to the news in your own voice!