2026-05-20 13:26:03 +02:00
|
|
|
import os
|
|
|
|
|
import tempfile
|
|
|
|
|
import zipfile
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
import cv2
|
|
|
|
|
|
|
|
|
|
|
2026-05-20 13:42:48 +02:00
|
|
|
def load_frames(zip_path: Path, max_frames: int, display_max: int, fps_fallback: int):
|
2026-05-20 13:26:03 +02:00
|
|
|
video_bytes = zipfile.ZipFile(zip_path).read("left.mp4")
|
|
|
|
|
|
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as f:
|
|
|
|
|
f.write(video_bytes)
|
|
|
|
|
tmp_path = f.name
|
|
|
|
|
|
|
|
|
|
cap = cv2.VideoCapture(tmp_path)
|
2026-05-20 13:42:48 +02:00
|
|
|
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)
|
2026-05-20 13:26:03 +02:00
|
|
|
|
|
|
|
|
frames = []
|
2026-05-20 13:42:48 +02:00
|
|
|
i = 0
|
2026-05-20 13:26:03 +02:00
|
|
|
while len(frames) < max_frames:
|
2026-05-20 13:42:48 +02:00
|
|
|
cap.set(cv2.CAP_PROP_POS_FRAMES, i)
|
2026-05-20 13:26:03 +02:00
|
|
|
ok, frame = cap.read()
|
|
|
|
|
if not ok:
|
|
|
|
|
break
|
|
|
|
|
frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
|
2026-05-20 13:42:48 +02:00
|
|
|
i += step
|
2026-05-20 13:26:03 +02:00
|
|
|
|
|
|
|
|
cap.release()
|
|
|
|
|
os.unlink(tmp_path)
|
|
|
|
|
|
|
|
|
|
if not frames:
|
|
|
|
|
raise RuntimeError(f"No frames found in {zip_path}")
|
|
|
|
|
|
|
|
|
|
h, w = frames[0].shape[:2]
|
2026-05-20 13:42:48 +02:00
|
|
|
scale = display_max / max(h, w)
|
2026-05-20 13:26:03 +02:00
|
|
|
dh, dw = int(h * scale), int(w * scale)
|
|
|
|
|
|
|
|
|
|
frames = [cv2.resize(f, (dw, dh)) for f in frames]
|
|
|
|
|
|
|
|
|
|
return frames, fps, dh, dw, h, w
|