Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用moviepy进行多处理_Python_Moviepy - Fatal编程技术网

Python 使用moviepy进行多处理

Python 使用moviepy进行多处理,python,moviepy,Python,Moviepy,最近,我制作了一个脚本,用5分钟的视频剪辑和5个视频的剪辑,每个视频1分钟,效果很好,但对于像我这样的pc来说,时间太长,而且我的pc的部件性能非常好: 英特尔(R)核心(TM)i7-10700 CPU@2.90GHz,2904 Mhz,8核,16 逻辑处理器 已安装的物理内存(RAM)16.0 GB 所以我在moviepy的文档“线程”中搜索,我在“write_videofile”函数中找到了一些东西,我可以设置我的线程以加快速度,我尝试了它,但它不起作用,我的意思是它起作用了,但只是它可能变

最近,我制作了一个脚本,用5分钟的视频剪辑和5个视频的剪辑,每个视频1分钟,效果很好,但对于像我这样的pc来说,时间太长,而且我的pc的部件性能非常好:

英特尔(R)核心(TM)i7-10700 CPU@2.90GHz,2904 Mhz,8核,16 逻辑处理器

已安装的物理内存(RAM)16.0 GB

所以我在moviepy的文档“线程”中搜索,我在“write_videofile”函数中找到了一些东西,我可以设置我的线程以加快速度,我尝试了它,但它不起作用,我的意思是它起作用了,但只是它可能变为2或3 it/s以上

我还发现了带有多线程的示例代码,但似乎代码不起作用,因为moviepy库中不存在moviepy.multi-threading,请帮助我加快渲染速度, 多谢各位

以下是我找到的代码:

从moviepy.multi-threading导入multi-thread\u write\u视频文件
def concat_clips():
文件=[
“myclip1.mp4”,
“myclip2.mp4”,
“myclip3.mp4”,
“myclip4.mp4”,
]
多线程写入视频文件(“output.mp4”,获取最终剪辑,{“files”:files})
def get_最终_剪辑(文件):
clips=[视频文件剪辑(文件)用于文件中的文件]
最终=连接视频剪辑(剪辑,方法=“合成”)
返回决赛
这是我的代码:

从moviepy.video.io.ffmpeg\u工具导入ffmpeg\u提取\u子剪辑
从moviepy.editor导入*
从numpy导入数组中,选择true_divide
进口cv2
导入时间
#ffmpeg_extract_subclip(“full.mp4”、开始秒、结束秒、targetname=“cut.mp4”)
def duration_剪辑(文件名):
clip=VideoFileClip(文件名)
持续时间=clip.duration
返回持续时间
当前\u时间=时间.strftime(“%Y\u%m\u%d\u%H\u%m\u%S”)
def main():
全局持续时间
开始=0
切割\u名称\u数量=1
结束时间=开始时间+60秒
视频持续时间=持续时间剪辑(“video.mp4”)
txt=输入(“请输入您的文本:”)[:-1]
txt_部分=1
当开始
使用进程我只减少了15-20秒的时间,因为即使是在单个进程中,我的计算机也几乎耗尽了CPU的全部能力,无法更快地运行其他进程


首先,我减少了代码,使其更短

tryexcept中的代码具有相似的元素,因此我将它们移到了try/except之外

接下来我用

        if end > video_duration:
            end = video_duration
我根本不需要
尝试/除了

使用
os.makedirs(…,exist\u ok=True)
我不需要在
try/except中运行它

同时,我使用

        clip = VideoFileClip(filename).subclip(start, end)
而不是

        temp_filename  = f"{base_folder}/cut_{number}.mp4"
        
        fmpeg_extract_subclip(filename, start, end, targetname=temp_filename)
        
        clip = VideoFileClip(temp_filename)
这样,我就不需要在磁盘上写subclip,也不需要从磁盘上再次读取它


接下来,我将代码移动到带有参数的函数
myu进程(文件名、文本、开始、结束、编号、基本文件夹)

