Dev.to WebDev 🛠 Dev 👁 0 📖 5 min read

Create a Voice-Powered News Reader App

Why a Voice‑Powered News Reader? If you’ve ever tried to skim headlines while commuting, cooking, or hitting the gym, you know the friction of reading on a small screen. A voice‑first news reader solves that problem by

Why a Voice‑Powered News Reader?

If you’ve ever tried to skim headlines while commuting, cooking, or hitting the gym, you know the friction of reading on a small screen. A voice‑first news reader solves that problem by turning text into natural‑sounding speech that you can listen to hands‑free. In this post we’ll walk through building a simple Voice‑Powered News Reader using:

  • A public news API (e.g., NewsAPI.org) to fetch the latest articles
  • ElevenLabs for high‑quality text‑to‑speech (TTS) and voice cloning – see the affiliate link below for a free trial
  • A lightweight Flask (Python) backend that stitches everything together

By the end you’ll have a small web service that returns an MP3 stream you can play in any browser or embed in a mobile app.

Architecture Overview

+----------------+        +-------------------+        +-------------------+
|  Front‑end UI  |  <---> |  Flask Backend    |  <---> |  NewsAPI.org      |
| (HTML/JS)      |        |  /generate-audio  |        |  (JSON)           |
+----------------+        +-------------------+        +-------------------+
                                 |
                                 v
                        +-------------------+
                        | ElevenLabs TTS    |
                        | (audio generation)|
                        +-------------------+
  1. Client sends a request like GET /generate-audio?topic=technology.
  2. Flask fetches the top 5 headlines for the topic from NewsAPI.
  3. The concatenated article text is sent to ElevenLabs via their REST API.
  4. ElevenLabs returns an MP3 stream that Flask streams back to the client.

Prerequisites

Item Version
Python 3.9+
Flask 2.3+
requests library latest
An API key for NewsAPI.org (free tier works) –
An ElevenLabs API key (sign up through the affiliate link) –
# Create a virtual environment (optional but recommended)
python -m venv venv
source venv/bin/activate

# Install dependencies
pip install flask requests

Step 1 – Pulling the Latest Headlines

First we need a function that talks to NewsAPI. The endpoint we’ll use is https://newsapi.org/v2/everything.

import requests

NEWSAPI_KEY = "YOUR_NEWSAPI_KEY"

def fetch_headlines(topic: str, limit: int = 5) -> str:
    """Return a plain‑text string containing the top `limit` headlines."""
    url = "https://newsapi.org/v2/everything"
    params = {
        "q": topic,
        "pageSize": limit,
        "language": "en",
        "sortBy": "publishedAt",
        "apiKey": NEWSAPI_KEY,
    }
    resp = requests.get(url, params=params)
    resp.raise_for_status()
    articles = resp.json()["articles"]

    # Build a simple script: "Headline 1. ... Headline 2. ..."
    script = "\n".join([f"{i+1}. {a['title']}" for i, a in enumerate(articles)])
    return script

Tip: If you want a richer experience, you can also pull the article description or full content (subject to the source’s licensing).

Step 2 – Turning Text into Speech with ElevenLabs

ElevenLabs offers a REST endpoint that accepts plain text and returns an audio file. The API is straightforward: POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id}.

You’ll need a voice ID – the platform ships with a few default voices, or you can clone your own voice using their UI. For this tutorial we’ll use the default “Rachel” voice (voice_id = "21m00Tcm4TlvDq8ikWAM").

ELEVENLABS_API_KEY = "YOUR_ELEVENLABS_API_KEY"
VOICE_ID = "21m00Tcm4TlvDq8ikWAM"   # Rachel (default)

