Media correlation
MTL Explorer places indexed photos and videos in activity context without changing their source metadata. Track Details includes a Media tab with a persisted timeline, position provenance, camera-clock correction, manual location assignment, and the shared media viewer.
On this page
Position evidence and resolution
Each source is stored separately so later information does not overwrite earlier evidence:
media_file.exif_gps_locationkeeps the embedded EXIF point unchanged.media_track_correlationkeeps every eligible activity correlation and its interpolated route point.media_manual_locationkeeps the point and note entered by the user.media_resolved_locationis the small indexed projection used by map reads.
The resolved position uses this precedence:
USER_ASSIGNEDEXIF_EMBEDDEDTRACK_INTERPOLATED
Timeline and trend-item responses carry positionOrigin, shown as Set by you,
Photo GPS, or Estimated. Clearing a user assignment exposes the
preserved EXIF or track-derived position again. A track-derived position never
creates EXIF GPS metadata. If provenance is unavailable, the client shows
Position unknown instead of assuming embedded GPS.
Capture time and activity matching
EXIF GPS time is authoritative when present. Otherwise, EXIF
DateTimeOriginal is used with an optional saved camera offset from -24 to
+24 hours. Corrections are stored separately in media_time_correction and
never modify source timestamps.
Only successful, unique, imported activities with supported recorded timing
and timestamped canonical points are eligible. Estimated or unsupported timing
cannot supply time-based matches. Map/statistics use decisions do not erase an
otherwise supported correlation; selection still controls map and trend scope.
All overlapping activity correlations are retained. The selected
match is deterministic: a photo with GPS prefers the nearest route; remaining
ties use interval midpoint, duration, then activity id. The response includes
ambiguousMatch and alternativeMatchCount when more than one activity was
eligible. Map-point responses contain coordinates only; the ordinary media-details
response does not carry this provenance. A viewer needs the collection item's
provenance to label its position.
Track position is interpolated between the canonical points around the adjusted capture time. The stored correlation includes route position, distance, duration, nearest point index and time delta, algorithm version, activity version, applied offset, and calculation time.
Incremental correlation job
Correlation is asynchronous and durable. Media metadata changes, saved time or
manual-location changes, activity changes, and authoritative
RAW_OUTLIER_CLEANED track-data changes add small work items. Track work first
expands to media in the activity's old or new indexed time window. Media work is
then processed in bounded batches. A failed batch is retried one item at a
time. Deterministic failures are deferred with an error summary so later work
continues instead of repeatedly blocking the queue.
This avoids comparing every photo with every activity. Replacing or deleting an activity also requeues its previously correlated photos so they can fall back to another match, EXIF, or no resolved position. An algorithm-version marker allows stale rows to be recalculated after the matching rules change.
Reads keep the last completed result while recalculation is pending. Admin job status reports the remaining correlation work.
Normal read paths do no interpolation:
- map bounds query the GiST-indexed
media_resolved_locationprojection; - an activity timeline queries a bounded page through the
(track_id, adjusted_capture_time, media_id)selected-correlation index; - the original media content remains loaded only when a thumbnail or viewer requests it.
API
The OpenAPI schema is the source of truth and the frontend uses its generated TypeScript client.
GET /mtl/api/media/by-track/{trackId}returns a page envelope whencameraOffsetSeconds=0; a non-zero offset returns the corresponding unsaved preview page.pageis zero-based,pageSizedefaults to 100 and is limited to 200, and the response includes total item and page counts.POST /mtl/api/media/trendsreturns grouped photo/video counts within the matching tracks' continuous time range. Track related also requires a selected correlation to a matching track. See selection semantics.POST /mtl/api/media/trends/itemsreturns a stable newest-first page for one trend period and optional photo/video kind filter. The UI requests 60 items per page.PUT /mtl/api/media/time-correctionssaves or clears reversible corrections for a bounded media-id set and returns204 No Content.PUT /mtl/api/media/{mediaId}/manual-locationsaves a user assignment.DELETE /mtl/api/media/{mediaId}/manual-locationclears it.
A missing activity or media item returns 404. Invalid coordinates, offsets,
or request sizes return 400.
See the media guide for browsing and corrections.