Skip to content

Keep a timelapse's clock rate when the GPX starts with the video - #853

Merged
caglarpir merged 3 commits into
mapillary:mainfrom
caglarpir:gpx-start-time-keeps-clock-rate
Oct 22, 2026
Merged

caglarpir merged 3 commits into
mapillary:mainfrom
caglarpir:gpx-start-time-keeps-clock-rate

Conversation

@caglarpir

@caglarpir caglarpir commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Problem

--interpolation_use_gpx_start_time skips reading the video's GPS clock, and with it the clock's rate (#849), so a timelapse gets its GPX laid out at 1x. Distance sampling a 5 s, 30x GoPro MAX timelapse picks 5 frames along the first 12 m of its 1.4 km route.

Changes

  • In that mode the clock is still read, and placed at the start of the GPX, so that only its rate is used. A video that is not a timelapse has a rate of 1 and is placed as before.
  • The coverage check sees such a track as before, as one that no clock placed: the clock gave it only its pace. _check_coverage() is unchanged.

Verification

  • The 30x and 15x timelapses: 148 and 81 frames along the whole route, the same as without the option. Main gives 5 and 8.
  • GPX sync in this mode across 20 sample videos: only the 7 timelapses that Sync a GPX to the GPS clock of a timelapse, even one too noisy to publish #849 detects change, and each GPX now spans its video (for example 157 s becomes 5.2 s). Normal-speed videos, and noisy GPS with placeholder dates, are identical to main.
  • Unit: 922 passed, 18 skipped, 1 xfailed. Integration: 69 passed. Doctests, mypy, ruff check, ruff format --check and usort diff are clean.

With #851: no changes needed. Its rules then apply to this mode as to any track placed at the start of the video: a miss caused by --interpolation_offset_time raises, with the advice to check the offset. Merged with #851 (717bc81): no conflicts, and its tests for this mode pass.

Interval sampling stamped each frame with the start time of the video plus
its time in the video. A timelapse packs several seconds of capture into
each second of video, so its frames were stamped that many times too close
together. Geotagged from a GPX by those stamps, they all landed near the
start of the track. Geotagged from the video's own track, they moved so far
per second that the speed check could reject them: a 30x timelapse of a
drive read as over 1,000 km/h.

Interval sampling now reads the rate from the video's GPS clock, as GPX sync
does, and stamps the frames at it. The start time is mapped back from the
first GPS timestamps at the same rate. --video_duration_ratio, which used to
apply to every video, now paces only the videos without a GPS clock, so that
a ratio given for those leaves the other videos in the batch alone. Each
video whose clock overrides a given ratio says so in a warning.

The samples are then geotagged from the video's own track (the gopro, camm
and blackvue sources) by their time since the first sample, while the track
is timed in video seconds. It is now timed in GPS seconds, at the rate of its
clock. That also fixes distance samples of a timelapse, which were already
stamped with their capture times.
The previous commit timed the GPS points of a timelapse at one rate from
its first timestamp. Distance samples are stamped with the GPS time of
their video time instead, and the first timestamp of a GoPro MAX
timelapse can be about 3 s early: in one, the camera moved 6 m at 8 m/s
in the 3.9 s to the next one. On two such timelapses (30x and 15x), the
frames that geotagged were placed a median of 36 m and 5 m from where
the sampler picked them, and the last 2 and 1 frames were stamped past
the end of the track:

    The image time is 1.801 seconds beyond the GPX end point

Time the track by the timestamps, interpolated between them and
extrapolated beyond them at the clock's rate. Stamp interval samples of
a timelapse the same way, from the GPS time at video time 0, as distance
samples are.

On those two timelapses, distance samples now all geotag where they
were picked. Interval samples (0.5 s) stay where they were with
--geotag_source gopro, and with a GPX of the same track they move from
a median of 0.6 m and 0.04 m (4.4 m and 1.4 m at most) to within 1 cm.
Videos without a timelapse clock are unchanged.
--interpolation_use_gpx_start_time places the GPX from the start of the
video instead of by the video's GPS clock. It skipped reading the clock
altogether, and with it the clock's rate, so a timelapse got its GPX laid
out at 1x: a 5 s, 30x timelapse got 157 s of GPX, and distance sampling
picked 5 frames along its first 12 m instead of 148 along the 1.4 km route.

The clock is now read in that mode too, and placed at the start of the GPX,
so that only its rate is used. A video that is not a timelapse has a rate of
1, and is placed as before. The coverage check still sees such a track as
one that no clock placed: the clock gave it only its pace.
@caglarpir
caglarpir force-pushed the gpx-start-time-keeps-clock-rate branch from 9c725cd to a8c3147 Compare October 22, 2026 09:04
caglarpir added a commit to caglarpir/mapillary_tools that referenced this pull request Oct 22, 2026
The previous commit clips a GPX track whenever a clock gives its pace
along the video, so that where the video ends along it is known. Since
the GPS clock's rate is kept for --interpolation_use_gpx_start_time
(mapillary#853), that includes a track the option starts with the video: it is
clipped as any other, and a GPS logger left running past the end of the
video uploads only the part of the track that the video covers.

Say so in the docstrings, which said a clock had to place the track, and
test it among the tracks a clock paces.
@caglarpir
caglarpir merged commit cc8818f into mapillary:main Oct 22, 2026
16 checks passed
@caglarpir
caglarpir deleted the gpx-start-time-keeps-clock-rate branch October 22, 2026 11:25
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