Skip to content

Implement "reverse" import by starting with individual images - #3

Open
qwhelan wants to merge 8 commits into
tjhorner:mainfrom
qwhelan:reverse_import
Open

Implement "reverse" import by starting with individual images#3
qwhelan wants to merge 8 commits into
tjhorner:mainfrom
qwhelan:reverse_import

Conversation

@qwhelan

@qwhelan qwhelan commented Dec 28, 2025

Copy link
Copy Markdown
Contributor

Not yet ready to merge, but more-or-less working locally version of #2 so wanted to get some feedback on the structure.

Basic approach is:

  • Start with a collection of GoPro Max images, assuming that they're named in a format like GOPRO_MAX.20240629.104937.GSAT3081.JPG for the moment

    • GS is a GoPro photo identifier, and AT is the sequence id (starting at AA when memory card is wiped, then AB, etc). 3081 is a photo id that counts since last memory card wipe but is also sequential within a sequence (but might wrap around at 10,000)
  • Create new queue for "reverse" import and process the photos with exiftool to get the embedded GPS/time data

    • At present, not sure if heading is embedded. Just setting to 0 for now but should be able to estimate from the track if not available in EXIF
  • On photo import, generate geometry and use the date + sequence id as a track identifier

    • Current approach is potentially O(n^2 log(n)) so needs some optimization (eg, handle case where photos are imported in-order and can just append)
    • Skipping simplification currently
  • Frontend seems to work as-is

Screenshot from 2025-12-28 16-24-23 Screenshot from 2025-12-28 16-25-05

@qwhelan

qwhelan commented Jan 9, 2026

Copy link
Copy Markdown
Contributor Author

A couple updates here:

  • Skip GoPro Max image files that are missing EXIF GPS data (guessing I didn't have a GPS fix when starting the sequence and it just never recovered)
  • Estimate heading from current coordinates and prior one

Comment thread backend/src/track-watcher.service.ts Outdated

this.logger.log(`New file detected; import queued for ${filePath}`)
this.logger.log(`New file detected; considering ${filePath}`)
if (filePath.endsWith(".360") || filePath.endsWith('.JPG')) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably want to make this case-insensitive

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +132 to +137
const { stdout, stderr } = await runCmd("exiftool", [
"-location:all",
"-time:all",
"-n",
filePath,
])

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably use something like exiftool-vendored so we don't have to do all the brittle parsing stuff below

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Needed to run npm install --workplaces false in backend/ to get a clean package-lock.json here

Comment thread backend/src/tracks/reverse-import/reverse.controller.ts Outdated
Comment thread backend/src/tracks/queues.constants.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants