Add camera-raw format support (.arw/.cr2/.dng/.raw)

Verified via exiftool against real Sony ARW, Canon CR2, and Pixel DNG
files pulled from are-nas -- same EXIF DateTimeOriginal/CreateDate
tags as JPEG, no new codepath needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 16:11:06 -04:00
co-authored by Claude Sonnet 5
parent 6fd83d2b1c
commit c077c535b3
2 changed files with 11 additions and 6 deletions
+2 -1
View File
@@ -148,7 +148,8 @@ Handles `.mov`/`.mp4`/`.m4v` (ffprobe container tags, preferring Apple's
`creation_time`, usually UTC; falls back to exiftool's QuickTime atoms if `creation_time`, usually UTC; falls back to exiftool's QuickTime atoms if
neither ffprobe tag is present), `.avi` (exiftool's RIFF `DateTimeOriginal`), neither ffprobe tag is present), `.avi` (exiftool's RIFF `DateTimeOriginal`),
and photo formats — `.jpg`/`.jpeg`/`.png`/`.tif`/`.tiff`/`.heic`/`.heif` and photo formats — `.jpg`/`.jpeg`/`.png`/`.tif`/`.tiff`/`.heic`/`.heif`
(exiftool's EXIF `DateTimeOriginal`). Values with no timezone offset are plus camera-raw `.arw`/`.cr2`/`.dng`/`.raw` (all via exiftool's EXIF
`DateTimeOriginal` — raw formats carry standard EXIF too). Values with no timezone offset are
interpreted as this machine's local time (DST-aware) — run it somewhere interpreted as this machine's local time (DST-aware) — run it somewhere
with the same system timezone the footage was actually shot in. Placeholder with the same system timezone the footage was actually shot in. Placeholder
"clock never set" timestamps some cameras write (e.g. literal "clock never set" timestamps some cameras write (e.g. literal
+9 -5
View File
@@ -19,9 +19,10 @@ Handles, in priority order per format:
.avi -- exiftool's RIFF DateTimeOriginal (IDIT chunk). This is .avi -- exiftool's RIFF DateTimeOriginal (IDIT chunk). This is
the camera's own local wall-clock time with no the camera's own local wall-clock time with no
timezone info, unlike the QuickTime tags above. timezone info, unlike the QuickTime tags above.
.jpg/.jpeg/.png/.tif/.tiff/.heic/.heif .jpg/.jpeg/.png/.tif/.tiff/.heic/.heif/.arw/.cr2/.dng/.raw
-- exiftool's EXIF DateTimeOriginal. Also local wall-clock -- exiftool's EXIF DateTimeOriginal (the .arw/.cr2/.dng/
time with no timezone info. .raw camera-raw formats carry standard EXIF too).
Also local wall-clock time with no timezone info.
Values with no timezone offset (AVI, EXIF, and ffprobe's bare creation_time Values with no timezone offset (AVI, EXIF, and ffprobe's bare creation_time
fallback path is UTC-aware so it's unaffected) are interpreted using this fallback path is UTC-aware so it's unaffected) are interpreted using this
@@ -60,7 +61,10 @@ QUICKTIME_TAG_PRIORITY = ["com.apple.quicktime.creationdate", "creation_time"]
QUICKTIME_EXTS = {".mov", ".mp4", ".m4v"} QUICKTIME_EXTS = {".mov", ".mp4", ".m4v"}
AVI_EXTS = {".avi"} AVI_EXTS = {".avi"}
VIDEO_EXTS = QUICKTIME_EXTS | AVI_EXTS VIDEO_EXTS = QUICKTIME_EXTS | AVI_EXTS
EXIF_PHOTO_EXTS = {".jpg", ".jpeg", ".png", ".tif", ".tiff", ".heic", ".heif"} EXIF_PHOTO_EXTS = {
".jpg", ".jpeg", ".png", ".tif", ".tiff", ".heic", ".heif",
".arw", ".cr2", ".dng", ".raw", # camera raw formats -- standard EXIF via exiftool
}
ALL_SUPPORTED_EXTS = VIDEO_EXTS | EXIF_PHOTO_EXTS ALL_SUPPORTED_EXTS = VIDEO_EXTS | EXIF_PHOTO_EXTS
# Synology (and other NAS/sync tool) internal housekeeping directories that # Synology (and other NAS/sync tool) internal housekeeping directories that
@@ -190,7 +194,7 @@ def main():
parser.add_argument("files", nargs="*", type=Path, help="Media files to fix") parser.add_argument("files", nargs="*", type=Path, help="Media files to fix")
parser.add_argument("--dir", type=Path, help="Recursively scan this directory for supported files instead of (or in addition to) explicit FILES") parser.add_argument("--dir", type=Path, help="Recursively scan this directory for supported files instead of (or in addition to) explicit FILES")
type_group = parser.add_mutually_exclusive_group() type_group = parser.add_mutually_exclusive_group()
type_group.add_argument("--only-photo", action="store_true", help="Only consider photo formats (jpg/jpeg/png/tif/tiff/heic/heif)") type_group.add_argument("--only-photo", action="store_true", help="Only consider photo formats (jpg/jpeg/png/tif/tiff/heic/heif/arw/cr2/dng/raw)")
type_group.add_argument("--only-video", action="store_true", help="Only consider video formats (mov/mp4/m4v/avi)") type_group.add_argument("--only-video", action="store_true", help="Only consider video formats (mov/mp4/m4v/avi)")
parser.add_argument("--dry-run", action="store_true", help="Show what would change without modifying anything or prompting") parser.add_argument("--dry-run", action="store_true", help="Show what would change without modifying anything or prompting")
parser.add_argument("--yes", "-y", "--unattended", dest="yes", action="store_true", help="Apply changes without an interactive confirmation prompt") parser.add_argument("--yes", "-y", "--unattended", dest="yes", action="store_true", help="Apply changes without an interactive confirmation prompt")