Android 实现云知声版离线语音合成

来自:网络
时间:2022-08-07
阅读:
目录

简介

科大讯飞:合成速度快,准确度高,模型多。但问题也是相当明显,只有在线合成是免费的,离线则是一笔不小的开销。

百度:是专门为他的导航做的一套,性能相对也还可以,但是他只支持离在线混合模式,默认是在wifi情况下是使用在线模式,4g或无网络情况下使用离线模式。

云知声:则可以实现完全的离线合成模式,相比于前两个,性能可能没那没完美,不过对合成的语音要求不高的应用来说,可以考虑接入,缺点就是模型比较少。

在线合成和离线合成(合成速度)

在线合成必须将数据传到第三方平台,调用他们的服务接口进行合成,这中间牵扯到网络状况,在网络良好的情况下,合成速度和离线模式没有太大的差别,但是有时候服务器也会来开个小差,无法保证网络一直都是畅通无阻的。在线模式虽然不太稳定,但是不需要把模型和合成底层代码放在本地,离线合成虽然稳定快速,但是apk体积增加的有点小夸张。

云知声的解决办法:把语音合成模型放在服务器后端,你要使用的时候下载到本地。

集成方法

注册云知声开发者,创建应用,下载离线语音合成sdk,里面就两个文件。

Android 实现云知声版离线语音合成

将这里面的所有东西都拷贝到你的项目的对应的libs下(比如app目录下的libs)

Android 实现云知声版离线语音合成

在app模块的 build.gradle的defaultConfig括号下加上

        ndk {
            abiFilters 'armeabi'
        }
        sourceSets {
            main {
                jniLibs.srcDirs = ['libs']
            }
        }

截图如下:

Android 实现云知声版离线语音合成

在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,比如模型文件放在不正确的地方会导致没有声音,模型文件不完整的时候回导致程序崩溃,发音不是预期的效果等等,还有一些参数的设置,具体参数还是得看官方的开发文档。

返回顶部
顶部