| import os |
| import cv2 |
| import numpy as np |
| import math |
| from modules.video_queue import JobStatus |
|
|
| def assemble_grid_video(grid_job, child_jobs, settings): |
| """ |
| Assembles a grid video from the results of child jobs. |
| """ |
| print(f"Starting grid assembly for job {grid_job.id}") |
| |
| output_dir = settings.get("output_dir", "outputs") |
| os.makedirs(output_dir, exist_ok=True) |
| |
| video_paths = [child.result for child in child_jobs if child.status == JobStatus.COMPLETED and child.result and os.path.exists(child.result)] |
| |
| if not video_paths: |
| print(f"No valid video paths found for grid job {grid_job.id}") |
| return None |
| |
| print(f"Found {len(video_paths)} videos for grid assembly.") |
|
|
| |
| num_videos = len(video_paths) |
| grid_size = math.ceil(math.sqrt(num_videos)) |
| |
| |
| try: |
| cap = cv2.VideoCapture(video_paths[0]) |
| if not cap.isOpened(): |
| raise IOError(f"Cannot open video file: {video_paths[0]}") |
| width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) |
| height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
| fps = cap.get(cv2.CAP_PROP_FPS) |
| cap.release() |
| except Exception as e: |
| print(f"Error getting video properties from {video_paths[0]}: {e}") |
| return None |
|
|
| output_filename = os.path.join(output_dir, f"grid_{grid_job.id}.mp4") |
| fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
| video_writer = cv2.VideoWriter(output_filename, fourcc, fps, (width * grid_size, height * grid_size)) |
|
|
| caps = [cv2.VideoCapture(p) for p in video_paths] |
|
|
| while True: |
| frames = [] |
| all_frames_read = True |
| for cap in caps: |
| ret, frame = cap.read() |
| if ret: |
| frames.append(frame) |
| else: |
| |
| all_frames_read = False |
| break |
| |
| if not all_frames_read or not frames: |
| break |
|
|
| |
| grid_frame = np.zeros((height * grid_size, width * grid_size, 3), dtype=np.uint8) |
|
|
| |
| for i, frame in enumerate(frames): |
| row = i // grid_size |
| col = i % grid_size |
| grid_frame[row*height:(row+1)*height, col*width:(col+1)*width] = frame |
|
|
| video_writer.write(grid_frame) |
|
|
| for cap in caps: |
| cap.release() |
| video_writer.release() |
| |
| print(f"Grid video saved to {output_filename}") |
| return output_filename |
|
|