def generate_audio(text: str) -> bytes:
    """Send `text` to ElevenLabs and receive MP3 bytes."""
    url = f"https://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}"
    headers = {
        "xi-api-key": ELEVENLABS_API_KEY,
        "Content-Type": "application/json",
    }
    payload = {
        "text": text,
        "model_id": "eleven_monolingual_v1",   # high‑quality model
        "voice_settings": {
            "stability": 0.75,
            "similarity_boost": 0.85
        }
    }

    response = requests.post(url, json=payload, headers=headers)
    response.raise_for_status()
    return response.content   # MP3 binary

Why ElevenLabs? Their neural TTS sounds remarkably human, supports voice cloning, and the free tier gives you 10 k characters per month—perfect for a hobby project. Grab your API key through the affiliate link: https://try.elevenlabs.io/kr07zfuqn1bp

Step 3 – Glue It Together in Flask

Now we expose a single endpoint that accepts a topic query parameter, fetches headlines, generates audio, and streams the MP3 back to the caller.

from flask import Flask, request, Response, abort

app = Flask(__name__)

@app.route("/generate-audio")
def generate_audio_route():
    topic = request.args.get("topic")
    if not topic:
        abort(400, description="Missing 'topic' query parameter")

    # 1️⃣ Pull headlines
    script = fetch_headlines(topic)

    # 2️⃣ Convert to speech
    try:
        audio_bytes = generate_audio(script)
    except requests.HTTPError as e:
        abort(502, description=f"ElevenLabs error: {e}")

    # 3️⃣ Stream MP3 back
    return Response(
        audio_bytes,
        mimetype="audio/mpeg",
        headers={"Content-Disposition": f'attachment; filename="{topic}.mp3"'}
    )

if __name__ == "__main__":
    app.run(debug=True)

Run the server:

python app.py

Visit http://127.0.0.1:5000/generate-audio?topic=technology in your browser. The download should start automatically, and playing the MP3 will read the top tech headlines in a natural voice.

Step 4 – Front‑End Quick Demo (Optional)

If you’d like a single‑page UI, a few lines of HTML + JavaScript can fetch and play the audio without a page reload.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Voice News Reader</title>
</head>
<body>
  <h1>Voice‑Powered News Reader</h1>
  <input id="topic" type="text" placeholder="Enter a topic (e.g., sports)" />
  <button id="listen">Listen</button>
  <audio id="player" controls></audio>

  <script>
    document.getElementById('listen').onclick = async () => {
      const topic = document.getElementById('topic').value.trim();
      if (!topic) return alert('Please type a topic');
      const resp = await fetch(`/generate-audio?topic=${encodeURIComponent(topic)}`);
      if (!resp.ok) return alert('Error: ' + resp.statusText);
      const blob = await resp.blob();
      const url = URL.createObjectURL(blob);
      const player = document.getElementById('player');
      player.src = url;
      player.play();
    };
  </script>
</body>
</html>

Place this file in a templates folder, add a route in Flask to serve it, and you have a complete web app in under 100 lines of code.

Going Further

Idea How to Implement
Voice cloning – let users record a 30‑second sample and use ElevenLabs’ voice‑cloning endpoint to generate a personalized narrator.
Multiple languages – combine NewsAPI’s language param with ElevenLabs’ multilingual models.
Podcast style – stitch a short intro, headlines, and a closing line, then upload the MP3 to a storage bucket for on‑demand streaming.
Mobile integration – expose the Flask endpoint via a simple Flask‑RESTful API and consume it from a React Native or Swift client.

All of these extensions still rely on the same core building blocks we covered: fetch text, send it to ElevenLabs, and stream the audio.

Wrap‑Up & Call to Action

You now have a functional voice‑powered news reader that you can run locally, host on a cheap VPS, or embed in a larger product. The heavy lifting—producing clear, expressive speech—is handled by ElevenLabs, which consistently ranks among the best TTS services for developers. Their API is simple, their pricing (including a generous free tier) is friendly, and you can start right away with the affiliate link below.

🚀 Ready to give your app a human voice? Sign up at https://try.elevenlabs.io/kr07zfuqn1bp and get your API key in minutes. Happy coding!

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.