Trackmania AI Analyzer
Compare your Trackmania 2020 run against any ghost — the world record, a friend,
your own PB — and see exactly where the time goes: speed and steering overlaid
on the same graphs, split into track sections, a corner-by-corner breakdown
(time gained/lost, entry/min/exit speed, braking point, steering), and an AI
coach that works from those measurements.
- My maps front page: add your
Documents\Trackmania\Replays\Autosaves folder
(drop it on the page) and every map you've finished appears with your best time.
Pick one to open it.
- Full-width analysis: large graphs that share one crosshair (speed, time gap,
speed difference, steering, brake/throttle), a colour-coded track map, per-section
charts, and a corner table. Every graph has an Expand button, and the workspace can
go full screen.
- Track tab (3D) and full page: a 3D view of the track with its heights that you can orbit
and zoom (or switch to a flat map), with your line coloured by time, speed or pedals, the
ghosts' lines, numbered corners and jumps drawn as arcs. Select a corner to fly in and see
exactly where the ghost brakes, turns in, hits the apex and gets back on the throttle, with
your markers next to it, how many metres earlier or later you are, how much wider or tighter
your line is, and whether the corner is uphill or downhill. Also: an elevation profile, a
list of jumps (air time, speed lost, air-braking) compared with the ghost, and a replay of both
runs side by side with a scrubber and a follow camera. It's the "Track" tab of a map, and
"Full page" opens it full screen.
- What's under the car: the map file itself is read (its block list) to work out whether each
stretch is tech, plastic, dirt, grass, ice, bumps or water. The Track tab has a Surface
colour mode, every corner shows its surface, and the coach knows how speed and surface change
what works (no speed-drift advice on ice, how dirt and grass punish a late lift, and so on).
- What to press, and when: for each corner the steering, brake and lift runs are extracted for
you and for the ghost and drawn along the metres of the corner, so you see "ghost steers left
0.7 for 1.1 s from 20 m before, you start 8 m later".
- Pictures in the coach's report: the coach can place a figure of a corner in its report: your
line against the ghost's, the brake / turn-in / apex / exit points, distance ticks, the surface
and the input timeline. Each figure has a Save PNG button, and the coach's note shows up in the
Track tab next to that corner.
- A new look, and the ground up front: a deep-navy theme with one violet accent. The overview now opens with "The lap at
a glance", a strip along the lap showing the ground you drive on (tech, ice, dirt, grass...), the corners (coloured by
time lost or gained), the checkpoints and every trick. Below it, a "Ground" card shows what share of the lap is on each
surface, your speed against the ghost's and the time you gain or lose on it, with a one-line tip per surface. The ground
also runs as a thin strip along every chart, as a "Ground" colour mode on the maps, and as a chip on each corner.
- Corner by corner, on the overview: a card for every corner with a picture of your line (white) against the ghost's
(blue), numbered turn-in / apex / throttle points, your entry, slowest and exit speeds against the ghost's, where each of
you braked, the ground under it, and any trick in or around it (jump line, landing, wall ride, air-brake spot). Click the
picture for the full figure, or use the buttons to show it on the graphs or make a share card.
- Steering plan (made for bobsleigh and ice maps, works on any): the steering of the reference ghosts, combined and
aligned to your distance. The Corners tab shows their median and spread against your wheel, a list of the stretches where
you differ most with exact numbers ("700-780 m: the references steer right 0.48, you 0.17: add to about 0.48; they start at
612 m, you at 625 m"), and the references' steering script metre by metre. A keyboard-style reference is given as holds in
seconds. The coach gets the same blueprint (with up to two more selected ghosts), a deeper bobsleigh/ice knowledge base,
every corner's input script on those maps, and a
Steering plan section that must use only the blueprint's numbers.
- How to do it: the steering plan also measures how the fastest ghosts wiggle the wheel (reversals per second and size of a
swing) and how far your line is from theirs, and turns the numbers into step-by-step lessons (set the angle early and hold
it, the wheel wiggle, drive the ghosts' line) with drills, shown under the Steering plan and given to the coach, which now
retitles focus areas after the actual fix and writes a "How to do it" section. Per Nadeo's October 2022 update, ice wiggles
no longer add speed by themselves, so the wiggle lesson copies the pros' rate and size from the data and says so.
- Places, not metres, and a trick playbook: nobody can see metres while driving, so every place is named by the corner or checkpoint it is near ("from corner 5 to 0.6 s before corner 6", "1.1 s before CP 6") together with the checkpoint stretch it is in and what that stretch costs you. The Playbook tab holds a prepared set of tricks for the map (speed drift, air-brake landings, wall rides, gear-shift timing, bobsleigh wiggle and line, bug slide, throttle/brake points), each with steps, what it feels like, mistakes, a drill and where on this map to use it. The report's
How to do it section is written from those measured numbers by the server, not by the model. The trick steps are general Trackmania knowledge, not verified against the current physics.
- Replay tab (3D): a real replay of both runs on the same race clock. Your car and the see-through ghost drive the lines they actually drove, turned the way the replay recorded them (banks, jumps, slides), under a dusk sky over terrain with trees and the pillars the track stands on, with a textured road (coloured by the ground), glowing barriers, car shadows, headlights and underglow. Effects: tyre spray on slides (coloured by the ground), sparks under braking, dust and a camera kick on landings, speed streaks, gold trails and arcs for jumps. On screen: the game-style timer and gap, the checkpoint flash with the split, name tags with the distance between the cars, a mini-map, an AIR badge with a landing verdict (clean or rough, from the landing analysis; on bobsleigh and ice maps a sideways landing onto a bank counts as clean when the car keeps its speed), a drift-angle badge, and an arrow input display like the game's (left and right arrows fill with the exact steering, up and down with throttle and brake, with the percentages written out) for both drivers. Slow it to 1/20, step one frame (50 ms, or 10 ms with shift), and move the camera: chase you or the ghost, both cars, hood, orbit, trackside (it moves itself ahead of the cars, or pin it), top down, with sliders and drag/scroll to look around. The Air list replays any jump in slow motion. A shot list cuts between cameras and slows down at chosen times (editable, saved per map; Auto-direct cuts to the costliest corners and the jumps), and Record clip / Photo save a video or a picture. The world is built from the lines driven, not the map's own blocks. It loads three.js from a CDN, like Chart.js.
- Coach captions in the Replay: at the moments that matter, a caption appears while it happens and says what to change ("Corner 4: you turn in 0.24 s earlier, the ghost holds 0.63 of lock, you 0.53"), colour-coded for time lost, gained or a note. They are written from the same measured numbers behind the coach report (each corner's brake, turn-in and throttle timing, speeds and steering, the steering plan's zones, the playbook's tricks and the costliest checkpoint stretches), with no AI call, at most two on screen at once. A Coach notes list jumps to each one in slow motion, markers show them on the scrub bar, and they can be read aloud with the browser's voice (off by default).
- Progress tab: how you are getting on with a map, from your own runs oldest first: the time of each against the medals, a personal-best line, the time each checkpoint stretch took run after run (with trend), and, by comparing each of your recent runs (up to eight) with the same ghost, which corners are improving, steady or slipping. It ends with a concrete target for the next session (your own best stretches added up, the corner that is stuck, the next medal). Corner comparisons are remembered in the browser so the tab opens instantly next time.
- Road and blocks in the Replay: the road is drawn with a Trackmania-style surface for each kind of ground (dark asphalt with edge lines, bumps, plastic, dirt, grass, glossy ice) with a seam every 32 m like block joins.
/api/blocks returns the map's blocks near your line from the map file (name, grid cell, level, facing, shape family), and the Replay draws the ones it can place from the road itself: flat pieces on the same level as the road's platforms, as block-sized platforms with seams, and pillars standing from the road down to the ground. Ramps, curves, free blocks and custom items are not in the block list, so on maps built from them little or nothing is added and the road is the driven line alone. A "Map blocks" switch turns the blocks off.
- Timing tower and more ghosts in the Replay: every ghost you have selected (up to five) is on the track as a see-through car in its own colour, with a live timing tower (ranked by how far each has got, gap to the leader in seconds, finish time once across the line). The HUD also shows "on pace for" (the ghost's finish plus today's gap, like the Predictor plugin) and, at each checkpoint, your speed and the difference to the ghost's, like Split Speeds. A free camera (W A S D, Q and E, drag to look, + and - for speed, shift to boost) and Home/End keys follow the game's own replay editor. The Cockpit has the same arrow pad, on-pace line and split speeds. The Replay's on-screen display scales with the size of the picture and has its own HUD size slider and switches for the timer, timing tower, inputs and mini-map (remembered between visits), so it never has to cover the action.
- Cockpit tab: a live replay of both runs' inputs. A speed gauge, a steering wheel that turns with the input and gas/brake bars for you and for the ghost (with a pill for what each is doing: braking, coasting, full lock, full throttle), the gap to the ghost as a scrubbable curve, a mini-map, and a scrolling input tape of steering and pedals around "now". Line the drivers up by the same spot on the track or by the race clock. The moments that cost the most jump to the run-up of that corner, an optional co-driver voice reads pace notes while it plays, and a Driver DNA radar compares entry, corner and exit speed and input smoothness against the ghost. Keys: space, arrows (shift for 5 s) and , . for single frames.
- Checkpoints: the checkpoint times the game stored in each replay or ghost give a split table (your time, the ghost's,
the gap at each checkpoint and over each stretch), checkpoint flags with the gap on the track, and sections that run
between checkpoints ("CP 2 → CP 3") instead of equal slices. The coach gets the splits too. The replay keeps recording
after the finish line, so runs are now cut at the finish, which also corrects the final gap and the last section.
Runs saved before the parser kept these times show equal-distance sections: re-import them.
- Tricks, jumps and landings: from the car's recorded orientation the app scores every landing (nose angle against
the slope, sideways tilt, speed lost, flips in the air) and finds wall-rides and upside-down stretches. With several
ghosts selected it also shows what most of them do that you don't: a different line that gains time, a jump line, an
air-brake spot. They appear as cards on the overview and as flags on the track, and the coach is told about them.
Runs saved before this was added don't carry the orientation: re-import them.
- Input calm: a 0-100 score for how calm your wheel and pedals were against the ghost's (a comparison on the same map,
not a skill rating).
- Share cards: one click makes a 1200x630 picture of the lap or of a corner (line, markers, time lost) to save, copy or
share to Discord.
- Track of the Day: the home page shows today's TOTD with the world record, how far your best is from it, and a button
that downloads the record ghost and compares it with your run.
- Challenge links: "Challenge link" on a comparison stores both runs for 30 days under a short link; anyone who opens
it sees the comparison. Needs Upstash / Vercel KV on Vercel (it works in memory locally); only runs you choose to share
are stored.
- Full world leaderboard: page through every player, jump to a rank, or find where
your own time sits (the board is searched by time, so it works on any map).
- What to focus on: ranked, titled focus areas ("Carry more speed through the
hairpin at 1882–2032 m") with the measured evidence and the time at stake, plus
the stretches you're already good at.
- Search a username for their profile and zone standing.
- Find a map (ManiaExchange), see its world leaderboard, and import the top
ghosts or community replays with one click — or upload your own
.Gbx.
- AI coaching with a choice of detail (Concise / Detailed / Very detailed).
- Your runs are saved in your browser, not on a server.
- The coach remembers its last session on a map and checks whether you improved.
Run it locally
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt # macOS/Linux: .venv/bin/pip
copy .env.example .env # then put your NVIDIA key in .env
.venv\Scripts\uvicorn backend.main:app --reload
Open http://127.0.0.1:8000. Get an NVIDIA NIM key at https://build.nvidia.com.
Keep real keys in .env only — it is git-ignored; .env.example is the shareable template.
Deploy to Vercel (step by step)
The app is a FastAPI function plus a static public/ folder; Vercel detects it
with no build step. You need a free account at https://vercel.com/signup.
Option A — Vercel CLI (fastest, no GitHub needed)
- Install Node.js (https://nodejs.org), then in a terminal:
npm i -g vercel
- Open the project folder in the terminal and run
vercel login (it opens your
browser to sign in).
- Run
vercel. Answer: Set up and deploy? Y → pick your account → Link to
existing project? N → accept the project name → directory ./ → it
detects FastAPI; override settings? N. You get a preview URL.
- Add your settings (each command asks you to paste the value):
vercel env add NVIDIA_NIM_API_KEYS production # your key(s), comma-separated
vercel env add ACCESS_CODE production # optional: a password for the site
vercel env add ADMIN_CODE production # optional: lets *you* skip the AI limits
- Run
vercel --prod. It prints your live address, e.g.
https://trackmania-ai-analyzer-xxxx.vercel.app. Environment variables only
apply to deployments made after you add them, so always redeploy.
Option B — GitHub (auto-deploys every time you push)
- Create an empty repository on github.com (private is fine).
- In the project folder:
git init
git add .
git status # check that .env, .env.txt, data/ and .venv are NOT listed
git commit -m "Trackmania AI Analyzer"
git branch -M main
git remote add origin https://github.com/YOU/REPO.git
git push -u origin main
- On vercel.com choose Add New → Project, import the repository, open
Environment Variables, add the names from the table below, and click
Deploy.
- From then on, every
git push redeploys the site.
Then
Open your URL, click ⚙ Settings (enter your access/admin code if you set
them), and try it: find a map → import a ghost → compare → Analyze with AI.
Environment variables
| Name | Purpose |
|---|
NVIDIA_NIM_API_KEYS | One or more NVIDIA NIM keys (comma, space or new-line separated). Each AI request uses the next key in rotation; if one is throttled or rejected the request moves to another. NVIDIA_NIM_API_KEY (one key) also works. Optional: visitors can paste their own in Settings instead. |
AI_LIMIT_PER_HOUR, AI_LIMIT_PER_DAY | Free AI analyses per visitor (defaults on Vercel: 5/hour, 20/day; 0 = unlimited). Visitors who paste their own key aren't limited. |
AI_LIMIT_GLOBAL_PER_DAY | Optional cap on all visitors combined per day, to protect your keys' quota. |
API_LIMIT_PER_MINUTE | Per-visitor cap on API calls per minute (default 120 on Vercel). |
ADMIN_CODE | Enter it in Settings to skip the AI limits yourself. |
ACCESS_CODE | If set, every /api call needs this code (visitors enter it in Settings) — a password for the whole site. |
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN | Shared counter store so rate limits are exact (see below). KV_REST_API_URL / KV_REST_API_TOKEN work too. |
API_CONTACT | Appended to the User-Agent sent to ManiaExchange / trackmania.io (they ask for an identifiable agent). |
TMIO_API_KEY | Free trackmania.io key for a higher rate limit. |
NIM_MODEL, NIM_URL | Use a different NIM model or a self-hosted endpoint. |
AI keys and rate limits
- Key pool. Put several keys in
NVIDIA_NIM_API_KEYS. Requests rotate through
them one at a time, spreading load across each key's own free-tier limits. A key
that NVIDIA rate-limits (429) is benched for 45 s, one it rejects (401) for an
hour, and the request moves straight on to the next key. Keys are never sent to
the browser or logged.
- Capacity is shared. NVIDIA's free tier also runs out of worker capacity for
everyone at once; that isn't fixed by more keys. The app backs off and retries
a few times, then shows a friendly "at capacity, try again" message and does not
count the attempt against the visitor's allowance.
- Per-visitor limits are on by default on Vercel (5/hour, 20/day; visitors are
identified by a hash of their IP, never stored raw). Out of the box each serverless
instance counts on its own, so a determined visitor could exceed the limit across
instances. For exact limits add Upstash for Redis: Vercel dashboard →
Storage → Create → Upstash for Redis → connect it to the project →
redeploy. It sets the
KV_REST_API_* variables, which the app picks up
automatically (the Settings panel and /api/health report which backend is
active). If that store is ever unreachable, the limiter falls back to
per-instance counting instead of blocking everyone.
- Detail level (Concise / Detailed / Very detailed) controls how much the AI is
asked for and how long it may think and write.
Things to know on Vercel
- Nothing is stored server-side. Runs live in each visitor's browser
(IndexedDB) and are sent along with each comparison request, so the
read-only filesystem and lack of a database don't matter, and visitors never
see each other's runs. Clearing site data removes them.
- Request size limit: 4.5 MB. Uploads above ~4.3 MB are refused with a clear
message (import big replays from ManiaExchange / trackmania.io instead —
those download server-side, so the limit doesn't apply). Comparing several
ghosts at once sends all their telemetry; the page warns if it gets too big.
- Duration. A "Very detailed" AI analysis can take a few minutes. Functions
default to 300 s on current plans; the app stops waiting at 270 s and returns
whatever the AI has written so far rather than failing.
- Python version is Vercel's default (3.12); the code runs on 3.12+.
- Troubleshooting. Build can't find the app: make sure
pyproject.toml is in
the deployed folder. Env var change has no effect: redeploy. "Too large"
errors: import instead of uploading, or compare fewer ghosts at once.
How it works
backend/gbx_parser.py — self-contained Gbx parser: header metadata and the
~50 ms vehicle telemetry (position, speed, steering, gas, brake), including
the newer columnar delta-encoded format used by current ghosts. Uses a
vendored pure-Python LZO decompressor (lzo1x.py) since the C python-lzo
won't build on most machines or serverless platforms.
backend/compare.py — aligns two runs by position (interpolating between
samples, so the time gap is smooth rather than stepped in 50 ms jumps) and
produces the whole-track traces, corners (detected from the ghost's true
path curvature, not noisy steering input), equal-distance sections with
full-resolution traces, steering metrics, and an alignment check that warns
when two runs don't follow the same route.
backend/mapblocks.py, surface.py — read the map's blocks (own Gbx map parser, no keys) and
turn them into a surface label for every point of the lap. It is an estimate: the labels come from
the nearest blocks, so custom or very unusual blocks may show as "unknown".
public/lap.js — the lap-at-a-glance strip, the ground card and the ground strip on the charts.
backend/blueprint.py — the references' steering blueprint and the zones where yours differs.
backend/landmarks.py — turns a distance into corners, checkpoints and seconds.
backend/playbook.py — the per-map trick cards and the How to do it section.
backend/checkpoints.py — splits and checkpoint-based sections from the times stored in the replay.
backend/driving.py — landings, wall-rides, input smoothness and what the top ghosts share. shares.py — the 30-day store
behind challenge links. public/share.js — the share-card images.
backend/inputs.py — the steering / brake / lift runs through each corner.
backend/focus.py — ranks the titled focus areas from the measured
corners/sections (deterministic, no AI, so they always match the charts).
backend/keypool.py, ratelimit.py — the rotating key pool and per-visitor limits.
backend/coach.py, coach_knowledge.py, nim_client.py — builds the
coaching prompt (measured corners/sections/steering, map tags, leaderboard and
zone context, the last session's notes) with a Trackmania coaching knowledge
base, and calls NVIDIA NIM.
backend/mx_client.py, tmio_client.py, net.py — ManiaExchange and
trackmania.io clients (no keys needed). Every id that becomes part of an
outbound URL is validated and downloads are size-capped.
Limits
- Corner detection finds stretches where the ghost's path curves (~95 m radius or
tighter); on a mostly straight map there may only be a few.
- Left/right labels assume the usual convention (+1 steering = right), which
matched the path geometry on real runs.
- "Input device" (keyboard vs pad) is inferred from steering values — an estimate.
- Some replays carry no per-tick telemetry; they compare by finish time only.
- Zone standing is trophy-based (what trackmania.io exposes without Nadeo OAuth);
world position is exact only within the top 50.
- The telemetry formats are community-documented; a future game update could
change them.