diff --git a/movmaker.py b/movmaker.py index 6e843ea..e535953 100755 --- a/movmaker.py +++ b/movmaker.py @@ -504,31 +504,33 @@ def media_embedded_date(path: Path) -> datetime | None: return dt except Exception: pass - return ffprobe_creation_date(path) + return None + if ext in VIDEO_EXTS: + return ffprobe_creation_date(path) + return None def parse_date_from_filename(path: Path) -> datetime | None: - # Look for 8 digits (YYYYMMDD) followed by optional separator and 6 digits (HHMMSS) - m = re.search(r'(\d{8})[_-]?(\d{6})?', path.stem) - if m: - try: - date_part = m.group(1) - time_part = m.group(2) if m.group(2) else '000000' - full_ts = date_part + time_part - return datetime.strptime(full_ts, '%Y%m%d%H%M%S') - except ValueError: - return None - return None + # Match exactly YYYYMMDD[_-]HHMMSS as a standalone numeric chunk. + m = re.search(r'(?:^|[^0-9])(\d{8})[_-]?(\d{6})(?:[^0-9]|$)', path.name) + if not m: + return None + full_ts = f"{m.group(1)}{m.group(2)}" + try: + return datetime.strptime(full_ts, "%Y%m%d%H%M%S") + except ValueError: + return None + def media_date(path: Path) -> datetime: - # 1. Try embedded metadata + # 1) Embedded metadata (EXIF/ffprobe) dt = media_embedded_date(path) - - # 2. Try filename parsing for videos - if dt is None and path.suffix.lower() in VIDEO_EXTS: + + # 2) Filename parsing + if dt is None: dt = parse_date_from_filename(path) - - # 3. Fallback to mtime + + # 3) Filesystem datetime fallback if dt is None: dt = datetime.fromtimestamp(path.stat().st_mtime) @@ -616,13 +618,6 @@ def default_output_path(first_media: Path, data: MovieData, out_dir: Path) -> Pa return out_dir / f"{date}_{title}.mp4" -def natural_key(path: Path) -> list[object]: - # Simple natural-ish sort: IMG_2 before IMG_10. - import re - parts = re.split(r"(\d+)", path.name.lower()) - return [int(p) if p.isdigit() else p for p in parts] - - def scan_input(input_dir: Path, image_duration: float) -> tuple[list[MediaItem], list[Path], MovieData]: """Detect media/audio/data files inside the input directory and build metadata.""" if not input_dir.is_dir(): @@ -662,7 +657,9 @@ def scan_input(input_dir: Path, image_duration: float) -> tuple[list[MediaItem], sorted_media.extend(media_map.values()) media = sorted_media else: - media.sort(key=lambda item: (media_date(item.path), natural_key(item.path))) + # Datetime-only ordering (no filename-order fallback). + # Python sort is stable, so equal datetimes keep discovery order. + media.sort(key=lambda item: media_date(item.path)) return media, audio, parse_data_file(data_file)