Skip to content

PoseidonProMax/RoadCaster

Repository files navigation

title RoadCaster
emoji ๐ŸŽ๏ธ
colorFrom blue
colorTo red
sdk docker
app_port 7860
pinned false

๐ŸŽ๏ธ RoadCaster

Every Close Call Has a Story.

A 3D highway driving game powered by a real-time Computational Linguistics engine โ€”
where Natural Language Generation and Text-To-Speech bring every near-miss to life.


LingHacks VII Python Flask Three.js


๐ŸŽฏ What Is RoadCaster?

RoadCaster is a browser-based 3D highway driving game with a twist: it has a brain.

Every time you swerve, dodge, overtake, or crash, the game sends a structured event to a custom Natural Language Processing backend that determines what just happened, how exciting it is, and what the commentator should say โ€” all in real-time, delivered as synthesized voice audio.

This is not a chatbot. This is not a text summarizer. This is applied Computational Linguistics inside a game.

Built for LingHacks VII โ€” the world's first computational linguistics hackathon for high schoolers.


โœจ The Big Idea

Most games play background music. RoadCaster plays live commentary.

The challenge: how do you generate commentary that feels natural, contextual, non-repetitive, and timely โ€” all from raw game physics data?

The answer: CASCE โ€” the Context-Aware Sports Commentary Engine.


๐Ÿง  CASCE: The NLP Engine

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         CASCE: The NLP Pipeline                             โ”‚
โ”‚                                                                             โ”‚
โ”‚  ๐ŸŽฎ Gameplay          ๐Ÿท๏ธ Context           ๐Ÿงฎ Narrative         ๐Ÿ”Š Voice    โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€           โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€           โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€           โ”€โ”€โ”€โ”€โ”€โ”€       โ”‚
โ”‚  Physics Data    โ†’   Classification  โ†’   State Engine    โ†’   TTS Output   โ”‚
โ”‚  (speed, lane,       (event type,        (momentum,          (Kitten TTS  โ”‚
โ”‚   proximity,          danger level,       transitions,         15M Nano    โ”‚
โ”‚   combo, time)        context tags)       anti-repeat)         model)      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Stage 1 โ€” Event Classification

Every frame, the frontend sends a structured event payload to the Flask backend:

{
  "event": "extreme_near_miss",
  "speed": 187,
  "combo": 7,
  "timestamp": 42.3,
  "lane": 1
}

Stage 2 โ€” Context Tagging

The NarrativeEngine ingests a sliding 18-second window of events and computes:

Context Tag Trigger Condition
pressure_rising Traffic density jumps from low โ†’ heavy
masterclass_streak 20+ seconds of clean, uninterrupted driving
high_speed Average speed > 150 km/h
combo_5 Combo chain โ‰ฅ 5 consecutive near-misses

Stage 3 โ€” Narrative State Engine

This is the heart of CASCE. A priority-ordered rule engine maps the 18-second event window to one of 20 named narrative states:

flowchart TD
    A[๐ŸŽฎ New Events Window] --> B{Has Crash?}
    B -->|Yes| C[๐Ÿ’ฅ Crash]
    B -->|No| D{Extreme Near Miss?}
    D -->|Yes| E[๐Ÿ˜ฑ Extreme Near Miss]
    D -->|No| F{Combo โ‰ฅ 10?}
    F -->|Yes| G[๐Ÿ”ฅ High Combo]
    F -->|No| H{Near Misses โ‰ฅ 3?}
    H -->|Yes| I[๐ŸŽฏ Clutch Survival]
    H -->|No| J{Speed > 150 + Overtakes โ‰ฅ 5?}
    J -->|Yes| K[โšก Dominant Run]
    J -->|No| L{Clean Driving โ‰ฅ 30s?}
    L -->|Yes| M[๐Ÿ† Total Control]
    L -->|No| N[... 15 more states ...]
    
    style C fill:#ff4444,color:#fff
    style E fill:#ff8800,color:#fff
    style G fill:#ff6600,color:#fff
    style I fill:#cc4400,color:#fff
    style K fill:#6644ff,color:#fff
    style M fill:#22aa44,color:#fff
