gps-video-sync
Find each video's clock offset relative to an IGC GPS flight track. The offset maps timestamps in the video to UTC times on the track, even when the camera's date or time is wrong.
The tool uses camera GPS time when available and falls back to motion matching. It also checks clock drift and can plot the alignment. In a batch, two accepted recordings from the same camera can place clips which have otherwise weak evidence.
Install
Requires Python 3.10 or later. Tests cover Python 3.10 to 3.15.
uv tool install gps-video-sync
or with pip
pip install gps-video-sync
Align recordings
Match your recordings against an IGC flight track and save the results:
gps-video-sync sync takeoff.MP4 ridge.MP4 landing.MP4 --track flight.igc --json sync.json
Use one or more recordings, each listed once. Include all recordings from the flight to help align short clips. File order does not matter.
Each recording gets a result in sync.json. ok means it has an alignment.
ambiguous means there is not enough reliable evidence. failed means the
recording could not be processed. Other recordings still get their results.
Run gps-video-sync sync --help for more options.
Results contain file paths and recording dates. Remove private data before sharing.
Use the Python API
from gps_video_sync import match_videos, read_track, read_video, synchronize
track = read_track("flight.igc")
results = match_videos(track, ["takeoff.MP4", "ridge.MP4", "landing.MP4"])
for result in results:
print(result.video, result.status, result.offset_seconds)
telemetry = read_video("ridge.MP4", hz=10)
result = synchronize(track, telemetry)
match_videos returns one result per input, in input order. It joins confirmed
continuous chapters and places unresolved clips from camera-session anchors.
A file error gives a failed result for that file only. read_video reads one
recording. synchronize matches one recording and also accepts array-based
Telemetry.
To match exported telemetry, use source="npz" in the API or --source npz in
the CLI. NPZ exports from telemetry --out keep the original recording
identity, duration, media offset, and optional recording-clock and camera-start
evidence. Telemetry.slice clears both kinds of timing evidence. In a batch
result, input_file identifies the NPZ archive.
The result maps video seconds to UTC seconds from midnight of the track date:
utc_seconds = video_seconds * clockRate + offset_seconds
Supported cameras
The bundled test recordings are from a GoPro HERO11 Black. They test motion alignment but contain no GPS data. GPS extraction and alignment have synthetic tests only. GoPro documents compatible metadata for the other models below, but this package has no recordings from them. Their extraction, alignment, and frame verification are untested.
The reader needs a timed GPMF track with sample format gpmd in the original
video. It uses these fields:
GPS9supplies UTC and fix status for GPS alignment. The olderGPS5format needsGPSUfor UTC andGPSFfor fix status. The reader accepts only valid 3D fixes.GPS9takes priority when both formats occur in a packet.GYROandACCLsupply the motion features. Motion alignment works without camera GPS, within the limits below.- The reader also extracts
GRAV,CORI, andIORIwhen present. Alignment does not need these fields. The matcher estimates gravity fromACCL.
| Camera | GPS metadata for UTC alignment | GYRO + ACCL |
GRAV + CORI + IORI |
Compatibility / test status |
|---|---|---|---|---|
| HERO5 Black | GPS5 + GPSU + GPSF |
Yes | Not documented | GPS and motion expected; untested |
| HERO5 Session | None | Yes | Not documented | Motion only expected; untested |
| HERO6 Black | GPS5 + GPSU + GPSF |
Yes | Not documented | GPS and motion expected; untested |
| HERO7 Black | GPS5 + GPSU + GPSF |
Yes | Not documented | GPS and motion expected; untested |
| HERO8 Black | GPS5 + GPSU + GPSF |
Yes | Yes | GPS and motion expected; untested |
| HERO9 Black | GPS5 + GPSU + GPSF |
Yes | Yes | GPS and motion expected; untested |
| HERO10 Black | GPS5 + GPSU + GPSF |
Yes | Yes | GPS and motion expected; untested |
| HERO10 Black Bones | None | Yes | Yes | Motion only expected; untested |
| HERO11 Black | GPS9, plus legacy GPS5 |
Yes | Yes | Motion tested with bundled recordings; GPS untested |
| HERO12 Black | None | Yes | Yes | Motion only expected; untested |
| HERO13 Black | GPS9 |
Yes | Yes | GPS and motion expected; untested |
| Fusion | Not documented in the cited table | Yes | Not documented | Motion metadata compatible; 360 workflow untested |
| MAX | GPS5 + GPSU + GPSF |
Yes | Yes | Metadata compatible; 360 workflow untested |
| MAX2 | GPS9 |
Yes | Yes | Metadata compatible; 360 workflow untested |
| MISSION 1 family | GPS9 |
Yes | Yes | Metadata compatible per GoPro; untested |
Use original, normal-speed recordings. Enable GPS on cameras that have it and
wait for a satellite lock before you record. Some clips can still lack usable
fixes. Edited, transcoded, or stitched exports can omit the metadata track.
Check each recording with gps-video-sync info.
The 360 camera rows cover sensor metadata only. Stitching, projection, and frame extraction from native 360 files are untested.
The table does not cover Silver, White, Mini, or entry-level HERO models, HERO4 and earlier cameras, external GPS accessories, or special recording modes. A model number or GPS chip alone does not establish compatibility.
Sources:
- GoPro's model-by-model GPMF tables. The documented firmware includes HERO7 v1.8, HERO8 v2.5, and MAX v2.0.
- Gyroflow's GoPro motion-data notes.
Firmware and recording mode can change the available streams. The reader checks for metadata keys, not camera model names.
Limits
GoPro extraction allows at most 1,000,000 resampled samples per recording.
Lower --hz if the recording duration in seconds multiplied by --hz exceeds
this limit.
Motion matching needs at least 90 seconds of usable overlap. The overlap must also cover at least 65% of the shorter feature sequence. Each independent file or confirmed continuous group needs enough varying motion. Repeated turns, data gaps, or low motion can produce ambiguous or false matches. Check the plot and distinctive events before you use an alignment. Short clips cannot establish clock stability. Session placement uses other accepted recordings to place such clips. A GPS UTC step blocks placement. A continuity candidate with no approved common mapping cannot use session placement when it retains an accepted member.
See the API and format reference for data contracts, plugins, telemetry formats, and matching limits.
Run the tests
uv sync --extra dev --extra verify
uv run pytest
uv run python scripts/check_independent_videos.py
uv run python scripts/check_continuous_videos.py
Run the tests from a repository checkout. Release archives exclude tests and fixtures. The bundled fixtures contain flight coordinates, times, and media.
- Extraction and alignment tests need no external program.
- Parity tests use the
ffprobemarker and needffprobe9 or later. - Frame tests need
ffmpegand Matplotlib. - To skip integration tests, run
uv run pytest -m 'not integration'.
scripts/check_continuous_videos.py needs the verify extra and ffmpeg.
It runs the API and the CLI on the bundled recordings with cold and warm
caches. It checks exact boundaries, reordered inputs, subsets, weak chapters,
non-unit drift, gaps, overlaps, counters, contradictory fits, and failures.
It also checks cache rebuilds, NPZ and JSON exports, crops, saved-result
selection, plots, and frames against direct FFmpeg seeks.
scripts/check_independent_videos.py checks independent motion crops and GPS
recordings with gaps, overlaps, shuffled inputs, and isolated failures. It also
checks exports and file-local frame extraction on the bundled videos.
Check an alignment visually
Check an alignment with a plot:
gps-video-sync verify ridge.MP4 --track flight.igc --result sync.json --output ridge.png
Plot output requires the verify extra. Install it with
uv tool install 'gps-video-sync[verify]'.
License
MIT.
Metadata
Release files for gps-video-sync 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| gps_video_sync-1.1.0.tar.gz | 47.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gps_video_sync-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 89.9 kB
Release files / gps_video_sync-1.1.0.tar.gz
| Download URL | gps_video_sync-1.1.0.tar.gz |
|---|---|
| Size | 47.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9d0640eb46d4adca89ca9a62c350e76054ff556bd5cee8893f61c663d5f51d53
|
|
BLAKE2b-256 checksum How to use checksums |
f9a4f6c4fb57c021e4c370a951b07e6c6c3e5b0ab85b86238d09f979c89f828e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / gps_video_sync-1.1.0-py3-none-any.whl
| Download URL | gps_video_sync-1.1.0-py3-none-any.whl |
|---|---|
| Size | 42.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4621064e8414a13f2a1609802a2a6e3943512e3c29787f451bcd8fd0ac65cb19
|
|
BLAKE2b-256 checksum How to use checksums |
c9831f03c116a331cfcddafdfd34673f060377dd2b1f39271f69e98b609f1d75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for gps-video-sync 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for gps_video_sync-1.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.