Generate 3D trail videos from GPX files using a Python CLI, MapLibre GL, and ffmpeg.
- Install dependencies with
uv:
uv venv
uv pip install -e ".[dev]"- Configure defaults (recommended):
uv run trailgen configureOr add your map provider credentials in .env:
# MapTiler (default)
MAPTILER_KEY=your_key_here
# Optional: terrain exaggeration (MapDirector uses ~1.5)
# MAP_TERRAIN_EXAGGERATION=1.5
# Mapbox (optional, MapDirector-like satellite labels)
# MAP_PROVIDER=mapbox
# MAPBOX_TOKEN=your_token_here
# MAPBOX_STYLE_URL=https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v12?access_token={token}
# MAPBOX_TERRAIN_TILES=https://api.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/{z}/{x}/{y}.png?access_token={token}
# MAP_MAX_ZOOM=18- Install Playwright browser binaries (one-time):
uv run playwright install chromiumNote: Installing the Python package does not install Playwright browser binaries. You must run the command above on each machine.
- Optional: vendor MapLibre assets (recommended for production/offline):
scripts/vendor_maplibre.shIf you skip this step, MapLibre will load from the CDN as a fallback.
- Render a video (vertical 720p @ 30 fps):
uv run trailgen render --gpx /path/to/route.gpx --out outputs/route.mp4 --fps 30 --resolution 720p --orientation portrait --duration 45Note: uv init is only for creating new projects. This repo already has pyproject.toml, so you can go straight to uv venv/uv run.
Tiles are cached on disk at ~/.trailgen/cache.
Config is stored in a local file (created by trailgen configure):
- macOS:
~/Library/Application Support/trailgen/config.ini - Linux:
~/.config/trailgen/config.ini
Override with TRAILGEN_CONFIG_PATH.
Environment overrides (highest priority):
MAP_PROVIDER(maptiler|mapbox)MAPTILER_KEYorTRAILGEN_MAPTILER_KEYMAPBOX_TOKENTRAILGEN_STYLE_URL(orMAPBOX_STYLE_URLfor mapbox)TRAILGEN_TERRAIN_TILES(orMAPBOX_TERRAIN_TILESfor mapbox)TRAILGEN_TERRAIN_ENCODINGTRAILGEN_TERRAIN_EXAGGERATION(also supportsMAP_TERRAIN_EXAGGERATION,TERRAIN_EXAGGERATION)TRAILGEN_MAX_ZOOM(orMAP_MAX_ZOOM)TRAILGEN_CACHE_DIRTRAILGEN_CACHE_MAX(bytes or KB/MB/GB/TB)TRAILGEN_PAGE_TIMEOUT_MSTRAILGEN_FRAME_TIMEOUT_MSTRAILGEN_TILE_TIMEOUT_S
- Presets:
--resolution 720p|1080p|4k - Orientation:
--orientation portrait|landscape - Override with explicit
--widthand--height
Example 1080p portrait @ 60 fps:
uv run trailgen render --gpx /path/to/route.gpx --out outputs/route-1080.mp4 --fps 60 --resolution 1080p --orientation portrait --duration 45Use a 4K frame size:
uv run trailgen render --gpx /path/to/route.gpx --out outputs/route-4k.mp4 --fps 60 --resolution 4k --orientation landscape --duration 45The renderer uses MapTiler's hybrid-v4 style by default and a terrain DEM for 3D relief. To match MapDirector's look, switch to Mapbox:
MAP_PROVIDER=mapbox
MAPBOX_TOKEN=your_token_here
MAP_MAX_ZOOM=18If you have access to the MapDirector style, you can set:
MAPBOX_STYLE_URL=https://api.mapbox.com/styles/v1/brunomapdirector/cm7uf30u5019501s21cdtbe2c?access_token={token}Customize colors and widths:
uv run trailgen render --gpx /path/to/route.gpx --out outputs/route.mp4 --route-color \"#22c55e\" --route-width 5- The renderer writes PNG frames and then encodes to H.264 MP4 using ffmpeg.
- Use
--keep-framesto keep PNGs for debugging. - Use
--frames-dirto direct frames to a specific folder. - Fly-in/out tuning options:
--intro-seconds,--outro-seconds,--orbit-deg,--zoom-out,--pitch-drop. - The renderer serves a local HTTP page and proxies tiles to avoid CORS issues with tile requests.
Use --camera-mode auto (default) for adaptive terrain-aware framing, or --camera-mode follow to match a fixed distance/pitch style (similar to MapDirector).
Example follow mode:
uv run trailgen render --gpx /path/to/route.gpx --out outputs/route-follow.mp4 \\
--camera-mode follow --follow-distance-m 500 --follow-pitch 60 \\
--follow-lookahead-m 120 --follow-bearing-sensitivity 3 \\
--follow-panning-sensitivity 1.5 --follow-smoothing-s 0.5- If you see
ffmpeg not found, install ffmpeg and ensure it is on your PATH. - If Playwright cannot launch, re-run
playwright install chromium. - To enable verbose network/debug logs, set
TRAILGEN_DEBUG=1.
Install pre-commit hooks:
uv run pre-commit installRun format/lint:
make format
make lint
make precommitRelease build and tag:
make release VERSION=0.1.0This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE.