<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: rubengarcia0510</title>
    <description>The latest articles on DEV Community by rubengarcia0510 (@rubengarcia0510).</description>
    <link>https://dev.to/rubengarcia0510</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F484073%2Fd87b3646-fea7-47bc-b948-f107a7d8d124.png</url>
      <title>DEV Community: rubengarcia0510</title>
      <link>https://dev.to/rubengarcia0510</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rubengarcia0510"/>
    <language>en</language>
    <item>
      <title>Relator Virtual</title>
      <dc:creator>rubengarcia0510</dc:creator>
      <pubDate>Fri, 10 Jul 2026 19:12:00 +0000</pubDate>
      <link>https://dev.to/rubengarcia0510/relator-virtual-2kf9</link>
      <guid>https://dev.to/rubengarcia0510/relator-virtual-2kf9</guid>
      <description>&lt;p&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-07-09"&gt;Weekend Challenge: Passion Edition&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;El Relator Virtual&lt;/strong&gt; — a penalty-kick simulator that turns every shot into a moment of pure football passion, narrated live by an AI commentator with the energy of a classic South American match announcer.&lt;/p&gt;

&lt;p&gt;With the World Cup happening right now, I wanted to capture something every fan knows: the roar of the commentator's voice is half the magic of a goal. So instead of just building "another penalty game," I built one where every kick — save, post, or GOOOOL — gets narrated in real time with dynamically generated audio, so the emotional payoff feels as big as the moment itself.&lt;/p&gt;

&lt;p&gt;The player picks a side, takes the shot, and the AI relator reacts instantly with a burst of commentary matching the outcome — different phrasing and intensity depending on whether it's a save, a miss, or a screamer into the top corner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;🎥 &lt;a href="https://youtube.com/shorts/U2ijDG6eg9w?si=8ucoZpoa774VpxlT" rel="noopener noreferrer"&gt;Mirá el video demo acá&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Backend (Spring Boot + ElevenLabs):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rubengarcia0510" rel="noopener noreferrer"&gt;
        rubengarcia0510
      &lt;/a&gt; / &lt;a href="https://github.com/rubengarcia0510/relator-virtual" rel="noopener noreferrer"&gt;
        relator-virtual
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;⚽ Relator Virtual&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Simulador de penales donde cada jugada es narrada en tiempo real por un relator generado con IA (ElevenLabs), con la energía de un relato clásico sudamericano.&lt;/p&gt;
&lt;p&gt;Proyecto para el &lt;a href="https://dev.to/challenges/weekend-2026-07-09" rel="nofollow"&gt;DEV Weekend Challenge: Passion Edition&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Cómo funciona&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;El usuario patea un penal (gol, atajada o palo)&lt;/li&gt;
&lt;li&gt;El backend arma un texto de narración con variación aleatoria&lt;/li&gt;
&lt;li&gt;Se envía ese texto a la API de ElevenLabs para generar el audio&lt;/li&gt;
&lt;li&gt;El audio se devuelve al frontend y se reproduce en el momento justo&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Stack&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Java 17 + Spring Boot 3.3&lt;/li&gt;
&lt;li&gt;ElevenLabs API (Text-to-Speech)&lt;/li&gt;
&lt;li&gt;WebFlux (WebClient) para las llamadas HTTP&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Cómo correrlo localmente&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;export&lt;/span&gt; ELEVENLABS_API_KEY=tu-api-key
&lt;span class="pl-k"&gt;export&lt;/span&gt; ELEVENLABS_VOICE_ID=id-de-la-voz-que-elijas
./mvnw spring-boot:run&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Endpoint&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;POST /api/jugada&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"resultado"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;GOL&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"direccion"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;IZQUIERDA&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"nombreJugador"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;el 10&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Devuelve:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"textoNarracion"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;¡La reconquista, la tiene el 10, y... GOOOOOL!...&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  &lt;span class="pl-ent"&gt;"audioBase64"&lt;/span&gt;: &lt;/pre&gt;…
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rubengarcia0510/relator-virtual" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Frontend (Angular):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rubengarcia0510" rel="noopener noreferrer"&gt;
        rubengarcia0510
      &lt;/a&gt; / &lt;a href="https://github.com/rubengarcia0510/relator-virtual-frontend" rel="noopener noreferrer"&gt;
        relator-virtual-frontend
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;⚽ Relator Virtual — Frontend&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Mini-juego de penales en Angular (standalone components) que consume el backend Spring Boot de &lt;a href="https://github.com/rubengarcia0510/relator-virtual" rel="noopener noreferrer"&gt;relator-virtual&lt;/a&gt; para narrar cada jugada con voz generada por ElevenLabs.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Cómo correrlo&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install
npm start&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Se levanta en &lt;code&gt;http://localhost:4200&lt;/code&gt;. Necesitás el backend corriendo en &lt;code&gt;http://localhost:8080&lt;/code&gt; (ver &lt;code&gt;src/app/services/jugada.service.ts&lt;/code&gt; para cambiar la URL).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Para producción&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Antes de deployar, actualizá &lt;code&gt;API_URL&lt;/code&gt; en &lt;code&gt;jugada.service.ts&lt;/code&gt; con la URL de tu backend en Render.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run build&lt;/pre&gt;

&lt;/div&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rubengarcia0510/relator-virtual-frontend" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The project is split into two repos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt; (&lt;a href="https://github.com/rubengarcia0510/relator-virtual" rel="noopener noreferrer"&gt;relator-virtual&lt;/a&gt;) — a &lt;strong&gt;Spring Boot&lt;/strong&gt; service exposing a single endpoint, &lt;code&gt;POST /api/jugada&lt;/code&gt;, that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receives the outcome of a kick (goal / save / post, direction, minute)&lt;/li&gt;
&lt;li&gt;Builds a commentary script from a set of rotating templates so each play sounds a little different&lt;/li&gt;
&lt;li&gt;Calls the &lt;strong&gt;ElevenLabs&lt;/strong&gt; Text-to-Speech API to generate the narration on the fly, tuned with lower stability settings so it comes out sounding shouted and excited rather than flat&lt;/li&gt;
&lt;li&gt;Returns the generated audio (base64) to the frontend, timed to play exactly as the ball crosses the line&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt; (&lt;a href="https://github.com/rubengarcia0510/relator-virtual-frontend" rel="noopener noreferrer"&gt;relator-virtual-frontend&lt;/a&gt;) — an &lt;strong&gt;Angular&lt;/strong&gt; app (standalone components, signals for state) built around a stadium-at-night visual identity: a floodlit goal you tap to choose a corner, a scoreboard-style LED ticker that types out each commentary line as it arrives, and a net that ripples on goal / flashes on a post.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One deliberate design choice: the narrator reacts to &lt;em&gt;the play itself&lt;/em&gt; (the goal, the save, the drama) rather than being scripted to reference any real player by name — so it captures the passion of a World Cup moment without putting invented lines in a real person's mouth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prize category tech used:&lt;/strong&gt; ElevenLabs, for the real-time generated match commentary — the actual centerpiece of the whole project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Use of ElevenLabs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for participating!&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
    </item>
  </channel>
</rss>