现在我可以使用标准模块在单独的进程中运行函数

(或标准模块或外部模块等)

它只启动一个进程

# it has to use named arguments`target=`, `args=`

p = multiprocessing.Process(target=my_process, args=(filename, text, start, end, number, base_folder))
p.start()  # start it
但如果我在循环中使用它,那么我将同时启动许多进程



11个子进程的早期版本启动11个进程。使用
Pool(4)
可以将所有进程放入池中,它将同时运行4个进程。当一个进程完成任务时,它将使用新参数启动下一个进程

这一次,我使用循环为所有进程创建带有参数的列表

args_for_all_processes = []

for start in range(0, int(video_duration), 60):

    end = start + 60
    
    if end > video_duration:
        end = video_duration
    
    number += 1
    print("add process:", number)
    
    args_for_all_processes.append( (filename, text, start, end, number, base_folder) )
我将这个列表与
一起使用,它将完成其余的工作

# I have 4 CPU so I use Pool(4) - but without value it should automatically use `os.cpu_count()`
with multiprocessing.Pool(4) as pool:      
    results = pool.starmap(my_process, args_for_all_processes)
    #print(results)
Pool
可能以不同的顺序启动进程,但如果它们使用
return
发送一些结果,则
Pool
将以正确的顺序给出结果

from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from moviepy.editor import *
import time
import multiprocessing

def my_process(filename, text, start, end, number, base_folder):

    clip_duration = end - start
    print(f'[DEBUG] number: {number:2} | start: {start:6.2f} | end: {end:6.2f} | duration: {clip_duration:.2f}')
    
    final_text = f"{number} {text}"

    temp_filename  = f"{base_folder}/cut_{number}.mp4"
    final_filename = f"{base_folder}/result_edit/cut_{number}.mp4"
    
    #print('[DEBUG] ffmpeg_extract_subclip')
    #ffmpeg_extract_subclip(filename, start, end, targetname=temp_filename)
    
    #print('[DEBUG] VideoClip')
    #clip = VideoFileClip(temp_filename)
    clip = VideoFileClip(filename).subclip(start, end)
    clip = clip.volumex(2)

    #print('[DEBUG] TextClip')
    txt_clip = TextClip(final_text, font="font/VarelaRound-Regular.ttf", fontsize=50, color='white')
    txt_clip = txt_clip.set_pos(("center","top")).set_duration(60)
    
    #print('[DEBUG] CompositeVideoClip')
    video = CompositeVideoClip([clip, txt_clip])

    #print('[DEBUG] CompositeVideoClip write')
    video.write_videofile(final_filename)
    #print('[DEBUG] CompositeVideoClip end')
    
    # return "OK"  # you can use `return` to send result/information to main process.
    
def main():

    text = input("Enter Your text please: ") [::-1]
    #text = 'Hello World'
    
    base_folder = time.strftime("result_%Y_%m_%d_%H_%M_%S")    
    os.makedirs(f"{base_folder}/result_edit", exist_ok=True)
    
    filename = "video.mp4"
    #filename = "BigBuckBunny.mp4"
    
    video_duration = VideoFileClip(filename).duration

    number = 0 # instead of `cut_name_num` and `txt_part` because both had the same value

    time_start = time.time()
    
    # first create list with arguments for all processes
    
    args_for_all_processes = []
    
    for start in range(0, int(video_duration), 60):

        end = start + 60
        
        if end > video_duration:
            end = video_duration
        
        number += 1
        print("add process:", number)
        
        args_for_all_processes.append( (filename, text, start, end, number, base_folder) )

    # - after loop -            
        
    # next put all processes to pool
        
    with multiprocessing.Pool(4) as pool:  # I have 4 CPU so I use Pool(4) - but it should use `os.cpu_count()` in `Pool()
    
        results = pool.starmap(my_process, args_for_all_processes)
        #print(results)
            
    # - after loop -
    
    # because I use `number += 1` before loop so now `number` has number of subclips
    print('number of subclips:', number)

    time_end = time.time()
    
    diff = time_end - time_start
    print(f'time: {diff:.2f}s ({diff//60:02.0f}:{diff%60:02.2f})')