Loading
๐Ÿ“‹ All 20 Narrative States (click to expand)
Priority State Trigger
1 ๐Ÿ’ฅ Crash Player collides
2 ๐Ÿ˜ฑ Extreme Near Miss Dangerously close dodge
3 ๐Ÿ”ฅ High Combo Combo chain โ‰ฅ 10
4 ๐ŸŽฏ Clutch Survival 3+ near-misses in window
5 ๐Ÿ˜ฐ Panic Driving High events, low speed
6 ๐ŸŒช๏ธ Traffic Chaos 6+ events, high speed
7 โš ๏ธ High Risk Driving Near miss + speed > 140
8 โšก Elite Reactions Combo โ‰ฅ 5
9 ๐Ÿ›ก๏ธ Untouchable Clean 15s + 4 overtakes
10 ๐Ÿ’จ Dominant Run Speed > 150 + 5 overtakes
11 ๐Ÿง™ Highway Wizard 3 lane changes + 3 overtakes
12 ๐Ÿ”ช Traffic Surgeon 2 lane changes + 2 overtakes, no near-misses
13 ๐ŸŽฏ Precision Driving Clean 15s + lane changes + overtakes
14 ๐Ÿ‘‘ Total Control 30+ seconds clean
15 ๐Ÿ† Masterclass 25+ seconds clean
16 ๐ŸŒŠ Flow State 20s clean + 2 overtakes
17 ๐ŸŽธ Controlled Aggression 4+ overtakes, no near-misses
18 ๐Ÿš€ Record Pace Speed > 175 km/h
19 ๐Ÿ“ˆ Building Momentum 3+ overtakes
20 ๐Ÿ”„ Traffic Weaving 2+ lane changes

Stage 4 โ€” Template Selection & Anti-Repetition Gate

flowchart LR
    A[Narrative State] --> B[Template Pool]
    B --> C{Last 10 Lines\nCache Check}
    C -->|Template recently used| D[Filter it out]
    C -->|Template is fresh| E[Select It]
    D --> F{Any eligible\ntemplates left?}
    F -->|Yes| E
    F -->|No| G[Fallback: any random]
    E --> H[Apply Memory Prefix]
    H --> I[Final Commentary Line]
    
    style C fill:#333,color:#fff
    style E fill:#22aa44,color:#fff
    style D fill:#cc4400,color:#fff
Loading

The anti-repetition gate ensures no commentary line is repeated within the last 10 spoken lines โ€” making the experience feel dynamic and fresh across a full session.

Context Memory Prefixes are prepended when special conditions are detected:

  • "The pressure is rising now! " โ†’ when traffic density spikes
  • "This has been a masterclass in control! " โ†’ after a sustained clean streak

Stage 5 โ€” Priority Queue & Rate Limiter

The frontend enforces a 2.5-second cooldown between commentary lines with a priority queue:

CRASH > EXTREME NEAR MISS > HIGH COMBO > NEAR MISS > OVERTAKE > NORMAL

This prevents voice-over overlap and ensures the most dramatic moments always get airtime.

Stage 6 โ€” Kitten TTS Voice Synthesis

sequenceDiagram
    participant FE as ๐ŸŽฎ Frontend
    participant BE as ๐Ÿ Flask Backend
    participant NE as ๐Ÿง  NarrativeEngine
    participant CE as ๐Ÿ’ฌ CommentaryEngine
    participant TTS as ๐ŸŽ™๏ธ KittenTTS Nano

    FE->>BE: POST /api/narrative {events, speed, combo}
    BE->>NE: evaluate(events, time, speed, combo)
    NE-->>BE: {state, should_speak, context_tags, stats}
    BE->>CE: generate(narrative_result, mode, voice)
    CE-->>BE: {commentary_text, excitement, momentum}
    BE->>TTS: synthesize(text, voice="Jasper")
    TTS-->>BE: WAV bytes (24kHz mono)
    BE-->>FE: {commentary, voice, excitement}
    FE->>FE: Play WAV audio + update NLP debugger
Loading

The KittenTTS Nano (15M parameter model) synthesizes each commentary line to a 24kHz mono WAV and streams it back to the browser for immediate playback.


๐ŸŽ™๏ธ Three Commentator Personalities

Mode Voice Style Example
๐ŸŸ๏ธ Sports Broadcast Jasper High-energy, reactive, excited "OH NO! A COLLISION! AAAAAAH! HA HA HA! GAME OVER!"
๐ŸŽฌ Dramatic Narrator Hugo Cinematic, dark, reflective "The highway always wins. In the end. Ha... ha... ha..."
๐Ÿ˜ˆ Savage Critic Kiki Sarcastic, witty jabs "HA HA HA! Wrecked! Hope you have insurance, because that was pathetic!"

Each personality has its own full template library, excitement level mappings, and transition commentary for state changes.


๐Ÿ—๏ธ Architecture

