|
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 |
|
|