目录
简介
科大讯飞:合成速度快,准确度高,模型多。但问题也是相当明显,只有在线合成是免费的,离线则是一笔不小的开销。
百度:是专门为他的导航做的一套,性能相对也还可以,但是他只支持离在线混合模式,默认是在wifi情况下是使用在线模式,4g或无网络情况下使用离线模式。
云知声:则可以实现完全的离线合成模式,相比于前两个,性能可能没那没完美,不过对合成的语音要求不高的应用来说,可以考虑接入,缺点就是模型比较少。
在线合成和离线合成(合成速度)
在线合成必须将数据传到第三方平台,调用他们的服务接口进行合成,这中间牵扯到网络状况,在网络良好的情况下,合成速度和离线模式没有太大的差别,但是有时候服务器也会来开个小差,无法保证网络一直都是畅通无阻的。在线模式虽然不太稳定,但是不需要把模型和合成底层代码放在本地,离线合成虽然稳定快速,但是apk体积增加的有点小夸张。
云知声的解决办法:把语音合成模型放在服务器后端,你要使用的时候下载到本地。
集成方法
注册云知声开发者,创建应用,下载离线语音合成sdk,里面就两个文件。
将这里面的所有东西都拷贝到你的项目的对应的libs下(比如app目录下的libs)
在app模块的 build.gradle的defaultConfig括号下加上
ndk { abiFilters 'armeabi' } sourceSets { main { jniLibs.srcDirs = ['libs'] } }
截图如下:
在AndroidManifest.xml设置所需要的权限
<!-- 网络权限 --> <uses-permission android:name="android.permission.INTERNET"/> <!-- sd卡获得写的权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 获取网络状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 获取WiFi状态 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!-- 改变网络状态 --> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> <!-- 改变WiFi状态 --> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <!--唤醒锁定--> <uses-permission android:name="android.permission.WAKE_LOCK"/> <!--清除应用缓存--> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <!--麦克风权限组--> <uses-permission android:name="android.permission.READ_CALENDAR"/> <!-- 允许应用写(非读)用户的外部存储器 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!--允许读取电话的状态--> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!--允许应用读取用户的联系人数据--> <uses-permission android:name="android.permission.READ_CONTACTS"/> <!--允许使用电源锁定管理以使进程休眠或屏幕变暗--> <uses-permission android:name="android.permission.WAKE_LOCK" />
为了方便使用我这里将云知声语音合成做了进一步的封装,以方便调用,以下是示例,方便大家进行参考
import android.content.Context; import android.media.AudioManager; import android.util.Log; import cn.yunzhisheng.tts.offline.TTSPlayerListener; import cn.yunzhisheng.tts.offline.basic.ITTSControl; import cn.yunzhisheng.tts.offline.basic.TTSFactory; import cn.yunzhisheng.tts.offline.common.USCError; /** * 云知声离线语音封装类 */ public class SpeechUtilOffline implements TTSPlayerListener { public static final String TAG ="SpeechUtilOffline"; public static final String appKey = "_appKey_"; private ITTSControl ittsControl; private Context context; public SpeechUtilOffline(Context context) { this.context = context; init(); } /** * 初始化引擎 */ private void init() { // 初始化语音合成对象 ittsControl = TTSFactory.createTTSControl(context, appKey); // 设置回调监听 ittsControl.setTTSListener(this); // 设置音频流 ittsControl.setStreamType(AudioManager.STREAM_MUSIC); // 设置播报语速,播报语速,数值范围 0.1~2.5 默认为 1.0 ittsControl.setVoiceSpeed(2.5f); // 设置播报音高,调节音高,数值范围 0.9~1.1 默认为 1.0 ittsControl.setVoicePitch(1.1f); // 初始化合成引擎 ittsControl.init(); } /** * 停止播放 */ public void stop(){ ittsControl.stop(); } /** * 播放 */ public void play(String content) { ittsControl.play(content); } /** * 开始缓冲回调 */ @Override public void onBuffer() { Log.i(TAG, "onBuffer"); } /** * 开始播放回调 */ @Override public void onPlayBegin() { Log.i(TAG, "onPlayBegin"); } /** * 取消播放回调 */ @Override public void onCancel() { Log.i(TAG, "onCancel"); } /** * 语音合成错误回调 */ @Override public void onError(USCError uscError) { Log.i(TAG, "onError"); } /** * 播放完成回调 */ @Override public void onPlayEnd() { Log.i(TAG, "onPlayEnd"); ittsControl.stop(); } /** * 初始化成功回调 */ @Override public void onInitFinish() { Log.i(TAG, "onInitFinish"); } }
使用方法
SpeechUtilOffline speechUtilOffline = new SpeechUtilOffline(this); speechUtilOffline.play("此处是需要播放的文本内容")
总结
在集成的时候遇到过很多bug,比如模型文件放在不正确的地方会导致没有声音,模型文件不完整的时候回导致程序崩溃,发音不是预期的效果等等,还有一些参数的设置,具体参数还是得看官方的开发文档。