diff --git a/movmaker.py b/movmaker.py index 152365b..6e843ea 100755 --- a/movmaker.py +++ b/movmaker.py @@ -62,7 +62,16 @@ CLIP_AUDIO_SIDECHAIN_ATTACK = 5.0 CLIP_AUDIO_SIDECHAIN_RELEASE = 250.0 -def tool_path(local_path: Path, fallback: str) -> str: +ORDER_FILENAME = "order.json" + +def load_order_json(directory: Path) -> list[str] | None: + order_file = directory / ORDER_FILENAME + if order_file.exists(): + try: + return json.loads(order_file.read_text(encoding="utf-8")) + except Exception as e: + console(f"Error reading {ORDER_FILENAME}: {e}") + return None """Return the preferred executable path for ffmpeg/ffprobe style tools. Args: @@ -623,10 +632,12 @@ def scan_input(input_dir: Path, image_duration: float) -> tuple[list[MediaItem], audio: list[Path] = [] data_file: Path | None = None - for path in sorted(input_dir.iterdir(), key=natural_key): + for path in input_dir.iterdir(): if not path.is_file(): continue ext = path.suffix.lower() + if path.name.lower() == ORDER_FILENAME: + continue if path.name.lower() in DATA_NAMES: data_file = path elif ext in IMAGE_EXTS: @@ -639,7 +650,20 @@ def scan_input(input_dir: Path, image_duration: float) -> tuple[list[MediaItem], if not media: raise SystemExit(f"No images or videos found in {input_dir}") - media.sort(key=lambda item: (media_date(item.path), natural_key(item.path))) + order = load_order_json(input_dir) + if order: + # Sort based on order.json, append missing files at the end + media_map = {item.path.name: item for item in media} + sorted_media = [] + for name in order: + if name in media_map: + sorted_media.append(media_map.pop(name)) + # Add remaining + sorted_media.extend(media_map.values()) + media = sorted_media + else: + media.sort(key=lambda item: (media_date(item.path), natural_key(item.path))) + return media, audio, parse_data_file(data_file)