The Problem
Watching an F1 broadcast alongside timing data usually means juggling a separate timing app that drifts out of sync with the video. Replays are worse — you either get raw telemetry with no video context or a broadcast with no data overlay. This project solves that by pairing real-time F1 telemetry with a video replay, synchronized to the same timeline.
What This Does
F1ReplayTiming is a single-container web app that displays live and historical F1 session data — car positions on a track map, a full leaderboard with tyre/pit/penalty info, driver telemetry, race control messages, and weather — all synced to a video replay. The backend (backend/main.py) is FastAPI and uses FastF1 for data processing; the frontend is Next.js/React with Tailwind, built as static files and served by the backend on one port.
The data layer is split between backend/services/ (data fetching, live SignalR streaming, precomputation) and backend/routers/ (API and WebSocket endpoints). The frontend hooks (frontend/src/hooks/useLiveSocket.ts, useReplaySocket.ts) handle the real-time connection. A notable feature is broadcast sync: upload a screenshot of the timing tower and the app uses AI vision to align the replay to your recording.
How To Use It
Setup — Docker is the intended path. Copy .env.example to .env; defaults work out of the box.
Configuration — The .env file controls port and optional passphrase auth. Cloudflare R2 credentials are optional for persistent session storage; otherwise data is stored locally.
Running it — From the repo root:
cp .env.example .env docker compose up
The app serves the frontend and API from a single port. Sessions can be precomputed in bulk (backend/precompute.py) or processed on demand when selected in the UI.
Real-World Use
A race fan records the broadcast and wants to review a specific stint with full telemetry. They open the app, select the 2024 race from the session picker, upload a screenshot of the timing tower to sync the replay, then scrub through the lap with the track map, leaderboard, and a driver's throttle/brake/gear charts all moving in lockstep. The pit position prediction tells them whether a driver would have gained or lost track position by pitting a lap earlier.
Code Health & Issues
High — No license file. Usage and redistribution rights are unclear. This is a blocker for any commercial or public deployment. Med — Minimal test coverage. Only 1 test file exists for a project with 94 files and complex sync logic. The replay sync and live WebSocket paths are effectively untested. Med — No input validation on API routes. backend/routers/ files accept session IDs, driver numbers, and timestamps without obvious schema enforcement (backend/models/schemas.py exists but is thin). Malformed input could cause errors or unexpected behavior. Low — CI is minimal. .github/workflows/ has PR checks and Docker publish, but no linting or type-checking step visible in the workflow files. Low — frontend/tsconfig.tsbuildinfo is committed. Build artifact noise; should be gitignored. Low — Duplicate pit loss computation. computepitloss.py and computepitloss_v2.py suggest refactoring debt.
The Bottom Line
This is a feature-rich, well-architected F1 data visualizer that works out of the box with Docker. It's genuinely useful for F1 fans who want broadcast-synced telemetry, and the single-container design simplifies self-hosting. The lack of a license and thin test coverage are real concerns for anyone considering production use or redistribution. Best suited for personal use or as a reference implementation for F1 data visualization.