Persist all clip snapshots to output_dir so they survive delete_after_transcode #92

Closed
opened 2026-06-05 08:12:33 +00:00 by coding-agent-marvin8 · 1 comment
coding-agent-marvin8 commented 2026-06-05 08:12:33 +00:00 (Migrated from codeberg.org)

Currently _copy_thumbnail saves only the middle snapshot alongside the MP4. When delete_after_transcode = true, every other snapshot for the clip is permanently deleted, leaving the Snapshots page with at most one image regardless of how many the camera captured.

All snapshots within the clip's time window should be copied to output_dir before the source files are removed, so the Snapshots page remains fully usable under any configuration.

Currently _copy_thumbnail saves only the middle snapshot alongside the MP4. When delete_after_transcode = true, every other snapshot for the clip is permanently deleted, leaving the Snapshots page with at most one image regardless of how many the camera captured. All snapshots within the clip's time window should be copied to output_dir before the source files are removed, so the Snapshots page remains fully usable under any configuration.
coding-agent-marvin8 commented 2026-06-05 08:13:05 +00:00 (Migrated from codeberg.org)

Findings: _copy_thumbnail in lifespan.py saves only clip.snapshots[len//2] — one file. _delete_source then removes every source JPG. The snapshots page has no way to recover them.

Plan of attack:

  1. Rename _copy_thumbnail to _persist_snapshots(clip, camera_root, output_path). For each snapshot in clip.snapshots, copy it to output_path.with_suffix('') / snapshot.relative_to(camera_root), preserving the channel/jpg/HH/MM/SS directory structure so _snapshot_time and _snapshot_label continue to work. Still copy the middle one alongside the MP4 as the .jpg preview thumbnail.
  2. Add collect_snapshots_from_output(camera, filename, output_dir) to snapshots.py that globs output_dir/camera/filename_stem/**/*.jpg. Insert it into the fallback chain in both clip route handlers (after camera-root search, before the single-thumbnail fallback so old clips still work).
  3. TDD throughout: failing tests first, then implementation.

Files: src/cang/web/lifespan.py, src/cang/web/routes/snapshots.py, tests/web/test_lifespan.py, tests/web/test_clip_snapshots.py

Findings: _copy_thumbnail in lifespan.py saves only clip.snapshots[len//2] — one file. _delete_source then removes every source JPG. The snapshots page has no way to recover them. Plan of attack: 1. Rename _copy_thumbnail to _persist_snapshots(clip, camera_root, output_path). For each snapshot in clip.snapshots, copy it to output_path.with_suffix('') / snapshot.relative_to(camera_root), preserving the channel/jpg/HH/MM/SS directory structure so _snapshot_time and _snapshot_label continue to work. Still copy the middle one alongside the MP4 as the .jpg preview thumbnail. 2. Add collect_snapshots_from_output(camera, filename, output_dir) to snapshots.py that globs output_dir/camera/filename_stem/**/*.jpg. Insert it into the fallback chain in both clip route handlers (after camera-root search, before the single-thumbnail fallback so old clips still work). 3. TDD throughout: failing tests first, then implementation. Files: src/cang/web/lifespan.py, src/cang/web/routes/snapshots.py, tests/web/test_lifespan.py, tests/web/test_clip_snapshots.py
Sign in to join this conversation.
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marvin8/cang#92
No description provided.