Skip to content

Geotag videos from NMEA files - #869

Merged
caglarpir merged 1 commit into
mapillary:mainfrom
caglarpir:geotag-videos-from-nmea
Oct 22, 2026
Merged

caglarpir merged 1 commit into
mapillary:mainfrom
caglarpir:geotag-videos-from-nmea

Conversation

@caglarpir

Copy link
Copy Markdown
Contributor

Stacked on #868; review the last commit.

Problem

The README lists NMEA among the sources that geotag videos, but no video was read from an NMEA file (factory._build_video_geotag(): "TODO: geotag videos from NMEA"):

mapillary_tools process MAH04813.MP4 --geotag_source nmea --geotag_source_path MAH04813.nmea   # [] and exit 0

Sampling fell back to the GPS in the video, which a video recorded with an external logger does not have.

Fix

Read the NMEA file into a track and place it on the video exactly as a GPX track: synced by the video's GPS clock, by --video_start_time, or assumed to start with the video, with the interpolation options, the coverage checks and the clipping of process. GPXVideoExtractor reads its file through _parse_tracks(), which NMEAVideoExtractor overrides, and names the file's format in its messages (GPX messages are unchanged). A file that is not valid NMEA gets MapillaryInvalidGPXError, as an invalid GPX does. Interval sampling checks an NMEA track started by --interpolation_use_gpx_start_time as it checks a GPX track.

Verification

  • Sony FDR-X3000 MAH04813.MP4 with its track as GPX and as NMEA: process gives the same 650 points (time, position, altitude, epoch); video_process by interval (130 frames) and by distance (159) samples the same frames at the same positions (headings within 0.003°, from NMEA rounding).
  • GPX runs are unchanged.
  • New unit tests and an integration test comparing NMEA with GPX. Unit and integration tests, doctests, mypy --python-version 3.9, ruff check, ruff format --check and usort diff are clean.

The README lists NMEA among the sources that geotag videos, but no video
was read from an NMEA file: process and video_process gave the video no
description at all, and exited 0, so it was silently left out. Sampling
fell back to the GPS in the video, which a video recorded with an
external logger does not have.

Read the NMEA file into a track and place it on the video exactly as a
GPX track is: synced by the GPS clock of the video, or by
--video_start_time, or assumed to start with the video, with the
interpolation options, the coverage checks and the clipping of process.
GPXVideoExtractor now reads its file through _parse_tracks(), which
NMEAVideoExtractor overrides, and names the format of the file in its
messages. A file that is not valid NMEA is reported as an invalid GPX
file is. Interval sampling checks an NMEA track started with the video
by --interpolation_use_gpx_start_time as it checks a GPX track.

On an action camera video with a GPX and the same track as NMEA, process gives
the same track, and video_process samples the same frames at the same
positions.
@caglarpir
caglarpir force-pushed the geotag-videos-from-nmea branch from 8c7b13e to 2efacb8 Compare October 22, 2026 20:18
@caglarpir
caglarpir merged commit a42ab89 into mapillary:main Oct 22, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant