2019年1月

语音播报音频文件的生成,IOS12可能需要它

首先,我不是做IOS的,但是为什么我知道IOS需要它,还是IOS12以后才需要,其实很简单,因为我是做Android,同事是做IOS的,因为语音播报中IOS12后的推送出现了限制,目前只能使用此方法,做IOS自然懂,我不懂,就不多说了,其实没任何技术含量,只是闲着无事研究了一下如何合并音频文件,如何压缩音频文件,得到效果最好而且文件小,这样的事情。

其实,本文的本质其实就是生成批处理文件,然后去执行它而已,我虽然没有MAC,但是其执行的命令行应该不会差太多,然后我自己写的代码其实没有几行,而且只是为了实现需求,无事性能,因为考虑到生成个批处理文件,慢个10、20倍也没多大影响,加之代码质量差,就没有任何代码了,毕竟现在还只是个菜鸡,给自己和面子。

一、音频文件的获取和形式
首先是获取,如果你们公司还算对语音播报比较重视,那么公司应该会安排好,然后最终把音频文件给你的,但是,我想会自己录制的公司可能不多,我所在的公司是一家乙方公司,给甲方维护APP,我给甲方提交了需要音频文件的需求,目前还没有回复我,这种情况先用已经录制好的音频好了,或者用百度语音、讯飞什么的合成一些素材,这里我使用的是支付宝的语音播报文件。
然后是语音的形式,其实没什么可说的,它就是每个字每个字的音频文件,如“135.6元”,那么音频文件就是“一”、“百”、“三”、"十"、“五”、“点”、“六”、“元”,一般情况下语音播报多采用这种拼接的方式进行连续的音频文件播放,因为此方式在效率,性能、及时性方面都是最好的,如果你有更好的方式,来告诉我哇。

二、生成批处理文件
这里的批处理文件,是指Windows下的BAT文件,我对BAT的语法和使用方式并不了解,可以的话,完全可以优化一下这里使用的方法。这里只说逻辑,我这里直接使用了Android的开源项目,如何将数字对应上相应的音频文件,全部使用了此项目。
生成批处理文件是为了拼接音频文件,这里使用的是FFMPEG,这里不在赘述,拼接的命令行如下

ffmpeg -i tts_success.mp3 -i tts_9.mp3 -i tts_ten.mp3 -i tts_9.mp3 -i tts_yuan.mp3 -filter_complex "[0:0] [1:0] [2:0] [3:0] [4:0] concat=n=5:v=0:a=1 [a]" -map [a] tmp\99.mp3

这里生成的音频文件为“99元”,使用了5个音频文件,-i后面跟音频文件,然后是固定的“-filter_complex”方法命令,然后是“[0:0] [1:0] [2:0] [3:0] [4:0] ”音频集合,“concat=n=5”,5则是音频文件的数量,然后后面的“v=0:a=1 [a]" -map [a]”都是固定写法,然后是输出的目录“tmp99.mp3”,你只需生成这样的命令行然后执行它,就得到了拼接好的音频文件了。

我是将这样的命令行生成一个文本,然后Window去一行一行执行它即可,但是,效率低,因为这样生成出来的是单线程执行的,无法全速在电脑运行,因为IO读写导致CPU无法全力发挥效率,这里还需要生成多线程,也就是多个BAT来同时执行,这样效率就会上去了,它的命令如下

start "Thread 0" cmd /k call output0.bat
start "Thread 1" cmd /k call output1.bat
start "Thread 2" cmd /k call output2.bat
start "Thread 3" cmd /k call output3.bat
start "Thread 4" cmd /k call output4.bat

这些命令行,是开启了5个线程(应该说是进程?)执行多个BAT,来进行全力的音频处理,然后它的完全形式如下,假设使用5条进程,生成100条音频,那么先把这100条分成5等分,每份是20条,生成5个批处理文件,然后再生成一个开启bat批处理文件的文件,最终运行它,这里我使用的文件名如下

output0.bat
output1.bat
output2.bat
output3.bat
output4.bat
output_run.bat

最终运行“output_run.bat”文件运行即可。

三、音频文件的压缩
假设生成了10000条音频文件,我这里的大小是约400MB,把这400MB的音频文件全部打包进APP,不太现实,所以需要压缩它,采用何种压缩方式,何种格式呢,这里使用的是HE-AACv2,具体理由参考如下文章:
AAC规格(LC,HE,HEv2)及性能对比
FFMPEG默认编译好的window下文件无法编码HE-AACv2,因为确实编码器,需要自己去编译,这里太麻烦,我就没有使用FFMPEG去转换文件,这里使用替代品——“fdkaac.exe”,其内核和ffmpeg需要使用的编码器是一个,但是“fdkaac.exe”可以单独运行,就方便了不少,使用命令如下

fdkaac "99.wav" --ignorelength -S -b 1 --profile 29 -o "aac\99.m4a"

这里只有“-b 1”需要说明,其他都是固定格式,或者可自行参考fdkaac,“-b 1”是转换为1比特率的音频文件,为什么1,音损会不会很大,不会,因为此命令并不会强制转换为1比特率,只是去接近它,实际转换后的比特率大概是6-15比特率左右,音频还算可以听清说的是什么。这里使用的命令行只是转换一条,如何批量转换?使用命令行如下

for %%a in ("*.wav") do fdkaac "%%a" --ignorelength -S -b 1 --profile 29 -o "aac\%%~na.m4a"

将本目录下的wav转换为aac,其目录为音频文件下面的aac文件夹下面,这里就不赘述了,但是这是单进程单线程的,你可以去优化为多线程,已经有相关文章,可以去搜索到下。

最终,压缩完毕后会得到60-70MB的音频文件,打包进包里即可,但是不知道IOS是否允许,音频文件其实可以做出拓展包的形式另外下载,这些音频文件压缩后实际只有几MB,也可以考虑先压缩进包,再解压,如果IOS允许的话。


10000条已经合成好的音频文件(有小数点)
链接: https://pan.baidu.com/s/112cV64IwmIlts4eKQHBUsg 提取码: fdxc

10000条已经合成好的音频文件(无小数点后面)
链接: https://pan.baidu.com/s/1k5Z14Pay-P25-ecwaGxrKg 提取码: pws8

支付宝商家语音播报Android开源项目
https://github.com/YzyCoding/PushVoiceBroadcast