The project's README from github.com/xflare-bot/pokemonlive. As one markdown file: README.md.
Choose a move. Watch the battle come to life.
Rule-driven Pokémon battles, brought to life with AI-generated 2D animation.
Turn-based singles ·
Pixel UI + anime video ·
Chinese / English / Japanese
Preview · Quickstart · Architecture · APIs · Development
[!NOTE] Unofficial, local, non-commercial learning prototype. Read the setup instructions and limitations before running.
Actual desktop gameplay · Chinese UI · Existing local idle video
Players choose moves, the rules engine resolves the battle, and AI turns the results into a continuous animated sequence. Videos play inside the battlefield, without a separate player modal.
| Rules first | Anime presentation | Continuous playback |
|---|---|---|
| Code resolves hits, damage, and status. | Hand-drawn, cel-shaded video over a retro pixel UI. | Prewarm upcoming assets; hold the last frame if the next clip is late. |
The move panel displays type, power, PP, and relevant type-effectiveness hints.

Generation endpoints were disabled during screenshot capture. No additional paid assets were generated.
When generating a short video takes about as long as—or less time than—playing it, could a game generate its next cinematic from the player's latest choice instead of relying entirely on prerecorded animations?
This project explores that idea through familiar Pokémon battles: the player gives an order, the trainer calls out a move, the Pokémon responds, attacks, takes a hit, and returns to a standoff. The goal is to generate the next segment while the previous one plays, preserving character identity, move effects, and status conditions across shots.
[!NOTE] This is a working experimental pipeline, not a promise of fixed generation times or zero waiting. Queueing, generation, transfer, and decoding all affect the experience.
Requirements: Node.js, npm, and FFmpeg. The locally verified environment uses Node.js 24 and FFmpeg 8.1. Make ffmpeg available on PATH or set FFMPEG_PATH.
npm ci
# First-time setup only; do not overwrite an existing .env.local
cp -n .env.example .env.local
Edit .env.local with your own keys:
DEEPSEEK_API_KEY=replace_with_your_deepseek_key
FAL_KEY=replace_with_your_fal_key
FAL_VIDEO_RESOLUTION=480P
MINIMAX_API_KEY=replace_with_your_minimax_key
Load the environment file explicitly:
node --env-file=.env.local server.mjs
Open http://localhost:4173/. If the variables are already set in the process environment, you can also use npm start. The --env-file option ensures that the DeepSeek key, resolution, and other variables are loaded together; do not assume the service automatically reads every setting from .env.local.
PORT changes the port; DEEPSEEK_MODEL overrides the planner model; FAL_VIDEO_RESOLUTION accepts 480P or 768P for attack generation. Without a planner key, local storyboards are used. Without video or speech keys, the corresponding generation features are unavailable, but the rules engine and local presentation can still run.
.local/. Deleting caches may trigger regeneration and additional charges; changing language may also require new assets..env* files (except the example), .local/, and outputs/ are Git-ignored. Never commit real keys or runtime artifacts containing private information.The rules engine owns the outcome. AI owns the presentation.
The stack is vanilla HTML / CSS / JavaScript, a Node.js HTTP server, multiple HTMLVideoElement players, and local FFmpeg. There is no frontend framework or Three.js runtime dependency.
flowchart LR
A["Battle engine<br/>Resolve actions + snapshot state"] --> B["Shot planner<br/>DeepSeek or local fallback"]
B --> C["Prompt validation<br/>Rebuild from battle facts"]
C --> D["Video pipeline<br/>fal generation + buffered playback"]
D --> E["Closing sequence<br/>State-matched idle"]
classDef rules fill:#fff0ad,stroke:#b58b00,color:#242f40
classDef planning fill:#e5efff,stroke:#3562a5,color:#242f40
classDef media fill:#ffe4df,stroke:#d45850,color:#242f40
classDef idle fill:#e4f2d6,stroke:#60884b,color:#242f40
class A rules
class B,C planning
class D media
class E idle
New battle and scene clips use seed = 42, but a fixed seed does not guarantee identical results across different prompts or input images. Local FFmpeg still handles idle looping, response-clip loudness processing, scene tail frames, and recovery from archived media; it no longer handles the real-time tail-frame path for new attack clips.
Video goes through fal, shot planning through DeepSeek, and callout speech directly through MiniMax. Model availability, access permissions, and pricing are determined by the providers.
| Service | Endpoint / Model | Purpose |
|---|---|---|
| DeepSeek Chat Completions | POST https://api.deepseek.com/chat/completions; default: deepseek-v4-flash |
Compact shot planning; overridable with DEEPSEEK_MODEL |
| fal H3 Max Turbo | minimax/h3-max-turbo/image-to-video |
Attack, continuation, recall, response, and closing clips with an opening frame |
| fal H3 Max Reference | minimax/h3-max/reference-to-video |
Opening clips without a usable first frame, send-outs, and state-specific scenes with both character references |
| fal FFmpeg Extract Frame | fal-ai/ffmpeg-api/extract-frame, frame_type: last |
Attack tail-frame URLs; one request shared by continuation, state prewarming, and archiving |
| MiniMax Speech WebSocket | wss://api.minimax.cn/ws/v1/t2a_v2; speech-2.8-turbo |
Player move callouts and switch announcements, cached by language and dialogue |
| fal H3 Max Turbo Text to Video | minimax/h3-max-turbo/text-to-video |
Asset scripts pre-generate trainer silhouettes for reuse as local files |
Video is generated through fal, not through MiniMax's direct video API. Only speech connects directly to MiniMax. The Chinese voice is Chinese (Mandarin)_Straightforward_Boy; English and Japanese use their respective language voices. Callout speech plays separately and is not baked into the video.
Only the Node.js server reads API keys. Character images are locally stored PokéAPI assets, so gameplay does not require live PokéAPI lookups. See the third-party notices and character reference provenance.
| Location | Responsibility |
|---|---|
src/battle-engine.js, src/data.js |
Battle rules and data |
src/attack-storyboard.js, src/compact-storyboard.js |
Action records, shot validation, and prompt reconstruction |
src/fal-video-runway.js, src/cloud-tail-frame.js |
Video generation pipeline and cloud tail-frame extraction |
src/scene-video-service.js, src/scene-video-client.js |
State-specific asset generation, prewarming, caching, and recovery |
src/attack-video-player.js, src/app.js |
Multi-slot playback, UI, and cinematic sequencing |
server.mjs |
Same-origin media serving and external API proxying |
assets/, tests/ |
Local assets and automated regression tests |
npm test
Automated tests cover rules, state continuity, generation parameters, shared downloads, cancellation, and failure recovery. Provider calls are mocked. Passing tests does not validate finished-video quality or real generation latency.
The original source code and original textual documentation in this repository are licensed under the MIT License, copyright (c) 2026 xflare-bot. This covers the project's own code in src/, scripts/, and tests/, its HTML, CSS, server and configuration files, and its original documentation, only to the extent that the contributors have the rights to license them.
The MIT grant does not cover media assets or third-party material. Files in assets/ and docs/images/, including sprites, reference artwork, fonts, audio, generated videos, and screenshots, are excluded from the project's MIT grant. Third-party code and other third-party material retain their respective licenses and rights; see THIRD_PARTY_NOTICES.md. No Pokémon character, artwork, name, design, or trademark rights are granted by this project's code license.
“Local, non-commercial learning prototype” describes this demo's purpose, not an additional restriction on MIT-licensed code. Commercial use, modification, and closed-source reuse of the covered code are permitted under MIT's terms; rights to excluded assets must be addressed separately.
This is an unofficial learning prototype, not a license to use Pokémon intellectual property. Characters, names, and imagery belong to The Pokémon Company, Nintendo, Creatures, GAME FREAK, and their respective rights holders. Non-commercial use does not automatically grant permission. Obtain the necessary permissions or replace restricted assets before distributing or deploying a version that includes them; adding a code license does not resolve those asset rights.
Font and image sources and license records are documented in THIRD_PARTY_NOTICES.md. Screenshots show the actual project interface, not official promotional material.