Skip to main content

Visualise & animate GPX race tracks.

Project description

gpx-player

CI codecov PyPI version PyPI downloads License

GPX Race Visualizer

GPX Race Visualizer is a Python script to visualize the progression of multiple GPS tracks (e.g., from a race) on a 2D map. It takes as input one or more GPX files and creates an animation showing the movement of each track over time. This is a simple, open-source alternative to features like Strava's Flyby, which require an account and can have privacy issues.

Modes

The player supports two modes:

1. "Video" mode

Produce an MP4 or a GIF file showing how the situation developed. For sailing races, it also calculates the distance covered after the 'start' signal and the current speed.

Example:

Example output

2. Map mode

Displays the track on OpenSeaMap. You can see the full tracks with colour-coded speeds, and you can 'play' the tracks and see the markers move around the map. While playing, a legend shows each boat's distance travelled (in nautical miles), current speed (in knots), and average speed in knots.

Example:

Since GitHub Markdown doesn't allow embedding HTML, you can see an interactive example here.

Screenshot: OPS Example

Installation

Install directly from PyPI using pip:

pip install gpx-player

Alternatively, clone the repository and install the required dependencies manually:

git clone https://github.com/kirienko/gpx-player.git
cd gpx-player
pip install -r requirements.txt

Usage

To run the script producing mp4, pass one or more GPX file paths as command-line arguments:

gpx-player example-data/track1.gpx example-data/track2.gpx

To get a sea map, run the module:

python -m gpx_player.openseamap --title 'Gin Sul Regatta 2024' --names Alex Yury Richard \
     --files example-data/osm-demo-Alex.gpx example-data/osm-demo-Richard.gpx \
             example-data/osm-demo-Yury.gpx

This writes a static playable HTML map to boat_tracks.html with the title, speed legend, boat stats legend, play/pause button, moving markers, and time slider. Playback maps also include a per-boat track visibility control. Each boat can show the full speed-coloured track, show only a moving tail in the boat colour, or hide both the track and marker.

The same playable OpenSeaMap can be created from Python code:

from gpx_player.openseamap import create_playback_map

folium_map = create_playback_map(
    [
        "example-data/osm-demo-Alex.gpx",
        "example-data/osm-demo-Richard.gpx",
        "example-data/osm-demo-Yury.gpx",
    ],
    names=["Alex", "Richard", "Yury"],
    max_speed=12,
    title="Gin Sul Regatta 2024",
    slider_active_color="#6e6e6e",
    slider_inactive_color="#d0d0d0",
    tail_length="normal",
)
folium_map.save("boat_tracks.html")

slider_active_color and slider_inactive_color are optional Python-only arguments for theming the played and unplayed sections of the playback slider. tail_length controls the point-based tail length in map playback mode: short keeps 30 points, normal keeps 60 points, and long keeps 120 points.

Playback templates and JavaScript are bundled as package assets, so downstream applications can call this API from any current working directory after pip install gpx-player; no source checkout or local asset copies are needed.

OpenStreetMap tile access

The generated HTML uses live raster tiles from tile.openstreetmap.org for the base map and an OpenSeaMap seamark overlay. OpenStreetMap data is open, but the public OSM tile servers are a shared service with a tile usage policy. In particular, browser requests from web pages must send a valid HTTP Referer header.

If you open a generated map directly as a local file://.../boat_tracks.html file, many browsers will not send a valid HTTP Referer for tile requests. OSM may then return "blocked" placeholder tiles linking to https://osm.wiki/blocked. This can happen even for an old HTML file that works normally when hosted on a website.

For local viewing, serve the directory over HTTP instead:

python3 -m http.server 8000

Then open http://localhost:8000/boat_tracks.html in the browser.

For public or production applications, do not rely on the community tile.openstreetmap.org service as an application tile backend. Host the HTML on a normal web origin and use a tile provider, self-hosted tiles, or vector tiles whose terms fit your traffic and offline/static distribution needs.

Restrict the map to a specific time window with --start / --end (same format as in video mode). Speed, distance, map bounds and the animation slider all reflect only the filtered segment:

python -m gpx_player.openseamap --files example-data/osm-demo-Alex.gpx \
     --start 2024-07-24T18:10:00+0200 --end 2024-07-24T18:30:00+0200

Use --tail-length short|normal|long to control the moving tail length in the map track visibility control.

A more sophisticated example, that produced a video above:

gpx-player example-data/track1.gpx example-data/track2.gpx example-data/track3.gpx \
       --start 2023-07-01T10:53:00+0000 \
       --names "Mr. Pommeroy" "Miss Sophie" "Sir Toby²" \
       --title "Elbe-Damm Regatta (01.07.2023), Race 1" \
       --race_start 2023-07-01T10:58:00+0000 --marks example-data/marks.txt -g

