集成Android免费语音合成功能(在线、离线、离在线融合),有这一篇文章就够了(离线)

集成Android免费语音合成功能(在线、离线、离在线融合),有这一篇文章就够了(离在线融合)




那么为什么要分3篇文章来讲呢?看标题也能猜到了,就是在线、离线、离在线融合这3种语音合成方式,我将分别使用科大讯飞、云知声、百度语音来实现Android的语音合成。至于有什么优缺点,大家可以自行百度,这里就不再赘言了,好吧,不说废话了,我怕有人会打我,哈哈~

首先,这一篇先写用科大讯飞实现的在线语音合成吧,是免费的,它的离线是要钱的,有需求的可以自己到它们官网去看看。

打开讯飞开放平台


离线免费 语音合成 java 语音合成离线版_android


注册、登录开发者账号


离线免费 语音合成 java 语音合成离线版_语音合成_02


离线免费 语音合成 java 语音合成离线版_android_03

进入控制台,创建新应用

离线免费 语音合成 java 语音合成离线版_android_04

开通在线语音合成服务

离线免费 语音合成 java 语音合成离线版_免费_05

离线免费 语音合成 java 语音合成离线版_在线_06

下载SDK

离线免费 语音合成 java 语音合成离线版_语音合成_07

离线免费 语音合成 java 语音合成离线版_在线_08

下载完SDK后,解压压缩包sample-->SpeechDemo

离线免费 语音合成 java 语音合成离线版_android_09

离线免费 语音合成 java 语音合成离线版_android_10

打开SpeechDemo-->libs文件夹,复制jar包和.so文件到你的项目里面,然后sync一下

离线免费 语音合成 java 语音合成离线版_免费_11

离线免费 语音合成 java 语音合成离线版_离线免费 语音合成 java_12

做完以上准备工作,就可以开始撸代码了

    首先,AndroidManifest.xml申请权限(6.0需要动态申请权限,碍于篇幅,请自行百度)


<uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    然后,新建MyApplication.java文件,初始化语音合成SDK,APPID可在讯飞平台-->我的应用查看,也可查看下载的SDK压缩包名字后缀

离线免费 语音合成 java 语音合成离线版_android_13

离线免费 语音合成 java 语音合成离线版_android_14



package com.cyf.ttsdemo;

import android.app.Application;

import com.iflytek.cloud.SpeechUtility;

/**
 * Created by As on 2017/8/7.
 */

public class MyApplication extends Application{

    @Override
    public void onCreate() {
        super.onCreate();
        SpeechUtility.createUtility(this, "appid=5987d170");
    }
}

    最后记得在AndroidManifest.xml注册该Application

离线免费 语音合成 java 语音合成离线版_离线免费 语音合成 java_15



    为了可以全局调用语音合成功能,我封装成了一个工具类,大家可以直接复制过去用


package com.cyf.ttsdemo.utils;

import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

import com.cyf.ttsdemo.MyApplication;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;

/**
 * Created by As on 2017/8/7.
 */

public class TTSUtils implements InitListener, SynthesizerListener {

    private static final String TAG = "TTSUtils";
    private static volatile TTSUtils instance = null;
    private boolean isInitSuccess = false;
    private SpeechSynthesizer mTts;

    private TTSUtils() {
    }

    public static TTSUtils getInstance() {
        if (instance == null) {
            synchronized (TTSUtils.class) {
                if (instance == null) {
                    instance = new TTSUtils();
                }
            }
        }
        return instance;
    }

    public void init() {
        // 初始化合成对象
        mTts = SpeechSynthesizer.createSynthesizer(MyApplication.getContext(), this);
        // 清空参数
        mTts.setParameter(SpeechConstant.PARAMS, null);
        // 设置在线合成引擎
        mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
        // 设置在线合成发音人
        mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");
        // 设置合成语速
        mTts.setParameter(SpeechConstant.SPEED, "50");
        // 设置合成音调
        mTts.setParameter(SpeechConstant.PITCH, "50");
        // 设置合成音量
        mTts.setParameter(SpeechConstant.VOLUME, "50");
        // 设置播放器音频流类型
        mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");
        // 设置播放合成音频打断音乐播放,默认为true
        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
        mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/tts.wav");
    }

    public void speak(String msg) {
        if (isInitSuccess){
            if (mTts.isSpeaking()) {
                stop();
            }
            mTts.startSpeaking(msg, this);
        }else {
            init();
        }
    }

    public void pause() {
        mTts.pauseSpeaking();
    }

    public void resume() {
        mTts.resumeSpeaking();
    }

    public void stop() {
        mTts.stopSpeaking();
    }

    public void release() {
        if (null != mTts) {
            mTts.stopSpeaking();
            // 退出时释放连接
            mTts.destroy();
        }
    }

    @Override
    public void onInit(int code) {
        Log.d(TAG, "InitListener init() code = " + code);
        if (code == ErrorCode.SUCCESS) {
            isInitSuccess = true;
        }
    }

    @Override
    public void onSpeakBegin() {
        // 开始播放
    }

    @Override
    public void onBufferProgress(int percent, int beginPos, int endPos,
                                 String info) {
        // 合成进度
    }

    @Override
    public void onSpeakPaused() {
        // 暂停播放
    }

    @Override
    public void onSpeakResumed() {
        // 继续播放
    }

    @Override
    public void onSpeakProgress(int percent, int beginPos, int endPos) {
        // 播放进度
    }

    @Override
    public void onCompleted(SpeechError speechError) {
        if (speechError != null) {
            Log.d(TAG, "onCompleted: " + speechError.getPlainDescription(true));
        }
    }

    @Override
    public void onEvent(int eventType, int i1, int i2, Bundle bundle) {
        //以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
        if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            String sid = bundle.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            Log.d(TAG, "session id =" + sid);
        }
    }
}


要使用这个工具类,那么就要改造一下前面的MyApplication.java文件了


package com.cyf.ttsdemo;

import android.app.Application;
import android.content.Context;

import com.cyf.ttsdemo.utils.TTSUtils;
import com.iflytek.cloud.Setting;
import com.iflytek.cloud.SpeechUtility;

/**
 * Created by As on 2017/8/7.
 */

public class MyApplication extends Application {

    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        SpeechUtility.createUtility(this, "appid=5987d170");
        // 以下语句用于设置日志开关(默认开启),设置成false时关闭语音云SDK日志打印
        Setting.setShowLog(false);
        TTSUtils.getInstance().init();
    }

    public static Context getContext() {
        return context;
    }
}

    好的,这样就大功告成了,在需要进行语音合成的地方调用TTSUtils.getInstance().speak("xxx")即可

离线免费 语音合成 java 语音合成离线版_语音合成_16

    最后,我们需要到讯飞开放平台进行上传应用审核,不然使用的语音合成功能每天是有次数限制的。

离线免费 语音合成 java 语音合成离线版_离线免费 语音合成 java_17

离线免费 语音合成 java 语音合成离线版_在线_18

离线免费 语音合成 java 语音合成离线版_语音合成_19

    当应用审核通过之后,就可以免费无限制的使用在线语音合成功能啦。