Generalizes the tool beyond QuickTime video containers, based on what
we found fixing a Synology Photos mass-wrong-date bug: the indexer
only reads photo-EXIF fields and never video container metadata, even
though most cameras embed a real timestamp there.
- .avi via exiftool's RIFF DateTimeOriginal (local time, no offset)
- .jpg/.jpeg/.png/.tif/.tiff/.heic/.heif via exiftool's EXIF DateTimeOriginal
- exiftool fallback for .mp4/.mov when ffprobe finds neither QuickTime tag
- placeholder "clock never set" timestamps (e.g. 0000:00:00 00:00:00)
are treated as no metadata, not a real date
- --dir for recursive directory batch mode
- interactive y/N confirmation by default; --yes for unattended runs
Verified against real files: a 2007 camcorder AVI, a synthetic UTC-tagged
MP4, and an EXIF-tagged JPEG all round-trip correctly, including DST
handling.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Extracted the mtime-stamping logic added to concat_live_clips.py into
its own dependency-free script (just needs ffprobe), so it can be run
against any video file -- not just Live Photo clips -- to fix a
mismatched filesystem mtime for tools like Synology Photos that sort
videos by mtime instead of parsing embedded metadata.
Some tools (Synology Photos, for videos) key off filesystem mtime
rather than parsing QuickTime metadata for the capture date, so an
otherwise-correct output file would sort/date wrong there. Stamp the
output's mtime from the same clip whose metadata got embedded
(--metadata-from) after encoding.
When a clip boundary's audio doesn't match, print a full table of every
junction (capture-time gap, confidence, verdict) plus the input clips
grouped into continuous runs, each formatted as a ready-to-paste clip
list -- so a discontinuous batch can be immediately re-run on just the
subset that's actually one sequence, without manually diffing timestamps.
Distinguishes a genuine audio mismatch at a clip boundary (evidence
the inputs aren't really a continuous sequence) from a boundary that's
simply too quiet to judge either way, using an RMS floor alongside the
existing cross-correlation confidence score. A confident mismatch now
aborts before encoding instead of silently splicing unrelated clips
together; --allow-discontinuous opts back into the old behavior.
Detects genuine audio/video overlap between consecutive Live Photo
clips via audio cross-correlation, trims the duplicated footage, and
re-encodes a seamless, metadata-preserving output.