百度语音模块化集成

        最近在百度人工智能开放平台看到,百度的离在线语音已经免费了,小激动一下(毕竟之前跟科大一样,都是离线收费),然后写了一个小工具APP基本功能如下:

1.拦截通知栏消息(NotificationListenerService 

2.语音播放微信、QQ消息内容(可设置带着耳机的时候播放)

 

想法很简单,经常在跑步,中途不方便查看消息,这样的小工具就可以满足需求了,当然这篇文章主要是讲百度语音的快速集成,下面开始。

 

获取相关key

    登录百度开发者管理平台,注册一个APP获取到三个东东:APPID、APPKEY、SECRETKEY

开始集成

百度官网给的相关文档:百度官方文档

虽然写的不是很清楚,但相信聪明的你还是能集成进去[/斜眼笑]

项目里面我封装成了一个相对简单的类,方便在其他应用里面调用,下面看下代码:

package com.tommy.modelweb;

import android.content.Context;
import android.media.AudioManager;
import android.os.Environment;

import com.baidu.tts.auth.AuthInfo;
import com.baidu.tts.client.SpeechError;
import com.baidu.tts.client.SpeechSynthesizer;
import com.baidu.tts.client.SpeechSynthesizerListener;
import com.baidu.tts.client.TtsMode;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;


/**
 * Created by Tommy on 2017/3/15.
 */

public class BaiDuSpeechDao implements SpeechSynthesizerListener {

    private SpeechSynthesizer mSpeechSynthesizer;
    public String mSampleDirPath;
    private static final String SAMPLE_DIR_NAME = "baiduTTS";
    private static final String SPEECH_FEMALE_MODEL_NAME = "bd_etts_common_speech_m15_mand_eng_high_am-mix_v3.0.0_20170505.dat";
    private static final String SPEECH_MALE_MODEL_NAME = "bd_etts_common_speech_yyjw_mand_eng_high_am-mix_v3.0.0_20170512.dat";
    private static final String TEXT_MODEL_NAME = "bd_etts_text.dat";
    private static final String LICENSE_FILE_NAME = "temp_license";

    private static final String APIKEY = AppConfig.APIKEY;
    private static final String SECRETKEY = AppConfig.SECRETKEY;
    private static final String APPID = AppConfig.APPID;

    private AudioManager mAudioManager;     //音乐媒体管理

    public BaiDuSpeechDao(Context context){
        initialEnv(context);
        startTTS(context);
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    private void initialEnv(Context context) {
        if (mSampleDirPath == null) {
            String sdcardPath = Environment.getExternalStorageDirectory().toString();
            mSampleDirPath = sdcardPath + "/" + SAMPLE_DIR_NAME;
        }
        makeDir(mSampleDirPath);
        copyFromAssetsToSdcard(context,false, SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME);
        copyFromAssetsToSdcard(context,false, SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_MALE_MODEL_NAME);
        copyFromAssetsToSdcard(context,false, TEXT_MODEL_NAME, mSampleDirPath + "/" + TEXT_MODEL_NAME);
//        copyFromAssetsToSdcard(context,false, LICENSE_FILE_NAME, mSampleDirPath + "/" + LICENSE_FILE_NAME);
    }

    private void makeDir(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 将sample工程需要的资源文件拷贝到SD卡中使用(授权文件为临时授权文件,请注册正式授权)
     *
     * @param isCover 是否覆盖已存在的目标文件
     * @param source
     * @param dest
     */
    private void copyFromAssetsToSdcard(Context context, boolean isCover, String source, String dest) {
        File file = new File(dest);
        if (isCover || (!isCover && !file.exists())) {
            InputStream is = null;
            FileOutputStream fos = null;
            try {
                is = context.getAssets().open(source);
                String path = dest;
                fos = new FileOutputStream(path);
                byte[] buffer = new byte[1024];
                int size = 0;
                while ((size = is.read(buffer, 0, 1024)) >= 0) {
                    fos.write(buffer, 0, size);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    if (is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 初始化语音合成客户端并启动
    private void startTTS(Context context) {
        LogUtil.e("合成语音");
        // 获取语音合成对象实例
        mSpeechSynthesizer = SpeechSynthesizer.getInstance();
        // 设置context
        mSpeechSynthesizer.setContext(context);
        // 设置语音合成状态监听器
//        mSpeechSynthesizer.setSpeechSynthesizerListener(this);
        // 设置在线语音合成授权,需要填入从百度语音官网申请的api_key和secret_key
        mSpeechSynthesizer.setApiKey(APIKEY, SECRETKEY);
        // 设置离线语音合成授权,需要填入从百度语音官网申请的app_id
        mSpeechSynthesizer.setAppId(APPID);
        // 设置语音合成文本模型文件
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/"+ TEXT_MODEL_NAME);
        // 设置语音合成声音模型文件
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME);
        //设置发音的人: 0 普通女声(默认) 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "4");
        // 设置合成的音量,0-9 ,默认 5
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "9");
        // 设置合成的语速,0-9 ,默认 5
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "3");
        // 设置合成的语调,0-9 ,默认 5
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");
        // 设置语音合成声音授权文件
//        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_LICENCE_FILE, mSampleDirPath + "/" + LICENSE_FILE_NAME);
        // 获取语音合成授权信息
        AuthInfo authInfo = mSpeechSynthesizer.auth(TtsMode.MIX);
        // 判断授权信息是否正确,如果正确则初始化语音合成器并开始语音合成,如果失败则做错误处理
        if (authInfo.isSuccess()) {
            LogUtil.e("授权成功");
            mSpeechSynthesizer.initTts(TtsMode.MIX);  //离在线合成
            mSpeechSynthesizer.setStereoVolume(1.0f,1.0f);
//            mSpeechSynthesizer.speak("百度语音合成示例程序正在运行");
        } else {
            // 授权失败
            LogUtil.e("授权失败");
        }
    }
    //设置音量
    public void setVolume(float l,float r){
        mSpeechSynthesizer.setStereoVolume(l,r);
    }

    public void onError(String arg0, SpeechError arg1) {
        // 监听到出错,在此添加相关操作
        LogUtil.e("合成失败");
    }
    public void onSpeechFinish(String arg0) {
        // 监听到播放结束,在此添加相关操作
        LogUtil.e("合成结束");
    }
    public void onSpeechProgressChanged(String arg0, int arg1) {
        // 监听到播放进度有变化,在此添加相关操作
        LogUtil.e("合成播放进度变化");
    }
    public void onSpeechStart(String arg0) {
        // 监听到合成并播放开始,在此添加相关操作
        LogUtil.e("合成并播放开始");
    }
    public void onSynthesizeDataArrived(String arg0, byte[] arg1, int arg2) {
        // 监听到有合成数据到达,在此添加相关操作
        LogUtil.e("合成到达");
    }
    public void onSynthesizeFinish(String arg0) {
        // 监听到合成结束,在此添加相关操作
        LogUtil.e("合成结束");
    }
    public void onSynthesizeStart(String arg0) {
        // 监听到合成开始,在此添加相关操作
        LogUtil.e("合成开始");
    }
    /**
     * 说话
     * @param str
     */
    public void speak(String str){
        if (mSpeechSynthesizer!=null){
            //说好的时候把焦点获取过来,然后再播放,放完后再恢复其他声音
//            if (mAudioManager!=null){
//                mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
//            }
//            mSpeechSynthesizer.speak(str);
            if (mAudioManager!=null){
                //请求媒体焦点
                int result = mAudioManager.requestAudioFocus(audioFocusChangeListener,9,
                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
                //判断请求焦点是否成功
                if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED){
                    //请求成功,这里你就可以开始播放了  (比如这时候在拨打电话,那请求是不成功的)
                    mSpeechSynthesizer.speak(str);
                    releaseFocus();
                }
            }
        }
    }

    //设置服务监听
    private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            switch (focusChange) {
                //重新获取焦点
                case AudioManager.AUDIOFOCUS_GAIN:
                    //判断是否需要重新播放音乐
                    LogUtil.e("重新获得焦点");
                    break;
                //暂时失去焦点
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    //暂时失去焦点,暂停播放音乐(将needRestart设置为true)
                    LogUtil.e("暂时失去焦点");
                    break;
                //失去焦点
                case AudioManager.AUDIOFOCUS_LOSS:
                    //暂停播放音乐,不再继续播放
                    LogUtil.e("失去焦点");
                    mSpeechSynthesizer.stop();
                    break;
            }
        }
    };

    public void releaseFocus(){
        //取消注册音频竞争
        if (mAudioManager != null && audioFocusChangeListener != null) {
            LogUtil.e("主动释放焦点");
            mAudioManager.abandonAudioFocus(audioFocusChangeListener);
        }
    }
}

这个工具类贴进你项目中,然后在外面的调用是这样子滴:

  //语音播报
    private void speak(String text){
        if (baiDuSpeechDao!=null){
            baiDuSpeechDao.speak(text);
        }else {
            baiDuSpeechDao = new BaiDuSpeechDao(this);
            baiDuSpeechDao.speak(text);
        }
    }

OK!就这么简单,完事。

快速集成步骤

1.导入各种离线包,你懂的,贴到你项目OK?

2.把 BaiDuSpeechDao.java 这个文件贴过去

3.权限

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>

    <!-- 语音合成 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

 

4.调用一下,完事

 

//语音播报
    private void speak(String text){
        if (baiDuSpeechDao!=null){
            baiDuSpeechDao.speak(text);
        }else {
            baiDuSpeechDao = new BaiDuSpeechDao(this);
            baiDuSpeechDao.speak(text);
        }
    }

结束语

感谢你看到这里,到此百度语音就算集成完了。

对了,提醒下,demo里的 那些key 我写了//TODO:  请自行填补

完整Demo下载地址:下载地址

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s清风s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值