wangzhibo
2024-12-04 4c5a1f2f09f6906bf26a783d2fa345a5886a2335
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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)