简体   繁体   English

使用多处理批量转换.wav到.flac(Python,Pydub)

[英]Using Multiprocessing to Batch Convert .wav to .flac (Python, Pydub)

So I have written a very simple Python 3 program to take all of the .wav audio files in the working directory and convert them to .flac. 所以我编写了一个非常简单的Python 3程序来获取工作目录中的所有.wav音频文件并将它们转换为.flac。 Don't worry about any assumptions it makes (like the .wav files being valid, output filenames already existing, etc.). 不要担心它所做的任何假设(例如.wav文件有效,输出文件名已经存在等)。 See below: 见下文:

import os
from multiprocessing import Pool
from pydub import AudioSegment

def worker(filename):
  song = AudioSegment.from_wav(filename)
  song.export(filename.replace(".wav",".flac"), format = "flac")

if __name__ == '__main__':
  converted_count = 0
  convertlist = []
  for filename in os.listdir(os.getcwd()):
    if filename.endswith(".wav"):
      convertlist.append(filename)
      converted_count += 1
  p = Pool(processes=min(converted_count, os.cpu_count()))
  p.map(worker, convertlist)

I've timed this and, on my system, have noticed a significant speedup as compared to using no multiprocessing at all. 我已经计时了,并且在我的系统上,与没有使用多处理相比,已经注意到了显着的加速。 However, this almost seems too simple; 然而,这几乎看起来太简单了; I'm not very experienced with multiprocessing (nor multithreading), so I'm honestly not sure if there's a faster, more efficient way to do this. 我对多处理(也不是多线程)不是很有经验,所以老实说我不确定是否有更快,更有效的方法来做到这一点。

If you were tasked with writing this simple converter in Python, how would you do it? 如果你的任务是用Python编写这个简单的转换器,你会怎么做? What would you do to make it more efficient than this? 你会做些什么来使它比这更有效?

The pydub package that you are using in worker() is already pretty efficient, given that it is backed by a low level media library that is not written in Python: FFmpeg. 您在worker()中使用的pydub包已经非常高效,因为它由不是用Python编写的低级媒体库支持:FFmpeg。 That is, under the hood, pydub calls the ffmpeg command using the subprocess module (see pydub code ) to perform the conversion, resulting in a command that looks like this: 也就是说,在引擎盖下,pydub使用subprocess 进程模块调用ffmpeg命令(请参阅pydub代码 )来执行转换,从而产生如下所示的命令:

ffmpeg -y -f wav -i input.wav -write_xing 0 -f flac output.flac 

Unfortunately, FFmpeg's FLAC encoder implementation does not seem to be parallelized and it is therefore not possible to improve the encoding speed of each independent file while keeping the same encoding quality, with this specific encoder. 不幸的是,FFmpeg的FLAC编码器实现似乎没有并行化,因此使用这种特定的编码器不可能在保持相同编码质量的同时提高每个独立文件的编码速度。 Assuming that you want to keep using pydub and its FFmpeg FLAC encoder, your approach to the problem consisting of processing each file in a different process sounds reasonable. 假设您要继续使用pydub及其FFmpeg FLAC编码器,那么在不同过程中处理每个文件的问题的方法听起来是合理的。

However, if you really wanted to improve performance at all costs, an alternative option would be to trade audio quality for conversion speed. 但是,如果您真的想不惜一切代价提高性能,另一种选择是交换音频质量以获得转换速度。 For this, you could tune some of the encoding parameters, such as reducing the sampling frequency: 为此,您可以调整一些编码参数,例如降低采样频率:

# export the song with a lower sampling frequency
low_quality_song = song.set_frame_rate(11025)
low_quality_song.export(flac_filename, format="flac")

That being said, given that you are targeting a lossless format, switching to a more efficient (potentially GPU-based) encoder would most likely produce much better results while keeping the same audio quality. 话虽如此,鉴于您的目标是无损格式,切换到更高效(可能基于GPU的)编码器最有可能产生更好的结果,同时保持相同的音频质量。

If you have lots of small files (eg audio samples for speech recognition), so that conversion of a single file takes a fraction of a second, then you can reduce scheduling overhead of the multiprocessing module by batching multiple files together for conversion, so that each process converts more than one file at a time. 如果您有许多小文件(例如用于语音识别的音频样本),那么单个文件的转换只需要几分之一秒,那么您可以通过将多个文件一起批处理以进行转换来减少多处理模块的调度开销,以便每个进程一次转换多个文件。 Eg modify the filename loop, or group items in convertlist and add iteration in worker. 例如,修改文件名循环,或在convertlist中对项目进行分组,并在worker中添加迭代。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM