|
|
import cv2 |
|
|
import os |
|
|
import subprocess |
|
|
|
|
|
def make_video_grid_2x2(out_path, vid_paths, overwrite=False): |
|
|
""" |
|
|
将四个视频以原始分辨率拼接成 2x2 网格。 |
|
|
|
|
|
:param out_path: 输出视频路径。 |
|
|
:param vid_paths: 输入视频路径的列表(长度必须为 4)。 |
|
|
:param overwrite: 如果为 True,覆盖已存在的输出文件。 |
|
|
""" |
|
|
if os.path.isfile(out_path) and not overwrite: |
|
|
print(f"{out_path} already exists, skipping.") |
|
|
return |
|
|
|
|
|
if any(not os.path.isfile(v) for v in vid_paths): |
|
|
print("Not all inputs exist!", vid_paths) |
|
|
return |
|
|
|
|
|
|
|
|
if len(vid_paths) != 4: |
|
|
print("Error: Exactly 4 video paths are required!") |
|
|
return |
|
|
|
|
|
|
|
|
v1, v2, v3, v4 = vid_paths |
|
|
|
|
|
|
|
|
cmd = ( |
|
|
f"ffmpeg -i {v1} -i {v2} -i {v3} -i {v4} " |
|
|
f"-filter_complex '[0:v][1:v][2:v][3:v]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v]' " |
|
|
f"-map '[v]' {out_path} -y" |
|
|
) |
|
|
|
|
|
print(cmd) |
|
|
subprocess.call(cmd, shell=True, stdin=subprocess.PIPE) |
|
|
|
|
|
def create_video_from_images(image_list, output_path, fps=15, target_resolution=(540, 540)): |
|
|
""" |
|
|
将图片列表合成为 MP4 视频。 |
|
|
|
|
|
:param image_list: 图片路径的列表。 |
|
|
:param output_path: 输出视频的文件路径(如 output.mp4)。 |
|
|
:param fps: 视频的帧率(默认 15 FPS)。 |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
first_image = cv2.imread(image_list[0]) |
|
|
if first_image is None: |
|
|
print(f"无法读取图片: {image_list[0]}") |
|
|
return |
|
|
|
|
|
height, width, _ = first_image.shape |
|
|
if height != width: |
|
|
if height < width: |
|
|
vis_w = target_resolution[0] |
|
|
vis_h = int(target_resolution[0] / width * height) |
|
|
elif height > width: |
|
|
vis_h = target_resolution[0] |
|
|
vis_w = int(target_resolution[0] / height * width) |
|
|
else: |
|
|
vis_h = target_resolution[0] |
|
|
vis_w = target_resolution[0] |
|
|
target_resolution = (vis_w, vis_h) |
|
|
|
|
|
|
|
|
fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
|
|
video_writer = cv2.VideoWriter(output_path, fourcc, fps, target_resolution) |
|
|
|
|
|
|
|
|
for image_path in image_list: |
|
|
frame = cv2.imread(image_path) |
|
|
frame_resized = cv2.resize(frame, target_resolution) |
|
|
if frame is None: |
|
|
print(f"无法读取图片: {image_path}") |
|
|
continue |
|
|
video_writer.write(frame_resized) |
|
|
|
|
|
|
|
|
video_writer.release() |
|
|
print(f"视频已保存至: {output_path}") |