Replace hardcoded config and directory scan with YAML config and explicit clip list

- config.py constants -> config/config.yaml (user-editable, git-ignored)
- Questions and defaults now defined in the YAML, including per-question defaults
- ClipSelector no longer scans the data dir; reads a user-provided clips.txt instead
- Removed --daily / --time / --skip-existing-day args
- video_loader now samples frames evenly across the full clip
- pyyaml added as a dependency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 13:42:48 +02:00
parent 5f8c579247
commit 5468712a4a
11 changed files with 240 additions and 215 deletions

View File

@@ -5,10 +5,8 @@ from pathlib import Path
import cv2
from .config import Config
def load_frames(zip_path: Path, max_frames: int):
def load_frames(zip_path: Path, max_frames: int, display_max: int, fps_fallback: int):
video_bytes = zipfile.ZipFile(zip_path).read("left.mp4")
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as f:
@@ -16,14 +14,20 @@ def load_frames(zip_path: Path, max_frames: int):
tmp_path = f.name
cap = cv2.VideoCapture(tmp_path)
fps = cap.get(cv2.CAP_PROP_FPS) or Config.FPS_FALLBACK
fps = cap.get(cv2.CAP_PROP_FPS) or fps_fallback
total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
step = max(1, total // max_frames)
frames = []
i = 0
while len(frames) < max_frames:
cap.set(cv2.CAP_PROP_POS_FRAMES, i)
ok, frame = cap.read()
if not ok:
break
frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
i += step
cap.release()
os.unlink(tmp_path)
@@ -32,7 +36,7 @@ def load_frames(zip_path: Path, max_frames: int):
raise RuntimeError(f"No frames found in {zip_path}")
h, w = frames[0].shape[:2]
scale = Config.DISPLAY_MAX / max(h, w)
scale = display_max / max(h, w)
dh, dw = int(h * scale), int(w * scale)
frames = [cv2.resize(f, (dw, dh)) for f in frames]