离开老师的指导有一段时间了,天天都会给本身找点事情作,或则简单的安排计划一下,收货很少很多刚恰好。
这是2017年的第一篇比较正式的博客,也算是我在CSDN上的第一次吧!哈哈。今天记录的是最近在集成百度语音上的一些步骤和小部分总结。最开始准备使用讯飞语音的,然而在下载集成后屡次测试都没有反应,感受是哪儿出现了问题,而且讯飞语音在语音唤醒上面也有限制,最后无心间发现了百度语音,就尝试着试试,固然目前只完成了语音合成部分,接下来固然会去玩玩语音识别和唤醒咯。java
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <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.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
到此,集成就结束了,接下来就是如何使用。固然能够参照BaiduTtsSample文件夹下的src里面的一个MainActvity的写法。也能够按照我下面的总结的工具类来直接使用,方便快捷省事。android
package com.bk120.mytest_autoanswer; import android.content.Context; import android.os.Environment; import com.baidu.tts.client.SpeechError; import com.baidu.tts.client.SpeechSynthesizer; import com.baidu.tts.client.SpeechSynthesizerListener; import com.baidu.tts.client.SynthesizerTool; 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 bk120 on 2017/1/3. * 语音合成工具类 */ public class VoiceUtils { //////////////////需配置部分//////////////////////// //AppId private String APPID="9156383"; //ApiKey private String APIKEY="BZQ1owOxjYzf0ADT1agq8SxU"; //SecretKey private String SECRETKEY="43b8a384182f2af0b935cf4ee9dce03f"; ////////////////////配置结束//////////////////////////////////// private SpeechSynthesizer mSpeechSynthesizer; private String mSampleDirPath; private static final String SAMPLE_DIR_NAME = "baiduTTS"; private static final String SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female.dat"; private static final String SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male.dat"; private static final String TEXT_MODEL_NAME = "bd_etts_text.dat"; private static final String LICENSE_FILE_NAME = "temp_license.txt"; private static final String ENGLISH_SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female_en.dat"; private static final String ENGLISH_SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male_en.dat"; private static final String ENGLISH_TEXT_MODEL_NAME = "bd_etts_text_en.dat"; //初始化 public void init(Context context,int speaker){ initialEnv(context); initialTts(context,speaker); } //获取解析器 public SpeechSynthesizer getSyntheszer(){ return mSpeechSynthesizer; } //初始化配置文件 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); copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME); copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/" + ENGLISH_SPEECH_MALE_MODEL_NAME); copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + "/" + ENGLISH_TEXT_MODEL_NAME); } private void makeDir(String dirPath) { File file = new File(dirPath); if (!file.exists()) { file.mkdirs(); } } /** * 将资源语音文件复制到手机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.getResources().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 initialTts(Context context,int speaker) { this.mSpeechSynthesizer = SpeechSynthesizer.getInstance(); this.mSpeechSynthesizer.setContext(context); this.mSpeechSynthesizer.setSpeechSynthesizerListener(new MyListnener()); // 文本模型文件路径 (离线引擎使用) this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/" + TEXT_MODEL_NAME); // 声学模型文件路径 (离线引擎使用) this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME); // 请替换为语音开发者平台上注册应用获得的App ID (离线受权) this.mSpeechSynthesizer.setAppId(APPID); // 请替换为语音开发者平台注册应用获得的apikey和secretkey (在线受权) this.mSpeechSynthesizer.setApiKey(APIKEY, SECRETKEY); // 发音人(在线引擎),可用参数为0,1,2,3。。。(服务器端会动态增长,各值含义参考文档,以文档说明为准。0--普通女声,4--情感女声,3--普通男声,6--特殊男声。。。) this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, speaker+""); // 设置Mix模式的合成策略 this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT); // 受权检测接口(只是经过AuthInfo进行检验受权是否成功。) // 初始化tts mSpeechSynthesizer.initTts(TtsMode.MIX); // 加载离线英文资源(提供离线英文合成功能) mSpeechSynthesizer.loadEnglishModel(mSampleDirPath + "/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + "/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME); } //合成监听器 class MyListnener implements SpeechSynthesizerListener{ @Override public void onSynthesizeStart(String s) { //合成准备工做 } @Override public void onSynthesizeDataArrived(String s, byte[] bytes, int i) { //合成数据和进度的回调接口,分屡次回调 } @Override public void onSynthesizeFinish(String s) { //合成正常结束,每句合成正常结束都会回调,若是过程当中出错,则回调onError,再也不回调此接口 } @Override public void onSpeechStart(String s) { //播放开始,每句播放开始都会回调 } @Override public void onSpeechProgressChanged(String s, int i) { //播放进度回调接口,分屡次回调 } @Override public void onSpeechFinish(String s) { // 播放正常结束,每句播放正常结束都会回调,若是过程当中出错,则回调onError,再也不回调此接口 } @Override public void onError(String s, SpeechError speechError) { //当合成或者播放过程当中出错时回调此接口 } } }
该工具类我就很少解释了,惟一须要配置的地方在前面获取到的AppId,ApiKey和SecretKey直接替换成你本身的就能够了。该工具类作的事就是第一步将因为资源文件及Asserts下面的文件复制到SD卡上,而后初始化一个语音合成器SpeechSynthesizer。并提供放回的方法getSyntheszer供外部使用。合成监听器SpeechSynthesizerListener能处理各个阶段的事件。固然这个工具类很差,存在构造器还须要传入参数,有待改进,int speaker 为发声人,从0到7均可以使用,男声,女声,本身能够试着玩玩。api
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#7EBF4B" tools:context="com.bk120.mytest_autoanswer.MainActivity"> <EditText android:layout_height="120dp" android:layout_width="match_parent" android:hint="输入:" android:layout_marginTop="10dp" android:id="@+id/mainactivity_et" android:paddingLeft="10dp" android:background="@drawable/et_shape" /> <LinearLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="horizontal" android:layout_marginTop="10dp" > <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:onClick="puTongWoman" android:layout_weight="1" android:text="普通女声" android:textSize="15sp" android:textColor="#71A7C7" android:background="@drawable/btn_shape" /> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:onClick="qingGanWoman" android:layout_weight="1" android:text="情感女声" android:textSize="15sp" android:textColor="#71A7C7" android:background="@drawable/btn_shape" /> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:onClick="puTongMan" android:layout_weight="1" android:textSize="15sp" android:textColor="#71A7C7" android:text="普通男声" android:background="@drawable/btn_shape" /> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:onClick="qingGanMan" android:layout_weight="1" android:textSize="15sp" android:textColor="#71A7C7" android:text="情感男声" android:background="@drawable/btn_shape" /> </LinearLayout> </LinearLayout>
2.Activity中直接获取EditText对象并处理点击事件,以下:
MainActivity中:缓存
–
package com.bk120.mytest_autoanswer;服务器
import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.Toast; import com.baidu.tts.client.SpeechSynthesizer; public class MainActivity extends Activity { private EditText mInput; private SpeechSynthesizer mSpeechSynthesizer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mInput= (EditText) this.findViewById(R.id.mainactivity_et); } //普通女声 public void puTongWoman(View view){ speak(0); } //特殊女声 public void qingGanWoman(View view){ speak(4); } //普通男声 public void puTongMan(View view){ speak(3); } //特殊男声 public void qingGanMan(View view){ speak(6); } private void speak(int speaker) { //如果每次都这样是否是会有内存问题呢?须要思考改进 VoiceUtils utils=new VoiceUtils(); utils.init(this,speaker); mSpeechSynthesizer=utils.getSyntheszer(); String text = this.mInput.getText().toString(); //须要合成的文本text的长度不能超过1024个GBK字节。 if (TextUtils.isEmpty(mInput.getText())) { text = "你好!"; mInput.setText(text); } this.mSpeechSynthesizer.speak(text); } //释放缓存 @Override protected void onDestroy() { this.mSpeechSynthesizer.release(); super.onDestroy(); } }
经过上面的步骤语音合成就算完事了,在没有网络链接的状况下默认speaker为0–普通女声,即点击全部按钮都是普通女声朗读出文本框中的文字,英文中文均可以,网络状态下其余按钮才能发出不一样的声音。
网络
结果就是这样,点击按钮就能听见朗读声音咯。图中的按钮和输入框shape文件以下,文件名分别为btn_shape和et_shape,都放在res下的drawable文件夹中,适可参考Ctrl+C吧!
btn_shape:app
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:color="#8BE5E8" android:width="1dp"/> <corners android:radius="5dp"/> <solid android:color="#C46F5F"/> </shape>
et_shape:eclipse
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:color="#facd89" android:width="5dp"/> <corners android:radius="8dp"/> </shape>
第一次写这个东东,是否是太详细了居然写了老久了,这打字速度有点坑啊,还要多锻炼!ide