Repository navigation
Geotag interval samples by the video's own GPS, as distance samples are - #896
Merged
caglarpir merged 2 commits intoOct 23, 2026
Merged
Conversation
One malformed RMC or GGA sentence failed the whole file, as not a valid NMEA file, and since NMEA files are read from any talker, so did one from a talker that v0.14.7 did not read. A log of 222 sentences with one more, a $GLGGA sentence whose checksum does not match, failed all 113 images geotagged from it, where v0.14.7 geotagged 106 of them, the 7 others being duplicates of the previous image. A video geotagged from such a log failed too. v0.14.7 crashed on a malformed $GPGGA sentence. A sentence that does not parse, whose checksum does not match, or with a field a fix is read from that does not parse, is now skipped, and one warning per file says how many were skipped and quotes the first, with its line number and what is wrong with it. pynmea2 leaves a field it cannot parse a string: a malformed time failed the file, and a malformed altitude crashed process with a traceback, for images and videos alike. Void sentences and sentences without a fix are skipped as before, without a warning. A file of which no fix can be read and that has malformed sentences still fails as not a valid NMEA file. On that log the 106 images get the same positions, times, directions and altitudes as with v0.14.7 and as from the log without the bad sentence, and the 7 others are duplicates as before.
`video_process VIDEO OUT --video_sample_interval N --video_sample_distance -1` failed every sample with "Unable to extract GPS Longitude or GPS Latitude from the image", and so did sample_video followed by process. It did so on v0.13 and v0.14 too. Distance sampling writes the position of each sample into its EXIF, where the default geotag sources read it; interval sampling wrote only the capture time. Only the legacy gopro, camm and blackvue sources geotagged interval samples, by reading the video again in the geotagging stage. Locate each interval sample along the video's own GPS track at its video time, and write its position, altitude, direction and the make and model of the camera into its EXIF, as distance sampling does, reading the track by the same sources: the video's own GPS unless --geotag_source or --video_geotag_source says otherwise. The capture times are stamped by the video's GPS clock as before. A sample before the track starts or after it ends gets no position. A video whose GPS cannot be read, as it has none or it is rejected as noise, is named in a warning, and its samples fail as before. With a GPX or NMEA source, nothing changes: the geotagging stage places the samples along that track by their capture times, which for a video without a GPS clock come from its creation time, not from where GPX sync would place the track. An altitude above 4293 m, which a GoPro with poor GPS can report, failed the sample: written to the 1e-6 m, the numerator of its EXIF rational did not fit in 32 bits. Such altitudes are written to the precision that fits. That also fixes distance samples, which failed the same way. On a GoPro HERO7, a GoPro MAX (a normal video and a timelapse), a PANOX V2, a LabPano Pilot One, a BlackVue 900S, a Viofo A129 and a Ricoh Theta X, the samples now lie within 1 cm of the video's track at their video time, stamped at even steps of the clock (11.426 s for 10 s of the LabPano). They get the positions, capture times, altitudes and cameras that the legacy sources give them, within 1 cm on the LabPano, and sample_video followed by process describes them as video_process does. --geotag_source exif and native, which read the EXIF, now geotag them too. With a legacy source the descriptions do not change, but for the file sizes of the samples, which now hold their positions; nor do they with a GPX (also with --interpolation_use_gpx_start_time, and with native after it), with --video_geotag_source gpx, for distance sampling, for a video without GPS and for a GoPro MAX 2 whose GPS is noise.
caglarpir
force-pushed
the
geotag-interval-samples-by-default
branch
from
October 23, 2026 13:04
f7adc8e to
cc717e3
Compare
caglarpir
added a commit
that referenced
this pull request
Oct 24, 2026
…ource Interval sampling with --video_geotag_source gpx or nmea geotagged none of its samples: each failed with "Unable to extract GPS Longitude or GPS Latitude from the image", and the command exited 6, on a GoPro MAX timelapse with its GPX and on a Sony video with the GPX or NMEA log of its GPS. Such a source geotags videos only, so the geotagging stage reads the samples' own positions, and interval sampling wrote positions only from the video's own GPS. Distance sampling with the same options worked, and so did interval sampling with --geotag_source gpx, which geotags the samples themselves. The message of #896, which located interval samples along the video's own GPS, said that they were placed along a GPX too; they were not. Locate each interval sample along the GPX or NMEA track as GPX sync placed it on the video, at the sample's video time, and write its position into the sample, as distance sampling does. Stamp it with the time of the track there, as distance sampling stamps the samples of a track from a file: for a video with a GPS clock, and without --interpolation_offset_time, that is the time it was stamped with before. With --interpolation_use_gpx_start_time, the track starts at the first sample, which ffmpeg cuts at time 0, as the samples of a video whose GPS was rejected as noise are stamped from it, not at the first frame, where GPX sync starts it for distance sampling. The samples outside the track, or in one of its gaps of more than an hour, are left out with a warning, as other samples outside their track are, unless a legacy source or exiftool_xml, which geotag samples by the GPS of their video, may geotag them instead. Distance sampling with such a source interpolated the track across its gaps: the frames in a gap of hours got positions between the fixes either side of it, which say nothing of where the camera was, and the geotagging stage read them from the frames. Since #874 a time in such a gap is outside the track, and the samples of a file of --geotag_source in it fail geotagging. Leave those frames out too, with one warning per video that names the gaps, so that distance and interval samples agree. The limit is in GPS seconds, as in the geotagging stage, so it spans less video in a timelapse. Distance sampling with a file of --geotag_source, which the geotagging stage geotags the frames by, or with a legacy source or exiftool_xml, is unchanged. On the GoPro MAX timelapse sampled every 0.5 s, the Sony video sampled every 20 s with its GPX and with its NMEA log, and a noisy GoPro MAX 2 timelapse with its GPX started with the video, every sample is geotagged, within 1.4 cm of the track at its capture time, and the commands exit 0 (the last sample of the GoPro MAX 2 timelapse, past the GPX, is left out). --geotag_source gpx and nmea, the video's own GPS and the legacy sources give the same descriptions as before. Checked distance sampling with tracks made to have gaps: - A GoPro MAX video with a GPX missing 70 s of fixes inside it, with MAPILLARY_TOOLS_MAX_GPX_GAP_SECONDS at 60: the 2098 frames in the gap are left out, and at 5 m 55 samples are written instead of 70, none in the gap, the 24 before it as before. The same with --interpolation_offset_time 2 and with --interpolation_use_gpx_start_time. At the default limit, nothing changes. - The same video with a GPX that resumes 99 s into it, 2 hours after its previous fix: the first 99 s are left out (46 samples instead of 59), where the track starts after the gap; with the GPX ending a minute later too, the 14 samples of that minute are written. Started with the video, the GPX covers only its first frame, which alone is written, instead of 45 samples placed along the gap. - A Sony video with a GPX and with an NMEA log missing 2 minutes of fixes, at a limit of 60 s: 257 samples at 10 m instead of 316, none in the gap, the first 114 as before. - A GoPro MAX timelapse with 41 s of GPS time missing, 1.4 s of video: at a limit of 30 s, its 40 frames are left out; at 60 s, nothing changes. - With these tracks as --geotag_source gpx or nmea, with the legacy gopro source next to --video_geotag_source gpx, and with interval sampling, the descriptions are the same as before. With the GPX and NMEA tracks of sample videos from a dozen cameras, among them GPX logs of several trips with gaps of more than an hour outside the videos (111 runs of video_process: --video_geotag_source gpx and nmea, with --interpolation_use_gpx_start_time or an offset, interval sampling, and --geotag_source gpx and nmea), and plain video_process by distance and by interval on five cameras, the descriptions are the same as before.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #895; review the last commit.
video_process VIDEO OUT --video_sample_interval N --video_sample_distance -1failed every sample with "Unable to extractGPS Longitude or GPS Latitude from the image", and so did sample_video
followed by process. It did so on v0.13 and v0.14 too. Distance sampling
writes the position of each sample into its EXIF, where the default
geotag sources read it; interval sampling wrote only the capture time.
Only the legacy gopro, camm and blackvue sources geotagged interval
samples, by reading the video again in the geotagging stage.
Locate each interval sample along the video's own GPS track at its video
time, and write its position, altitude, direction and the make and model
of the camera into its EXIF, as distance sampling does, reading the
track by the same sources: the video's own GPS unless --geotag_source or
--video_geotag_source says otherwise. The capture times are stamped by
the video's GPS clock as before. A sample before the track starts or
after it ends gets no position. A video whose GPS cannot be read, as it
has none or it is rejected as noise, is named in a warning, and its
samples fail as before. With a GPX or NMEA source, nothing changes: the
geotagging stage places the samples along that track by their capture
times, which for a video without a GPS clock come from its creation
time, not from where GPX sync would place the track.
An altitude above 4293 m, which a GoPro with poor GPS can report, failed
the sample: written to the 1e-6 m, the numerator of its EXIF rational
did not fit in 32 bits. Such altitudes are written to the precision that
fits. That also fixes distance samples, which failed the same way.
On a GoPro HERO7, a GoPro MAX (a normal video and a timelapse), a PANOX
V2, a LabPano Pilot One, a BlackVue 900S, a Viofo A129 and a Ricoh Theta
X, the samples now lie within 1 cm of the video's track at their video
time, stamped at even steps of the clock (11.426 s for 10 s of the
LabPano). They get the positions, capture times, altitudes and cameras
that the legacy sources give them, within 1 cm on the LabPano, and
sample_video followed by process describes them as video_process does.
--geotag_source exif and native, which read the EXIF, now geotag them
too. With a legacy source the descriptions do not change, but for the
file sizes of the samples, which now hold their positions; nor do they
with a GPX (also with --interpolation_use_gpx_start_time, and with
native after it), with --video_geotag_source gpx, for distance sampling,
for a video without GPS and for a GoPro MAX 2 whose GPS is noise.
Unit and integration tests, doctests,
mypy --python-version 3.9,ruff check,ruff format --checkandusort diffare clean.