import cv2
|
import numpy as np
|
import subprocess
|
|
def read_video_frames_to_memory(video_path, frame_rate=30):
|
"""
|
使用 FFmpeg 将视频帧以 PNG 格式直接读取到内存中。
|
"""
|
ffmpeg_command = [
|
"ffmpeg", "-i", video_path,
|
"-vf", f"fps={frame_rate}",
|
"-f", "image2pipe", "-vcodec", "png", "-"
|
]
|
|
frame_size = 1080*1440*3
|
|
# 使用 subprocess 打开 FFmpeg 进程
|
process = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=frame_size**1)
|
|
frames = []
|
try:
|
while True:
|
# 读取单帧数据
|
frame_bytes = process.stdout.read(frame_size) # 每次尝试读取 1MB
|
if not frame_bytes:
|
break
|
|
# 解码 PNG 数据为 NumPy 数组(使用 OpenCV)
|
frame = cv2.imdecode(np.frombuffer(frame_bytes, np.uint8), cv2.IMREAD_UNCHANGED)
|
if frame is not None:
|
frames.append(frame)
|
finally:
|
process.stdout.close()
|
process.wait()
|
|
return frames
|
|
def write_frames_to_mp4(frames, output_path, frame_rate=30):
|
"""
|
从帧数据生成 MP4 文件。
|
"""
|
if not frames:
|
print("No frames to write.")
|
return
|
|
# 获取帧尺寸 (高度, 宽度)
|
frame_height, frame_width = frames[0].shape[:2]
|
print(frame_width,frame_height)
|
|
# 定义视频编码器和输出文件
|
fourcc = cv2.VideoWriter_fourcc(*"mp4v") # MP4 格式编码器
|
video_writer = cv2.VideoWriter(output_path, fourcc, frame_rate, (frame_width, frame_height))
|
|
for frame in frames:
|
# 检查帧是否是三通道 (RGB/BGR),如果需要转换格式
|
if len(frame.shape) == 2: # 灰度图
|
frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
|
elif frame.shape[2] == 4: # RGBA
|
frame = cv2.cvtColor(frame, cv2.COLOR_RGBA2BGR)
|
|
video_writer.write(frame)
|
|
video_writer.release()
|
print(f"Video saved to {output_path}")
|
|
if __name__ == "__main__":
|
video_path = "E:/抖音-AI风景/Test/demo.mp4"
|
output_path = "output.mp4"
|
|
# 读取视频帧到内存
|
frames = read_video_frames_to_memory(video_path)
|
|
# 将帧数据写入 MP4 文件
|
write_frames_to_mp4(frames, output_path)
|