# Agora Arena

> Create your own ultimate moves by voice.

Build a browser fighting game with Agora RTC voice chat and RTM multiplayer input synchronization. Players speak an ultimate move, OpenAI transcribes it, and Reactor FastH3 Omni generates a cinematic attack that both players can watch.

- Author: zicojiao
- Updated: 2026-10-26
- Difficulty: Advanced
- Categories: rtc
- Platforms: Web, TypeScript
- Use cases: Gaming, Entertainment, Realtime
- Capabilities: Agora RTC, Agora Signaling, STT, AI Video Generation, React
- [Recipe page](https://recipes.agora.io/recipes/agora-arena)
- [Implementation repository](https://github.com/zicojiao/agora-arena)
- [Source recipe](https://github.com/zicojiao/agora-arena/blob/main/docs/ai/RECIPE.md)
- [Raw source Markdown](https://raw.githubusercontent.com/zicojiao/agora-arena/main/docs/ai/RECIPE.md)
- [All recipes](https://recipes.agora.io/llms.txt)

## Implementation guide

# Agora Arena: Voice-Created Ultimate Moves

Build a browser fighting game where players describe their own ultimate moves.
Agora RTC carries player voice chat and shares the generated cinematic with the
opponent. Agora Signaling (RTM) synchronizes room events and gameplay inputs.
OpenAI transcribes the player's words, and Reactor FastH3 Omni turns them into
a video attack that lands inside the game.

![English gameplay: Emberpaw faces Cloudhop with the FastH3 ultimate gauge ready](https://github.com/zicojiao/agora-arena/blob/main/docs/images/fight.jpg)

## What you can build

- CPU matches and online one-on-one matches with ten original fighters.
- Voice chat between players through Agora RTC.
- A shared match driven by deterministic simulation and RTM input messages.
- Hold-to-speak ultimate moves, with live transcription and a typed alternative.
- AI video attacks that start from the current fight frame and apply damage
  after playback.

## How the pieces work together

1. Players join an Agora room. RTC carries their microphones, while RTM carries
   fighter selections, inputs, and match events.
2. Both browsers simulate the fight locally using the same inputs.
3. When the blue FastH3 gauge is full, the player holds **F**. The game captures
   a clean fight frame and starts preparing a Reactor session.
4. The player waits for **Speak English now**, describes the complete move,
   and releases **F**. OpenAI realtime transcription returns the final words.
5. The server derives a short display name. The complete request is preserved
   in a structured prompt identifying the attacker, target, positions, action,
   camera, and sound.
6. FastH3 Omni generates the cinematic. In an online match, the caster publishes
   its video as an Agora RTC track so the opponent can watch it too.
7. The game applies the ultimate's damage through its battle engine, keeping
   both players' match state consistent.

Speech recognition is provided by OpenAI; video generation is provided by
Reactor. Agora provides the multiplayer voice and signaling transport.

## Run the project

Requires Node.js 20 or newer and your own provider credentials.

```bash
git clone https://github.com/zicojiao/agora-arena.git
cd agora-arena
npm ci
cp .env.example .env.local
# Fill in .env.local, then:
npm run dev
```

Open `http://localhost:5173/?lang=en` for the English interface. Local
development does not require the deployed site's playtest password.

| Server environment variable | Purpose |
| --- | --- |
| `AGORA_APP_ID` | Agora project used by online matches |
| `AGORA_APP_CERTIFICATE` | Server-side RTC and RTM token generation |
| `REACTOR_API_KEY` | FastH3 Omni sessions and generated attacks |
| `OPENAI_API_KEY` | Spoken moves; typed moves work without this key |
| `ARENA_ACCESS_PASSWORD` | Shared access gate for a deployed preview |

Create the Agora project in [Agora Console](https://console.agora.io), use token
authentication, and enable Signaling (RTM). Keep provider keys and the App
Certificate on the server. Never put them in browser code or commit `.env.local`.

## Try a voice ultimate

Select **Play vs CPU**, choose fighters, and start the match. Land or take hits
to fill the blue FastH3 gauge. Hold **F**, wait for the listening cue, say a move,
then release the key. With voice disabled, enter the same request as text.

Try these ideas:

- "Summon a giant golden dragon that dives from the clouds and slams into my opponent."
- "Summon a fire dragon that breathes ice at my opponent."
- "Trap my opponent in an ice tornado and launch them into the sky."
- "Summon a giant cat paw to slap my opponent across the arena."

![Real FastH3 Omni output: a golden dragon attacks Cloudhop, with English game labels](https://github.com/zicojiao/agora-arena/blob/main/docs/images/clip-golden-dragon.jpg)

For an online match, choose **Play online**, create a room, and share its
six-digit code or invite link with a second browser. Allow microphone access to
hear each other. Both players need access to the same deployed backend.

## Implementation map

| File or directory | Responsibility |
| --- | --- |
| [`src/online/room.ts`](https://github.com/zicojiao/agora-arena/blob/main/src/online/room.ts) | Agora RTC, RTM, room lifecycle, and cinematic publishing |
| [`src/online/lockstep.ts`](https://github.com/zicojiao/agora-arena/blob/main/src/online/lockstep.ts) | Synchronized input frames |
| [`src/game/liveVoiceMove.ts`](https://github.com/zicojiao/agora-arena/blob/main/src/game/liveVoiceMove.ts) | Hold-to-speak realtime transcription |
| [`src/game/ultimatePrompt.ts`](https://github.com/zicojiao/agora-arena/blob/main/src/game/ultimatePrompt.ts) | Full spoken request and fighter-aware video prompt |
| [`src/h3-session.ts`](https://github.com/zicojiao/agora-arena/blob/main/src/h3-session.ts) | Reactor connection, reference upload, generation, and playback lifecycle |
| [`server/index.js`](https://github.com/zicojiao/agora-arena/blob/main/server/index.js) | Short-lived provider tokens and transcription endpoints |

## Verify and deploy

```bash
npm run verify
```

This runs the test suite and production build with provider calls stubbed.
Real speech and video testing requires credentials and may incur provider
charges. FastH3 sessions must close on cancellation, match exit, or completion.
Connection, generation, and media transfer each contribute to latency; generation
speed alone is not the full wait a player experiences.

The project includes Vercel and Cloudflare Workers adapters. Follow the
[project README](https://github.com/zicojiao/agora-arena/blob/main/README.md#test-and-deploy) to configure your own
deployment. Keep the deployed access gate enabled to control model usage.

## Source and license

- [Implementation repository](https://github.com/zicojiao/agora-arena)
- [Contributing](https://github.com/zicojiao/agora-arena/blob/main/CONTRIBUTING.md)
- [MIT license](https://github.com/zicojiao/agora-arena/blob/main/LICENSE)


## Recipe prompt

You are implementing the "Agora Arena" recipe in this project.

Read the recipe markdown first:
https://raw.githubusercontent.com/zicojiao/agora-arena/main/docs/ai/RECIPE.md

Use the source repository for cross-reference:
https://github.com/zicojiao/agora-arena

Build this recipe into the user's app using the markdown as the implementation guide. Inspect related source files through the repository links when the recipe points to them. Ask before installing new dependencies.
