我试着用包将视频文件转换成音频。它工作得很好。但是,我有1500 100 of大小的视频,我想把它们全部转换成音频文件。采用标准方法需要很长时间。
将一个视频文件转换为音频的代码:
import moviepy.editor as mp
clip = mp.VideoFileClip('file.mp4')
clip.audio.write_audiofile(r"file.mp3")
我也可以使用线程同时转换多个文件,但我想利用多线程和多线程,以获得最有效的结果,以较少的时间复杂度。
Algo只使用线程:
clip1...clip10= make 10 lists with 150 files names from os.listdir()
spawn 10 threads to process 10 files at a time.
t1= Thread(target=convert, args=(clips1))
.
.
.
t10= Thread(target=convert, args=(clips2))
有什么想法吗?
发布于 2021-02-08 14:23:25
在一种情况下,多线程和多处理的组合可能是有利的,即执行的任务由清晰描述的部分组成,其中一部分主要是I/O绑定(或者至少放弃全局解释器锁,经常允许其他线程运行),而另一部分则是CPU密集型的。例如,您需要执行由两部分组成的多个任务:(1)从网站中检索一段信息,(2)然后使用该信息进行一些非平凡的计算。第1部分显然非常适合多线程处理,因为在发出请求以检索URL之后,线程将进入等待状态,允许其他线程运行。如果第2部分是一个琐碎的计算,为了简单起见,只需在线程中计算即可。但是,由于我们是说这是非平凡的,在一个单独的过程中执行计算,这样我们就不必担心全局解释器锁(GIL)的争用了。
执行上述处理类型的模型是同时创建线程池和多处理池。“作业”提交给线程池工作者函数,指定需要作为一个参数检索信息的网站的URL,以及作为另一个参数的多处理池。线程池辅助函数首先从传递的URL中检索所需的信息,然后提交给使用传递的多处理池执行计算的第二个辅助函数。
尽管如此,我不太明白您的情况是如何划分为纯I/O绑定部分和纯CPU绑定部分的。显然,调用clip = mp.VideoFileClip('file.mp4')
同时执行I/O和处理数据以供查看。同样,clip.audio.write_audiofile(r"file.mp3")
进行CPU处理,将视频剪辑转换为音频剪辑,我认为这主要是一个与CPU绑定的进程,然后写出文件,这显然是一个I/O绑定进程。
如果API是以不同的方式设计的,其中文件的读取和写入是独立的方法,那么我认为使用线程和多处理都是可行的。例如:
with open('file.mp4', 'rb') as f:
mp4_file = f.read() # I/O
clip = mp.VideoClipFromMemory(mp4_file) # CPU
clip.convertToAudio() # CPU
clip.writeFile('file.mp3') # I/O
因此,最大的问题是:你的“工作”是从视频转换为音频,更多的CPU或更多的I/O绑定。如果是前者,那么您应该使用一个多处理池,这个池的大小可能会比您拥有的CPU核数目大得多,因为进程在等待I/O完成时,毕竟会进入等待状态,因为作业不是完全受CPU限制的。如果是后者,那么您应该使用多线程,因为线程在创建过程中所涉及的开销较少。但我怀疑你在多重处理方面会做得更好。下面的代码,只要做一些小改动,就可以使用以下两种方法之一:
import moviepy.editor as mp
import glob
import os
from concurrent.futures import ProcessPoolExecutor as Executor
# To use multithreading:
# from concurrent.futures import ThreadPoolExecutor as Executor
def converter(filename):
clip = mp.VideoFileClip(f'{filename}.mp4')
clip.audio.write_audiofile(f'{filename}.mp3')
def main():
mp4_filenames = map(lambda x: x.split('.')[0], glob.iglob('*.mp4'))
POOL_SIZE = os.cpu_count() # number of cores
# You might want to try a larger size, especially if you are using a thread pool:
with Executor(max_workers=POOL_SIZE) as executor:
executor.map(converter, mp4_filenames)
# required for multiprocessing under Windows
if __name__ == '__main__':
main()
补充意见/建议
我的建议是尝试一个小示例,比如100个文件,这两种方法(ProcessPoolExecutor和ThreadPoolExecutor)都使用相同的池大小os.cpu_count()
,并针对相同的100个文件运行,以查看哪个文件在较短的时间内完成。如果是ProcessPoolExecutor
运行,那么您可以看到增加池大小是否有助于重叠I/O处理和提高吞吐量。如果是ThreadPoolExecutor
运行,则可以大大增加线程池大小,直到性能下降为止。线程池大小为100 (或在处理所有文件时更大)并非不合理。
发布于 2021-02-08 14:19:45
如果您的所有视频都有相同的音频编解码器(AAC,又名MP4音频),您可以简单地将音频流屏蔽到单独的文件中。不需要转换/编码任何东西。
ffmpeg -i input.mp4 -vn -c:a copy audio.m4a
或者,如果您真的想要MP3文件(我不建议这样做,MP3已经过时了),您可以执行以下操作:
ffmpeg -i input.mp4 -vn -c:a mp3 -b:a 256k audio.mp3
这将只需要几毫秒的视频。
https://stackoverflow.com/questions/66100395
复制相似问题