if __name__ == "__main__":
    main()

我想知道如何能够在线程中连接文件。至于我,你们不能在你们写完第一个文件之前开始写第二个文件,所以第二个文件依赖于第一个文件,并没有地方把它分成两个线程。若因为创建了fi而必须剪切文件,则可以拆分该问题
args_for_all_processes = []

for start in range(0, int(video_duration), 60):

    end = start + 60
    
    if end > video_duration:
        end = video_duration
    
    number += 1
    print("add process:", number)
    
    args_for_all_processes.append( (filename, text, start, end, number, base_folder) )
# I have 4 CPU so I use Pool(4) - but without value it should automatically use `os.cpu_count()`
with multiprocessing.Pool(4) as pool:      
    results = pool.starmap(my_process, args_for_all_processes)
    #print(results)
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from moviepy.editor import *
import time
import multiprocessing

def my_process(filename, text, start, end, number, base_folder):

    clip_duration = end - start
    print(f'[DEBUG] number: {number:2} | start: {start:6.2f} | end: {end:6.2f} | duration: {clip_duration:.2f}')
    
    final_text = f"{number} {text}"

    temp_filename  = f"{base_folder}/cut_{number}.mp4"
    final_filename = f"{base_folder}/result_edit/cut_{number}.mp4"
    
    #print('[DEBUG] ffmpeg_extract_subclip')
    #ffmpeg_extract_subclip(filename, start, end, targetname=temp_filename)
    
    #print('[DEBUG] VideoClip')
    #clip = VideoFileClip(temp_filename)
    clip = VideoFileClip(filename).subclip(start, end)
    clip = clip.volumex(2)

    #print('[DEBUG] TextClip')
    txt_clip = TextClip(final_text, font="font/VarelaRound-Regular.ttf", fontsize=50, color='white')
    txt_clip = txt_clip.set_pos(("center","top")).set_duration(60)
    
    #print('[DEBUG] CompositeVideoClip')
    video = CompositeVideoClip([clip, txt_clip])

    #print('[DEBUG] CompositeVideoClip write')
    video.write_videofile(final_filename)
    #print('[DEBUG] CompositeVideoClip end')
    
    # return "OK"  # you can use `return` to send result/information to main process.
    
def main():

    text = input("Enter Your text please: ") [::-1]
    #text = 'Hello World'
    
    base_folder = time.strftime("result_%Y_%m_%d_%H_%M_%S")    
    os.makedirs(f"{base_folder}/result_edit", exist_ok=True)
    
    filename = "video.mp4"
    #filename = "BigBuckBunny.mp4"
    
    video_duration = VideoFileClip(filename).duration

    number = 0 # instead of `cut_name_num` and `txt_part` because both had the same value

    time_start = time.time()
    
    # first create list with arguments for all processes
    
    args_for_all_processes = []
    
    for start in range(0, int(video_duration), 60):

        end = start + 60
        
        if end > video_duration:
            end = video_duration
        
        number += 1
        print("add process:", number)
        
        args_for_all_processes.append( (filename, text, start, end, number, base_folder) )

    # - after loop -            
        
    # next put all processes to pool
        
    with multiprocessing.Pool(4) as pool:  # I have 4 CPU so I use Pool(4) - but it should use `os.cpu_count()` in `Pool()
    
        results = pool.starmap(my_process, args_for_all_processes)
        #print(results)
            
    # - after loop -
    
    # because I use `number += 1` before loop so now `number` has number of subclips
    print('number of subclips:', number)

    time_end = time.time()
    
    diff = time_end - time_start
    print(f'time: {diff:.2f}s ({diff//60:02.0f}:{diff%60:02.2f})')


if __name__ == "__main__":
    main()