DEV Community

Cover image for PassionCast: I Built an AI Hype Man for World Cup Fans Using Gemini + ElevenLabs
Sarvar Nadaf
Sarvar Nadaf

Posted on

PassionCast: I Built an AI Hype Man for World Cup Fans Using Gemini + ElevenLabs

DEV Weekend Challenge: Passion Edition Submission

This is a submission for Weekend Challenge: Passion Edition

What I Built

The World Cup quarter-finals are on right now. I'm watching matches, yelling at my screen, and I thought: what if I could bottle that feeling into an audio clip?

PassionCast lets you pick your team, choose a passion mode (hype speech, glory moment, rivalry fire, heartbreak, fan anthem, or custom), and generates a 60-second AI commentary clip. Not the generic "your team is amazing" stuff. Actual references to your team's players, history, and rivals.

Pick India, select "Rivalry Fire," hit generate. You get a breathless commentator talking about the India-Pakistan cricket-meets-football tension, with real names and real context. Try Argentina and you get Maradona, La Albiceleste, the Diego legacy. That's what I was going for.

Demo

πŸ‘‰ Try PassionCast Live

Three pre-generated sample clips are on the page. Hit play, no keys needed. You'll hear:

  • Argentina rivalry fire (Match Commentator voice)
  • India pre-match hype (Epic Narrator voice)
  • England heartbreak (Epic Narrator voice)

To generate your own, you'll need free API keys (30 seconds each):

The flow:

Code

πŸ”₯ PassionCast

Your personal AI hype man for the World Cup 2026.

Pick your team. Choose a moment. Get a passionate, AI-generated audio commentary that captures the fire of football fandom.

πŸ‘‰ Try PassionCast Live

PassionCast Landing


How It Works

  1. Pick your team from 48 World Cup 2026 nations
  2. Choose your passion β€” hype speech, glory moment, rivalry fire, heartbreak, or fan anthem
  3. Select a voice β€” epic narrator, match commentator, or poetic storyteller
  4. Generate β€” Gemini writes the script, ElevenLabs brings it to life as audio

Team Selection Flow


Tech Stack

Layer Technology Why
Script generation Google AI (Gemini 2.0 Flash) High temperature (0.9) + cultural context = scripts that feel personal, not generic
Voice synthesis ElevenLabs (Multilingual v2) Low stability (0.4) for emotional range, high style (0.6) for expressiveness
Frontend Vanilla JS + Vite Fast, no framework overhead, deploys anywhere
Hosting GitHub Pages Free, automatic deploys via GitHub Actions

No backend. No database…

How I Built It

No backend. No framework. One page, vanilla JS, two API calls. Vite for bundling, GitHub Pages for hosting.

Browser β†’ Gemini 2.0 Flash (writes script) β†’ ElevenLabs (speaks it) β†’ Audio playback
Enter fullscreen mode Exit fullscreen mode

I specifically didn't want a backend here. The whole point is that someone can fork this, drop in their own keys, and have it running in 30 seconds.

The Gemini Part (where I spent most of my time)

Getting Gemini to write passionate content was harder than I expected. At temperature 0.7, everything came out bland. "Your team has a proud history. The fans are excited." Useless.

At 0.9, things got interesting. Combined with a detailed system prompt that includes the team name, their rivals, their football culture, and the specific style I want (narrator vs commentator vs poet), the output started feeling real.

The trick was constraining length. I needed 150-200 words, the sweet spot for 45-60 seconds of audio. Too short and it feels empty. Too long and ElevenLabs starts rushing or the clip drags.

// Note: ${apiKey} is a template literal variable, not a real key. 
// Users provide their own free key from aistudio.google.com/apikey
const response = await fetch(
  `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`,
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      contents: [{ parts: [{ text: prompt }] }],
      generationConfig: { temperature: 0.9, maxOutputTokens: 500 }
    })
  }
);
Enter fullscreen mode Exit fullscreen mode

The ElevenLabs Part (where the magic happens)

I tested default voice settings first. Sounded flat. Like a GPS reading football commentary.

The fix: crank down stability to 0.4 (default is higher). This adds emotional variation. The voice wavers, speeds up, gets louder on key phrases. Exactly what you want for sports commentary.

Then style to 0.6 for extra expressiveness, and speaker boost on for clarity.

Three voices, matched to content:

  • Brian (dramatic narrator) for glory moments
  • Liam (energetic) for rivalry and hype
  • George (poetic storyteller) for heartbreak and anthems
body: JSON.stringify({
  text: script,
  model_id: 'eleven_multilingual_v2',
  voice_settings: {
    stability: 0.4,
    similarity_boost: 0.8,
    style: 0.6,
    use_speaker_boost: true,
  }
})
Enter fullscreen mode Exit fullscreen mode

Other Decisions

I used flag images from flagcdn.com instead of emoji because emoji flags don't render on Windows for England, Wales, and Scotland (they show as black rectangles). Learned that the hard way after building the whole grid with emoji first.

Dark theme with gold/fire accents because... it's a passion app. Light mode would feel wrong.

What I'd Add

If I had another weekend: social sharing (let people post their clips), match-day mode that checks today's fixtures and auto-suggests hype content, and a gallery so you can hear what other fans generated. PRs welcome if you want to tackle any of these.


Prize Categories

  • Best Use of Google AI: Gemini 2.0 Flash with temperature 0.9 and detailed cultural prompting. Produces scripts with real player names, real rivalry history, and team-specific fan culture for 48 nations. Three distinct writing styles (narrator, commentator, poet) via style instructions in the prompt.

  • Best Use of ElevenLabs: Multilingual v2 model with deliberately tuned settings. Stability at 0.4 for emotional range (default sounds robotic for sports content). Style at 0.6 for expressiveness. Three voices paired to content types. The output sounds like broadcast commentary, not text-to-speech.

Top comments (5)

Collapse
 
mustkhim_inamdar profile image
Mustkhim Inamdar

Hi it’s interesting use case, good work. For my understanding I have couple of questions, did you use structured JSON output from Gemini, or did you parse free-form text? And How do you prevent Gemini from hallucinating player names, scores, or match events?

Collapse
 
steven_r_404 profile image
Steven Ray

Its really impressive πŸ‘πŸ»

Collapse
 
sarvar_04 profile image
Sarvar Nadaf

Thank You πŸ™πŸ»

Collapse
 
pratikponde profile image
Pratik Ponde

Hey @sarvar_04 The voice experience is especially impressive. But How did you decide on the tone and personality of the AI commentator?

Collapse
 
inamdar profile image
Naisha

Hi sir, I wanted to understand, did you stream the audio as it was generated, or wait for the complete audio before playback?