Enhance Avisynth video workflow and metadata tools

This commit is contained in:
ajp_anton
2026-07-30 03:20:19 +00:00
parent d60ce51b14
commit 100cad1cb5
26 changed files with 2350 additions and 1161 deletions
+2 -37
View File
@@ -24,7 +24,7 @@ from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Iterable
from tools.console import pause_if_interactive, prompt_input
from tools.console import pause_if_interactive, prompt_input, prompt_yes_no as ask_yes_no
from tools.exiftool import require_exiftool, run_exiftool_json, run_exiftool_write
from tools.filenames import (
format_filename_stem,
@@ -40,6 +40,7 @@ from tools.filesystem import (
remove_empty_dirs,
unique_existing_target,
)
from tools.timezones import parse_timezone_offset, timezone_to_string
IMAGE_EXTS = {".jpg", ".jpeg", ".heic", ".arw"}
@@ -96,7 +97,6 @@ DATETIME_RE = re.compile(
TIME_ONLY_RE = re.compile(
r"^(?P<h>\d{1,2})(?::?(?P<m>\d{2}))(?::?(?P<s>\d{2}))?$"
)
TZ_RE = re.compile(r"^(?P<sign>[+-])(?P<h>\d{1,2})(?::?(?P<m>\d{2}))?$")
OFFSET_RE = re.compile(r"^([+-])(?:(\d+):)?(\d{1,2})(?::(\d{2}))?$")
TOKEN_SHIFT_RE = re.compile(r"(\d+|[a-zA-Z]+)")
ORDERED_TIMESTAMP_STEM_RE = re.compile(r"^(?P<timestamp>\d{8}_\d{6})-[1-9]\d*$")
@@ -195,19 +195,6 @@ class UserChoices:
apply_filename_timestamps: bool
def ask_yes_no(prompt: str, default: bool) -> bool:
suffix = "Y/n" if default else "y/N"
while True:
answer = prompt_input(f"{prompt} ({suffix}) ").strip().lower()
if not answer:
return default
if answer in {"y", "yes"}:
return True
if answer in {"n", "no"}:
return False
print("Please answer y or n.")
def ask_group_min_size() -> int:
while True:
answer = prompt_input(
@@ -225,28 +212,6 @@ def ask_group_min_size() -> int:
print("Please answer y, n, or an integer minimum group size.")
def parse_timezone_offset(value: str) -> timezone:
match = TZ_RE.match(value.strip())
if not match:
raise ValueError("timezone must look like +09:00 or -05:30")
sign = 1 if match.group("sign") == "+" else -1
hours = int(match.group("h"))
minutes = int(match.group("m") or "0")
if minutes not in {0, 15, 30, 45}:
raise ValueError("timezone minutes must be 00, 15, 30, or 45")
return timezone(sign * timedelta(hours=hours, minutes=minutes))
def timezone_to_string(tz: timezone) -> str:
offset = tz.utcoffset(None)
if offset is None:
return "+00:00"
total_minutes = int(offset.total_seconds() // 60)
sign = "+" if total_minutes >= 0 else "-"
total_minutes = abs(total_minutes)
return f"{sign}{total_minutes // 60:02d}:{total_minutes % 60:02d}"
def parse_datetime(value: str, default_date: datetime | None = None) -> datetime:
text = value.strip()
match = DATETIME_RE.search(text)