一、问题:大批量的音频测试文件,无法满足测试需求
项目测试需要往平台中上传一批音频文件进行算法测试, 平台规定的音频的时长必须在10-30s内, 而从算法开发人员那里获取到的3000条音频文件都是32s时长, 因此无法将测试数据上传到平台进行测试。
基于以上问题,需要在项目体测之前将3000条音频文件都转换成30s以内的文件,手动裁剪的话费时费力,且没有那么多的时间和人力去处理。因此想到了编写工具脚本来批量处理这些音频文件
二、解决思路:批量裁剪音频文件
网上搜索到python中的第三方库pydub中有很多音频文件处理的方法,以下是脚本的实现思路
1、调用脚本,传参:音频文件路径、音频文件格式,裁剪模式,裁剪的起点,裁剪的终点
音频文件格式:一般是mp3、wav格式
裁剪模式:分为模式1和模式2, 输入的是模式1的话,则将一条音频裁剪成相等时长的两段音频文件(生成了2条音频);输入的是模式2的话,则裁剪出起点 和终点之间的一段音频文件(生成了1条音频)
裁剪的起点、裁剪的终点:即按照指定的音频的开始时间位置和结束时间位置进行裁剪,参数值的单位为秒
2、根据 音频文件路径参数,先在此路径下生成一个名为“separateResultFile”的文件夹,若已存在此文件夹,则删除重新创建,若未存在此文件夹,则直接创建
3、根据1中输入的参数,读取音频文件夹下的所有文件,并循环处理每一条文件,并将处理后生成的音频文件保存到“separateResultFile”文件夹中
三、解决过程:采用python中的第三方库pydub进行批量处理音频文件
如下图所示,是实现的代码。用到了pydub 库中的AudioSegment 和 pydub.utils 中的make_chunks
from pydub import AudioSegment
from pydub.utils import make_chunks
import os, re,shutil
def mikdir(path):
folder=os.path.exists(path)
if not folder:
os.makedirs(path)
else:
shutil.rmtree(path)
os.makedirs(path)
return path
def audioFileSeparate(filepath,audiofile_type,separate_mode,starttime=0,endtime=0):
"""
:param filepath: 音频文件存放的文件夹路径
:param audiofile_type: 音频文件格式(mp3、wav等格式)
:param separate_mode: 裁剪模式(1:裁剪成长度相等的两段视频,2:输入起止时间进行裁剪)
:param starttime,endtime: 如果模式为2时,需要输入裁剪的开始时间和结束时间,单位为秒
:return:无
"""
#创建分割后存储的文件夹
savepath=mikdir(os.path.join(filepath,"separateResultFile"))
# # 循环目录下所有文件
for eachfile in os.listdir(filepath): # 循环目录
#audiofilename = re.findall(r"(.*?)\.wav", eachfile) # 取出.mp3后缀的文件名
print(eachfile)
try:
if eachfile:
audiofile_path = os.path.join(filepath, eachfile)
audiofile = AudioSegment.from_file_using_temporary_files(file=audiofile_path,
format=audiofile_type) # 打开指定格式的文件
# mp3 = AudioSegment.from_file('P:/ai测试数据/光纤/光纤/异常//{}'.format(eachfile), "wav") # 打开mp3文件
# # # mp3[17*1000+500:].export(filename[0], format="mp3") # 切割前17.5秒并覆盖保存,与以下代码不可同时使用
audioDuration = audiofile.duration_seconds
if separate_mode == 1:
# size = 16000 # 切割的毫秒数 10s=10000
chunks = make_chunks(audiofile, audioDuration // 2 * 1000) # 将文件平分成两个
for i, chunk in enumerate(chunks):
chunk_name = "{}-{}.wav".format(eachfile.split(".")[0], i) # 也可以自定义名字
# chunk.export('P:/ai测试数据/光纤/光纤/异常分割后/{}'.format(chunk_name), format=audiofile_type) # 新建的保存文件夹
chunk.export(savepath+ "/" + chunk_name, format=audiofile_type) # 新建的保存文件夹
elif separate_mode == 2:
audioAfterSeparate = audiofile[starttime*1000:endtime*1000]
audioAfterSeparate_name = "{}-{}.wav".format(eachfile.split(".")[0], 0) # 也可以自定义名字
audioAfterSeparate.export(savepath + "/" + audioAfterSeparate_name, format=audiofile_type)
else:
print("separate_mode 参数只能是1或2, 您输入的参数有误")
else:
print("文件夹下无视频文件,请确认一下文件夹路径")
except PermissionError:
pass
if __name__ == '__main__':
#audioFileSeparate(filepath="C:\\Users\\chenna9\\Desktop\\test",audiofile_type="wav",separate_mode=2,starttime=0,endtime=30)
audioFileSeparate(filepath="C:\\Users\\chenna9\\Desktop\\test", audiofile_type="wav", separate_mode=2, starttime=0,
endtime=30)
四、总结
1、脚本实现过程中,出现了permissionError 的问题,问题得到了一定程度的解决,但最后还是会有这个报错,所有并没有真正意义上的解决,最后是将此报错忽略了,具体解放方法可查看此的随笔 :python--python脚本中保存处理后的音频文件到指定文件夹时报错permission denied 的问题
2、将文件夹下的所有文件,获取到并循环处理每一个音频文件, 其实这里是有问题的,有可能此文件夹下有非音频类型的文件,所有应该是获取到指定的格式的文件并对此文件进行处理。
不过由于时间有限,且工作中都是一个文件夹下都是音频文件,所有此需求点比较低,没有实现,后续有需要的话再优化把。
3、其实代码里异常捕捉和处理的功能没有实现,奈何自己这块还有点薄弱,后续加强这一块的学习和使用把。