Skip to content

Feature: GPS Geotagging from GPX/KML Track Files #1

Description

@jalogisch

Summary

Add a new module (pg-geotag) that automatically sets GPS coordinates on photos by matching image timestamps against a GPX or KML track file. This enables photographers to geotag photos from cameras without built-in GPS by syncing with a GPS track recorded on a phone or dedicated GPS device.

Use Cases

  • Geotagging photos from a professional camera using a GPS track from a smartphone
  • Adding location data to action camera footage synced with a Garmin/Wahoo device
  • Batch geotagging archived photos from a recorded route

Proposed Implementation

1. CLI Script: bin/pg-geotag

pg-geotag <files...> --track <gpx/kml file> [options]

Arguments:

  • <files...> - One or more files or directories to process

Options:

  • -t, --track <file> - GPX or KML track file (required)
  • --tolerance <seconds> - Maximum time offset for matching (default: 30)
  • --offset <seconds> - Manual time correction (camera vs GPS clock drift)
  • --interpolate - Interpolate position between track points (default: on)
  • --no-overwrite - Skip photos that already have GPS data
  • -n, --dry-run - Show what would be done without changes
  • -v, --verbose - Show detailed output

Examples:

# Geotag photos from a hike using a GPX from a phone
pg-geotag ./photos --track route.gpx

# Geotag with larger tolerance and camera offset correction
pg-geotag ./photos --track track.gpx --tolerance 60 --offset -15

# Preview without making changes
pg-geotag ./photos --track route.kml --dry-run

2. Web Module: web/modules/geotag/

module.yaml:

id: geotag
name: Geotag from Track
description: Set GPS coordinates from GPX/KML track file
icon: map-pin
order: 3

parameters:
  - id: directory
    type: positional
    label: Directory
    placeholder: ~/Pictures/PhotoLibrary/2026-01-24
    required: true
    inherit_from: target_directory
    help: "Auto-filled from previous import step if available."
    
  - id: track_file
    type: path
    label: Track File (GPX/KML)
    placeholder: ~/Downloads/route.gpx
    required: true
    cli_flag: --track
    
  - id: tolerance
    type: number
    label: Time Tolerance (seconds)
    default: 30
    cli_flag: --tolerance
    help: "Maximum time difference between photo and track point."
    
  - id: offset
    type: number
    label: Time Offset (seconds)
    default: 0
    cli_flag: --offset
    help: "Correct camera/GPS clock difference. Positive = camera ahead."
    
  - id: interpolate
    type: boolean
    label: Interpolate positions
    default: true
    cli_flag: --interpolate
    
  - id: skip_existing
    type: boolean
    label: Skip photos with GPS
    default: true
    cli_flag: --no-overwrite

outputs:
  - id: geotagged_count
    type: number
    description: Number of photos geotagged
  - id: skipped_count
    type: number
    description: Number of photos skipped (no match or already tagged)

3. Python Library: lib/gpx_utils.py

New utility for parsing GPS track files:

class GPXParser:
    """Parse GPX/KML files and match timestamps to coordinates."""
    
    def parse(self, filepath: Path) -> list[TrackPoint]
    def find_position(self, timestamp: datetime, tolerance: int = 30) -> Optional[Coordinates]
    def interpolate(self, timestamp: datetime, before: TrackPoint, after: TrackPoint) -> Coordinates

Technical Details

Track File Parsing:

  • GPX: Parse <trkpt> elements with lat, lon, and <time> attributes
  • KML: Parse <gx:Track> or <gx:coord> elements with associated timestamps
  • Use Python's xml.etree.ElementTree (no external dependencies)

Time Matching Algorithm:

  1. Read image timestamp from EXIF (DateTimeOriginal)
  2. Apply manual offset correction if specified
  3. Find track points within tolerance window
  4. If interpolate=true and two points bracket the timestamp, calculate linear interpolation
  5. If no match within tolerance, skip the image

GPS Coordinate Writing:

  • Reuse existing ExifTool.write() with gps parameter
  • Write standard GPS EXIF tags: GPSLatitude, GPSLongitude, GPSLatitudeRef, GPSLongitudeRef

Acceptance Criteria

  • pg-geotag script works with GPX files
  • pg-geotag script works with KML files
  • Web module integrates with workflow planner
  • Time tolerance is configurable (default: 30 seconds)
  • Manual time offset correction works
  • Position interpolation between track points
  • Dry-run mode shows preview without changes
  • Skip photos that already have GPS data (optional)
  • Progress feedback for large batches

Dependencies

  • exiftool (existing requirement)
  • Python 3.9+ (existing requirement)
  • No new external dependencies (use stdlib xml.etree.ElementTree)

Related

  • Extends existing pg-exif functionality
  • Integrates with workflow planner as new step type

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions