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
import subprocess
import os
 
def test_pipeline_to_multiple_slices(video_path):
    frame_segments = [(0, 60), (60, 79), (79, 98), (98, 116), (116, 135),
                      (135, 153), (153, 172), (172, 190), (190, 209),
                      (209, 228), (228, 247), (247, 266), (266, 285), (285, 305)]  # 帧区间
    
    # 启动 FFmpeg 以读取视频帧数据并通过管道输出
    ffmpeg_extract = [
        "ffmpeg", "-i", video_path, "-vf", "fps=30", "-f", "image2pipe", "-vcodec", "png", "-"
    ]
    process_extract = subprocess.Popen(ffmpeg_extract, stdout=subprocess.PIPE, bufsize=10**8)  # 使用较大缓冲区
 
    # 创建多个子进程,处理视频切片
    slice_processes = []
    output_pipes = []
 
    for i, (start_frame, end_frame) in enumerate(frame_segments):
        output_file = f"slice_{i+1}.mp4"
        ffmpeg_encode = [
            "ffmpeg", "-framerate", "30", "-f", "image2pipe", "-vcodec", "png", "-i", "-",
            "-c:v", "libx264", "-preset", "slow", "-crf", "0", "-pix_fmt", "yuv420p", output_file
        ]
        process = subprocess.Popen(ffmpeg_encode, stdin=subprocess.PIPE)
        slice_processes.append(process)
        output_pipes.append((process.stdin, start_frame, end_frame))
 
    current_frame = 0
 
    try:
        while True:
            frame_data = process_extract.stdout.read(1024*1024)  # 每次读取 1MB,直到无数据
            if not frame_data:
                break  # 当读取到视频结束时跳出循环
 
            # 分发帧数据到合适的子进程
            for pipe, start_frame, end_frame in output_pipes:
                if start_frame <= current_frame < end_frame:
                    pipe.write(frame_data)  # 写入帧数据
                    break
 
            current_frame += 1
 
    finally:
        # 关闭所有子进程的输入流
        for pipe, _, _ in output_pipes:
            pipe.close()
 
        # 等待所有子进程完成
        for process in slice_processes:
            process.wait()
 
        # 关闭提取进程的输出流
        process_extract.stdout.close()
        process_extract.wait()
 
if __name__ == "__main__":
    video_path = "E:/抖音-AI风景/Test/demo.mp4"
    test_pipeline_to_multiple_slices(video_path)