F1ReplayTiming
Visualisation of real-time track data and telemetry synced to F1 replays.
Install / Use
/learn @adn8naiagent/F1ReplayTimingREADME
https://github.com/user-attachments/assets/952b8634-2470-46d9-96e2-67a820459a49
Disclaimer: This project is intended for personal, non-commercial use only. This website is unofficial and is not associated in any way with the Formula 1 companies. F1, FORMULA ONE, FORMULA 1, FIA FORMULA ONE WORLD CHAMPIONSHIP, GRAND PRIX and related marks are trade marks of Formula One Licensing B.V.
A web app for watching Formula 1 sessions with real timing data, car positions on track, driver telemetry, and more - both live during race weekends and as replays of past sessions. Built with Next.js and FastAPI.
Features
- Live timing (Beta) - connect to live F1 sessions during race weekends with real-time data from the F1 SignalR stream, including a broadcast delay slider and automatic detection of post-session replays
- Track map with real-time car positions from GPS telemetry, updating every 0.5 seconds with smooth interpolation, marshal sector flags, and toggleable corner numbers
- Driver leaderboard showing position, gap to leader, interval, last lap time, tyre compound and age, tyre history, pit stop count and live pit timer, grid position changes, fastest lap indicator, investigation/penalty status, and sub-1-second interval highlighting
- Race control messages - steward decisions, investigations, penalties, track limits, and flag changes displayed in a draggable overlay on the track map with optional sound notifications
- Pit position prediction estimates where a driver would rejoin if they pitted now, with predicted gap ahead and behind, using precomputed pit loss times per circuit with Safety Car and Virtual Safety Car adjustments
- Telemetry for unlimited drivers showing speed, throttle, brake, gear, and DRS (2025 and earlier) plotted against track distance, with a moveable side panel for 3+ driver comparisons
- Lap Analysis (Beta) compare lap times for up to two drivers with a line chart and lap-by-lap history, with pit stop and safety car periods highlighted. Race replay only
- Picture-in-Picture mode for a compact floating window with track map, race control, leaderboard, and telemetry
- Broadcast sync - match the replay to a recording of a session, either by uploading a screenshot of the timing tower (using AI vision) or by manually entering gap times
- Weather data including air and track temperature, humidity, wind, and rainfall status
- Track status flags for green, yellow, Safety Car, Virtual Safety Car, and red flag conditions
- Playback controls with 0.5x to 20x speed, skip buttons (5s, 30s, 1m, 5m), lap jumping, a progress bar, and red flag countdown with skip-to-restart
- Session support for races, qualifying, sprint qualifying, and practice sessions from 2024 onwards
- Full screen mode hides the session banner and enters browser fullscreen for a distraction-free view
- Imperial units toggle for °F and mph in settings
- Passphrase authentication to optionally restrict access when publicly hosted
Architecture
- Frontend: Next.js (React) with Tailwind CSS
- Backend: FastAPI (Python) - serves pre-computed data from local storage or Cloudflare R2
- Data Source: FastF1 (used during data processing only)
Session data is processed once and stored locally (or in R2 for remote access). You can either pre-compute data in bulk ahead of time, or let the app process sessions on demand when you select them.
Self-Hosting Guide
Option A: Docker with pre-built images (easiest)
Requires Docker and Docker Compose.
Create a docker-compose.yml file:
services:
backend:
image: ghcr.io/adn8naiagent/f1replaytiming-backend:latest
ports:
- "8000:8000"
environment:
- FRONTEND_URL=http://localhost:3000
- DATA_DIR=/data
volumes:
- f1data:/data
- f1cache:/data/fastf1-cache
frontend:
image: ghcr.io/adn8naiagent/f1replaytiming-frontend:latest
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8000 # Change to your backend URL if not using localhost
depends_on:
- backend
volumes:
f1data:
f1cache:
Then run:
docker compose up
Open http://localhost:3000. Select any past session and it will be processed on demand.
Option B: Docker from source
If you prefer to build the images yourself, or want to make changes to the code:
git clone <repo-url>
cd F1timing
docker compose up
Open http://localhost:3000. Select any past session and it will be processed on demand.
Docker configuration
Network & URL configuration
Two environment variables control how the frontend and backend find each other:
| Variable | Set on | Purpose |
|---|---|---|
| NEXT_PUBLIC_API_URL | frontend | The URL your browser uses to reach the backend |
| FRONTEND_URL | backend | The URL your browser uses to reach the frontend (needed for CORS) |
The defaults (http://localhost:8000 and http://localhost:3000) work when accessing the app on the same machine running Docker. If you access from another device, use a reverse proxy, or change ports, update both variables to match.
Example — accessing from other devices on your network:
backend:
environment:
- FRONTEND_URL=http://192.168.1.50:3000
frontend:
environment:
- NEXT_PUBLIC_API_URL=http://192.168.1.50:8000
Example — behind a reverse proxy (e.g. Cloudflare Tunnel, nginx):
backend:
environment:
- FRONTEND_URL=https://f1.example.com
frontend:
environment:
- NEXT_PUBLIC_API_URL=https://api.f1.example.com
In this setup your reverse proxy routes f1.example.com to the frontend container (port 3000) and api.f1.example.com to the backend container (port 8000).
Optional features
OPENROUTER_API_KEY- enables the photo sync feature (get a key)AUTH_ENABLED/AUTH_PASSPHRASE- restricts access with a passphrase
Data
Session data is persisted in a Docker volume, so it survives restarts.
To pre-process session data in bulk (instead of on demand), use the precompute script:
# Process a specific race weekend
docker compose exec backend python precompute.py 2026 --round 1
# Process only the race session (skip practice/qualifying)
docker compose exec backend python precompute.py 2026 --round 1 --session R
# Process an entire season (will take several hours)
docker compose exec backend python precompute.py 2025 --skip-existing
# Process multiple years
docker compose exec backend python precompute.py 2024 2025 --skip-existing
Option C: Manual setup
Prerequisites
- Python 3.10+
- Node.js 18+
- An OpenRouter API key (optional, enables photo/screenshot sync - manual entry sync works without this)
1. Clone the repository
git clone <repo-url>
cd F1timing
2. Configure environment variables
Backend (backend/.env):
FRONTEND_URL=http://localhost:3000
PORT=8000
DATA_DIR=./data
# Optional - enables photo/screenshot sync (manual entry sync works without this)
# Get a key from https://openrouter.ai/
OPENROUTER_API_KEY=
# Optional - restrict access with a passphrase
AUTH_ENABLED=false
AUTH_PASSPHRASE=
Frontend (frontend/.env):
NEXT_PUBLIC_API_URL=http://localhost:8000
3. Install dependencies and start
# Backend
cd backend
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --reload --port 8000
# Frontend (in a separate terminal)
cd frontend
npm install
npm run dev
Open http://localhost:3000.
4. Getting session data
There are two ways to get session data into the app:
Option A: On-demand processing (recommended for getting started)
Simply select any past session from the homepage. If the data hasn't been processed yet, the app will automatically fetch and process it using FastF1 and start the replay. The first load of a session takes 1-3 minutes. After that, it's instant.
Option B: Bulk pre-compute (recommended for preparing a full season)
Use the CLI script to process sessions ahead of time. This is useful if you want all data ready before you start using the app.
cd backend
source venv/bin/activate
# Process a specific race weekend
python precompute.py 2026 --round 1
# Process only the race session (skip practice/qualifying)
python precompute.py 2026 --round 1 --session R
# Process an entire season (will take several hours)
python precompute.py 2025 --skip-existing
# Process multiple years
python precompute.py 2024 2025 --skip-existing
Timing estimates:
- A single session (e.g. one race) takes 1-3 minutes
- A full race weekend (FP1, FP2, FP3, Qualifying, Race) takes 3-5 minutes
- A complete season (~24 rounds, all sessions) takes 2-3 hours
The app also includes a background task that automatically checks for and processes new session data on race weekends (Friday–Monday).
Photo Sync Feature
The broadcast sync feature lets you match the replay to a recording of a session. You can always sync manually by entering gap times directly. To also enable photo/screenshot sync (where the app reads the timing tower from an image), set an OpenRouter API key as OPENROUTER_API_KEY. It uses a vision model (Gemini Flash) to read the leaderboard from the photo. Any OpenRouter-compatible API key will work.
Acknowledgements
This project is powered by FastF1, an open-source Python library for accessing Formula 1 timing and telemetry data. FastF1 is the original inspiration and data source for this project - without it, none of this would be