Additional parameters:

  • --title or -t: The title of the video
  • --start or -s: start time in the format 2023-06-30T12:53:00+0200, all points before that will not be plotted
  • --end or -e: end time in the format 2023-06-30T13:53:00+0200, all points after that will not be plotted
  • --names or -n: names of the participants (otherwise the file names will be used in the legend)
  • --race_start, -r: Race start time in the format YYYY-MM-DDTHH:MM:SS%z, e.g. 2023-07-01T12:29:00+0200
  • --names or -n: Names of the participants
  • --marksor-m: The file with the static marks to put onto the map. One pair of coordinates per line, see below.
  • --gif or -g: Save as GIF moving picture instead of MP4
  • --timezone or -tz: Local timezone to use for processing timestamps, e.g. America/Los_Angeles, see here (default: Europe/Berlin).

Marks

The script also supports visualizing predefined marks on the map, which can be useful for events like sailing regattas. The marks are defined as a list of (latitude, longitude) tuples in a separate text file and can be added to the script as follows:

53.542484632728, 9.801163896918299
53.542997846049374, 9.80611324310303
53.54823800356785, 9.812614917755129
53.54921647691311, 9.807373881340029
53.54508251196638, 9.80433225631714

Getting GPX Files

GPX files can be obtained from several GPS-tracking services:

  • Strava: Go to the activity page and click on the wrench icon. Then select "Export GPX".
  • Garmin Connect: Open the activity, go to the gear icon and select "Export to GPX".
  • Endomondo: From the workout page, click the three-dot menu icon and select "Export". Then choose "GPX".

GPX Validation

For the gpx-player to work properly, it needs the correct GPX files. You can verify that you are inputting the correct file by using the special validator included in this package.

The validator.py script is a command-line utility and module for validating GPX files. It checks for XML schema conformance and timestamp consistency, supporting both strict and lenient modes. Errors are raised as GPXValidationError which can be caught in Python code. To run as a CLI tool, use:

gpx-validate path/to/yourfile.gpx --strict

Use as a Python module

from gpx_player.validator import validate_gpx, GPXValidationError

try:
    validate_gpx("path/to/yourfile.gpx", strict=True)
    print("GPX file is valid")
except GPXValidationError as e:
    print("GPX validation failed:", e)

The --strict parameter is optional. In most cases you do not need it, because files that strictly correspond to the GPX schema are rare. For example, almost all modern files contain coordinates, elevations and time stamps with more decimal places than originally planned.

Also, to better understand your GPX file, you can use the gpxinfo console command that comes with gpxpy. If you are already using the player, you have it:

$ gpxinfo example-data/osm_track1.gpx 
File: example-data/osm_track1.gpx
    Waypoints: 0
    Routes: 0
    Length 2D: 9.621km
    Length 3D: 9.648km
    Moving time: 01:05:22
    Stopped time: n/a
    Max speed: 3.12m/s = 11.22km/h
    Avg speed: 2.46m/s = 8.85km/h
    Total uphill: 97.20m
    Total downhill: 98.40m
    Started: 2024-07-24 15:59:05+00:00
    Ended: 2024-07-24 17:04:27+00:00
    Points: 776
    Avg distance between points: 12.40m

GPX Cleanup

For convenience, the repository provides clean_gpx.py. This utility first validates a GPX file using validator.py and then removes all <extensions> blocks using :func:remove_extensions_tags from gpx_utils. By default the cleaned file is saved alongside the original with _noext appended to its name. If the optional --overwrite flag is used, the original file is modified in place.

Run it from the command line as follows:

python -m gpx_player.clean_gpx path/to/yourfile.gpx [--overwrite]

If validation fails, the command exits with an error message. The output reports how many extension blocks were removed.

Support

Now you can buy me a coffee to encourage further development!

"Buy Me A Coffee"

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gpx_player-0.5.0.tar.gz (44.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gpx_player-0.5.0-py3-none-any.whl (45.4 kB view details)

Uploaded Python 3

File details

Details for the file gpx_player-0.5.0.tar.gz.

File metadata

  • Download URL: gpx_player-0.5.0.tar.gz
  • Upload date:
  • Size: 44.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gpx_player-0.5.0.tar.gz
Algorithm Hash digest
SHA256 a71f27f3c70e69d0b524ba4d5907141bea195227ac8ce1088cc4176ecd114357
MD5 ad148beda315e7dcc30e5188f9053cfa
BLAKE2b-256 af24d3c7aea36eeb726b9b9e634e090e54d88869abe5a1a36fcf63f433d7bcc6

See more details on using hashes here.

Provenance

The following attestation bundles were made for gpx_player-0.5.0.tar.gz:

Publisher: publish.yml on kirienko/gpx-player

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gpx_player-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: gpx_player-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 45.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gpx_player-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 618079937a521822fc636feb4d65a6599c3a1ec70a9b9286462b93fbd278dabf
MD5 09ee5211bb8966fbd729ada99ada28d1
BLAKE2b-256 02edb783f5ddc3140cf3d769cdd187d46a3c8d4640e03f47682100411605a0f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for gpx_player-0.5.0-py3-none-any.whl:

Publisher: publish.yml on kirienko/gpx-player

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page