graph TB
    subgraph Frontend ["๐ŸŒ Frontend (Three.js)"]
        G[3D Game Engine] --> EQ[Event Queue]
        EQ --> PQ[Priority Queue\n& Rate Limiter]
        PQ --> AC[Audio Controller\nWeb Audio API]
        G --> DB[NLP Pipeline\nDebugger Panel]
    end
    
    subgraph Backend ["๐Ÿ Backend (Flask)"]
        API["/api/narrative"] --> NE
        NE[NarrativeEngine\n18s Sliding Window] --> CE
        CE[CommentaryEngine\n+ Anti-Repeat Gate] --> TTS
        TTS[KittenTTS Nano\n15M params ยท 24kHz]
    end
    
    subgraph Storage ["๐Ÿ’พ State"]
        EH[Event History\nList]
        L10[Last 10 Spoken\nCache]
        ST[Narrative State\nTracker]
    end
    
    PQ -->|POST /api/narrative| API
    TTS -->|WAV bytes| AC
    NE <--> EH
    CE <--> L10
    NE <--> ST
    
    style Frontend fill:#1a1a2e,color:#fff
    style Backend fill:#16213e,color:#fff
    style Storage fill:#0f3460,color:#fff
Loading

๐Ÿ› ๏ธ Technology Stack

Layer Technology Purpose
3D Game Three.js 0.184.0 WebGL highway rendering, vehicle meshes, physics
Frontend Vanilla JS (ES Modules) Event detection, queue management, audio playback
Styling CSS3 + Glassmorphism Dark mode UI with NLP debugger panel
Backend Python 3.12 + Flask 3.0 REST API, NLP pipeline orchestration
NLG Custom Rule Engine Narrative state classification, template selection
TTS KittenTTS Nano (15M) PyTorch/ONNX neural voice synthesis
Audio NumPy + soundfile PCM โ†’ WAV conversion (16-bit, 24kHz, mono)
Package Manager uv Fast Python dependency management

๐Ÿš€ Getting Started

Prerequisites

  • Python 3.12+
  • uv package manager

Installation

# Clone the repository
git clone https://github.com/your-username/RoadCaster.git
cd RoadCaster

# Install all dependencies (including KittenTTS from GitHub release)
uv pip install -e .

Note: The KittenTTS Nano model (~35MB weights) will be downloaded automatically on first startup.

Running

python app.py

Then open http://localhost:5000 in your browser.

Docker (Hugging Face Spaces)

The project ships with a Dockerfile targeting port 7860 for HuggingFace Spaces deployment.


๐ŸŽฎ How to Play

Control Action
A / โ† Arrow Switch to the left lane
D / โ†’ Arrow Switch to the right lane
Space / โ†‘ Arrow Speed boost (hold)
R Restart after crash

Scoring tips:

  • Getting as close as possible to traffic without hitting it builds your combo multiplier
  • Sustained clean driving builds toward Masterclass and Total Control states
  • Weaving through dense traffic at high speed unlocks Highway Wizard commentary

๐Ÿ”ฌ NLP Pipeline Debugger

Press the toggle arrow on the right side of the screen to expand the live debugger. It shows:

  • Real-time event JSON payloads from the game
  • Active narrative state and context tags
  • Current commentator voice and excitement level
  • Momentum trend (rising / calm / falling)

๐Ÿ“‚ Project Structure

RoadCaster/
โ”œโ”€โ”€ app.py                  # Flask server + API routes
โ”œโ”€โ”€ narrative.py            # NarrativeEngine โ€” sliding window + state machine
โ”œโ”€โ”€ commentary.py           # CommentaryEngine โ€” template library + anti-repeat
โ”œโ”€โ”€ action_narrator.py      # ActionNarrator โ€” play-by-play physical action lines
โ”œโ”€โ”€ game.py                 # Event schema validation
โ”œโ”€โ”€ tts_provider.py         # KittenTTS integration + WAV encoding
โ”œโ”€โ”€ pyproject.toml          # Project metadata + dependencies
โ”œโ”€โ”€ Dockerfile              # Container setup for HF Spaces
โ”œโ”€โ”€ templates/
โ”‚   โ””โ”€โ”€ index.html          # Game UI + Three.js 3D engine
โ””โ”€โ”€ static/
    โ””โ”€โ”€ ...                 # Assets

๐Ÿ† LingHacks VII โ€” Why This Project?

LingHacks VII challenges teams to build software that integrates computational linguistics to solve a scientific or social problem. RoadCaster addresses this by:

  1. Natural Language Generation (NLG) โ€” A custom rule-based engine maps game physics to narrative prose. No LLM required; the language emerges from structured linguistic templates and contextual logic.

  2. Pragmatics & Context โ€” The commentary system models discourse context (commentator memory, anti-repetition), prosody cues (excitement levels passed to TTS), and temporal grounding (18-second event windows for situational awareness).

  3. Text-to-Speech Synthesis โ€” KittenTTS demonstrates applied speech synthesis: the same text spoken by Jasper (energetic), Hugo (cinematic), or Kiki (sardonic) feels completely different, showing how prosody and voice personality shape meaning.

  4. Human-Computer Interaction โ€” The NLP debugger panel makes the linguistics pipeline visible and legible, turning an invisible backend into an educational showcase of how NLG works in real time.


๐Ÿ”— Links


Made with โšก and way too much caffeine at LingHacks VII

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors