一個(gè)android懸浮窗的語(yǔ)音識(shí)別demo

帶有android懸浮窗的語(yǔ)音識(shí)別語(yǔ)義理解demo

轉(zhuǎn)載請(qǐng)注明CSDN博文地址:http://blog.csdn.net/ls0609/article/details/77162417

在線聽書demo:http://blog.csdn.net/ls0609/article/details/71519203

語(yǔ)音記賬demo:http://blog.csdn.net/ls0609/article/details/72765789

Android桌面懸浮窗實(shí)現(xiàn)比較簡(jiǎn)單萍诱,本篇以一個(gè)語(yǔ)音識(shí)別悬嗓,語(yǔ)義理解的demo來(lái)演示如何實(shí)現(xiàn)android懸浮窗。

1.懸浮窗效果

桌面上待機(jī)的時(shí)候裕坊,懸浮窗吸附在邊上


拖動(dòng)遠(yuǎn)離屏幕邊緣時(shí)圖標(biāo)變大包竹,松開自動(dòng)跑到屏幕邊緣,距離屏幕左右邊緣靠近哪邊吸附哪邊


點(diǎn)擊懸浮圖標(biāo)時(shí)籍凝,啟動(dòng)錄音


說(shuō)完后可以點(diǎn)擊左button周瞎,上傳錄音給服務(wù)器等待處理返回結(jié)果


服務(wù)器返回結(jié)果后自動(dòng)跳轉(zhuǎn)到應(yīng)用界面,本例用的是在線聽書饵蒂,跳轉(zhuǎn)到在線聽書的界面


2.FloatViewIdle與FloatViewIdleService

1.FloatViewIdle

定義一個(gè)FloatViewIdle類声诸,如下是該類的單例模式

publicstaticsynchronizedFloatViewIdlegetInstance(Context context)

{

if(floatViewManager ==null)

{

mContext =context.getApplicationContext();;

winManager = (WindowManager)

mContext.getSystemService(Context.WINDOW_SERVICE);

displayWidth =winManager.getDefaultDisplay().getWidth();

displayHeight =winManager.getDefaultDisplay().getHeight();

floatViewManager =newFloatViewIdle();

}

returnfloatViewManager;

}

利用winManager的addview方法,把自定義的floatview添加到屏幕中退盯,那么就會(huì)在任何界面顯示該floatview彼乌,然后再屏蔽非待機(jī)界面隱藏floatview,這樣就只有待機(jī)顯示懸浮窗了渊迁。

定義兩個(gè)自定義view慰照,分別是FloatIconView和FloatRecordView,前者就是待機(jī)看到的小icon圖標(biāo)宫纬,后者是點(diǎn)擊這個(gè)icon圖標(biāo)后展示的錄音的那個(gè)界面焚挠。

下面來(lái)看下怎么定義的FloatIconView

classFloatIconView extends LinearLayout{

privateintmWidth;

privateintmHeight;

privateintpreX;

privateintpreY;

privateintx;

privateinty;

publicboolean isMove;

publicboolean isMoveToEdge;

privateFloatViewIdle manager;

publicImageView imgv_icon_left;

publicImageView imgv_icon_center;

publicImageView imgv_icon_right;

publicintmWidthSide;

publicFloatIconView(Context context) {

super(context);

View view = LayoutInflater.from(mContext).

inflate(R.layout.layout_floatview_icon,this);

LinearLayout layout_content =

(LinearLayout)view.findViewById(R.id.layout_content);

imgv_icon_left = (ImageView)view.findViewById(R.id.imgv_icon_left);

imgv_icon_center = (ImageView)view.findViewById(R.id.imgv_icon_center);

imgv_icon_right = (ImageView)view.findViewById(R.id.imgv_icon_right);

imgv_icon_left.setVisibility(View.GONE);

imgv_icon_center.setVisibility(View.GONE);

mWidth = layout_content.getWidth();

mHeight =layout_content.getHeight();

if((mWidth ==0)||(mHeight ==0))

{

inttemp = DensityUtil.dip2px(mContext,icon_width);

mHeight = temp;

icon_width_side_temp =DensityUtil.dip2px(mContext, icon_width_side);

mWidth = icon_width_side_temp;

}

manager =FloatViewIdle.getInstance(mContext);

if(params!=null)

{

params.x = displayWidth -icon_width_side_temp;

params.y = displayHeight/2;

}

}

publicintgetFloatViewWidth()

{

returnmWidth;

}

publicintgetFloatViewHeight()

{

returnmHeight;

}

@Override

publicboolean onTouchEvent(MotionEventevent)

{

switch(event.getAction())

{

caseMotionEvent.ACTION_DOWN:

preX = (int)event.getRawX();

preY = (int)event.getRawY();

isMove =false;

if(params.width == icon_width_side_temp)

handler.sendMessage(handler.obtainMessage(

MSG_UPDATE_FLOAT_VIEW_AFTER_CHANGED,3,0));

break;

caseMotionEvent.ACTION_UP:

if(isMoveToEdge ==true)

{

if(params.width == icon_width_side_temp)

handler.sendMessage(handler.obtainMessage(

MSG_UPDATE_FLOAT_VIEW_AFTER_CHANGED,3,0));

handler.sendMessage(handler.obtainMessage(

MSG_FLOAT_VIEW_MOVE_TO_EDGE,this));

}

break;

caseMotionEvent.ACTION_MOVE:

x = (int)event.getRawX();

y = (int)event.getRawY();

if(Math.abs(x-preX)>1||Math.abs(y-preY)>1)

{

isMoveToEdge =true;

}

if(Math.abs(x-preX)>5||Math.abs(y-preY)>5)

isMove =true;

if(params.width == icon_width_side_temp)

handler.sendMessage(handler.obtainMessage(

MSG_UPDATE_FLOAT_VIEW_AFTER_CHANGED,3,0));

manager.move(this, x-preX,y-preY);

preX = x;

preY = y;

break;

}

returnsuper.onTouchEvent(event);

}

}

通過(guò)layout文件生成一個(gè)FloatIconView,在onTouchEvent函數(shù)中當(dāng)按下的時(shí)候漓骚,發(fā)送消息更新懸浮view,抬起即up事件時(shí)先更新懸浮view榛泛,然后再顯示吸附到邊上的動(dòng)畫蝌蹂。當(dāng)move的時(shí)候,判斷每次位移至少5和像素則更新view位置曹锨,這樣不斷move不斷更新就會(huì)形成連續(xù)的畫面孤个。

另一個(gè)FloatRecordView(錄音的懸浮窗)道理相同,這里就不貼代碼了沛简,有興趣可以下載demo自己編譯跑一下齐鲤。

在FloatIconView中定義一個(gè)handler斥废,用于接收消息處理懸浮窗更新位置和吸附的動(dòng)畫

privatevoidinitHandler(){

handler =newHandler(){

@Override

publicvoidhandleMessage(Message msg)

{

switch(msg.what)

{

caseMSG_REFRESH_VOLUME:

if(floatRecordView

!=null)

floatRecordView.updateVolume((int)msg.arg1);

break;

caseMSG_FLOAT_VIEW_MOVE_TO_EDGE:

//更新懸浮窗位置的動(dòng)畫

moveAnimation((View)msg.obj);

break;

caseMSG_REMOVE_FLOAT_VIEW:

if(msg.arg1 ==1)

{//此時(shí)已有floatview是floatIconView

if(floatIconView

!=null)

{//先移除一個(gè)floatview

winManager.removeView(floatIconView);

floatIconView =null;

floatRecordView= getFloatRecordView();

if(floatRecordView

!=null)

{

if(floatRecordView.getParent()

==null)

{//再加入一個(gè)新的floatview

winManager.addView(floatRecordView,params);

floatViewType =FLOAT_RECORD_VIEW_TYPE;

}

if(mHandler !=null)

{

mHandler.sendMessage(mHandler.obtainMessage(

MessageConst.CLIENT_ACTION_START_CAPTURE));

IS_RECORD_FROM_FLOAT_VIEW_IDLE =true;

}

}

}

}

else

{//此時(shí)已有floatview是floatRecordView即錄音的floatview

if(floatRecordView

!=null)

{//先移除一個(gè)floatview

winManager.removeView(floatRecordView);

floatRecordView=null;

}

floatIconView =getFloatIconView();

if(floatIconView

!=null)

{

if(floatIconView.getParent()

==null)

{/再加入一個(gè)新的floatview

winManager.addView(floatIconView,params);

floatViewType =FLOAT_ICON_VIEW_TYPE;

setViewOnClickListener(floatIconView);

}

//可能需要有吸附動(dòng)畫

moveAnimation(floatIconView);

}

}

break;

caseMSG_UPDATE_VIEW_SENDING_TO_SERVER:

if(floatRecordView

!=null)

{

floatRecordView.updateSendingToServerView();

floatRecordView.setTitle("努力識(shí)別中");

}

break;

caseMSG_UPDATE_ROTATE_VIEW:

if(floatRecordView

!=null)

{

floatRecordView.rotateview.startRotate();

}

break;

caseMSG_UPDATE_FLOAT_VIEW_AFTER_CHANGED:

//1,2是吸附到左邊還是右邊给郊,3是拖動(dòng)到中間顯示放大的懸浮窗icon

if(msg.arg1 ==1)

changeFloatIconToSide(false);

elseif(msg.arg1 ==2)

changeFloatIconToSide(true);

elseif(msg.arg1 ==3)

changeFloatIconToNormal();

break;

caseMSG_UPDATE_FLOAT_VIEW_ON_SIDE:

if(msg.arg1 ==1)

updateFloatIconOnSide(true);

elseif(msg.arg1 ==2)

updateFloatIconOnSide(false);

break;

caseMSG_START_ACTIVITY:

hide();

Intent intent =newIntent(mContext,MusicActivity.class);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.putExtra(START_FROM_FLOAT_VIEW,true);

IS_START_FROM_FLOAT_VIEW_IDLE =true;

mContext.startActivity(intent);

break;

}

}

};

}

那么牡肉,怎樣做到點(diǎn)擊吸附屏幕邊緣的懸浮按鈕,切換成錄音的懸浮窗呢淆九?

publicvoidshow()

{

isHide =false;

floatIconView = getFloatIconView();

if(floatIconView !=null)

{

if(floatIconView.getParent() ==null)

{

winManager.addView(floatIconView,params);

floatViewType =FLOAT_ICON_VIEW_TYPE;

}

if(floatRecordView !=null)

{

handler.sendMessage(handler.obtainMessage(

MSG_REMOVE_FLOAT_VIEW,2,0));

}

floatIconView.setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(View v) {

if(floatIconView.isMove ||floatIconView.isMoveToEdge)

{

floatIconView.isMove =false;

return;

}

winManager.removeView(floatIconView);

floatIconView =null;

floatRecordView =getFloatRecordView();

if(floatRecordView !=null)

{

if(floatRecordView.getParent()

==null)

{

winManager.addView(floatRecordView,params);

floatViewType =FLOAT_RECORD_VIEW_TYPE;

}

if(mHandler !=null)

{

mHandler.sendMessage(mHandler.obtainMessage(

MessageConst.CLIENT_ACTION_START_CAPTURE));

IS_RECORD_FROM_FLOAT_VIEW_IDLE =true;

}

}

}

});

}

}

在show函數(shù)中统锤,設(shè)置了floatIconView的點(diǎn)擊事件,移除小的懸浮吸附按鈕炭庙,加入錄音的懸浮窗view并啟動(dòng)錄音饲窿。

2.FloatViewIdleService

為什么要定義這個(gè)service?

這個(gè)service用途是焕蹄,定時(shí)掃描是否在待機(jī)桌面逾雄,如果是待機(jī)桌面則顯示floatview,否則隱藏腻脏。

publicclassFloatViewIdleServiceextendsService{

privatestaticHandler mHandler;

privateFloatViewIdle floatViewIdle;

privatefinalstaticintREFRESH_FLOAT_VIEW =1;

privatebooleanis_vertical =true;

@Override

publicvoidonCreate() {

super.onCreate();

initHandler();

}

@Override

publicintonStartCommand(Intent intent,intflags,intstartId) {

mHandler.sendMessageDelayed(mHandler.obtainMessage(REFRESH_FLOAT_VIEW),500);

FloatViewIdle.IS_START_FROM_FLOAT_VIEW_IDLE =false;

is_vertical =true;

returnSTART_STICKY;

}

protectedvoidinitHandler() {

mHandler =newHandler() {

@Override

publicvoidhandleMessage(Message msg) {

switch(msg.what) {

caseREFRESH_FLOAT_VIEW://1s發(fā)送一次更新floatview消息

updateFloatView();

mHandler.sendMessageDelayed(

mHandler.obtainMessage(REFRESH_FLOAT_VIEW),1000);

break;

}

}

};

}

privatevoidupdateFloatView()

{

booleanisOnIdle = isHome();//判斷是否在待機(jī)界面

floatViewIdle =FloatViewIdle.getInstance(FloatViewIdleService.this);

if(isOnIdle)

{//待機(jī)界面則顯示floatview

if(floatViewIdle.getFloatViewType() ==0)

{

floatViewIdle.show();

}

elseif(floatViewIdle.getFloatViewType() ==

floatViewIdle.FLOAT_ICON_VIEW_TYPE||

floatViewIdle.getFloatViewType() ==

floatViewIdle.FLOAT_RECORD_VIEW_TYPE)

{

if(this.getResources().getConfiguration().orientation==

Configuration.ORIENTATION_LANDSCAPE)

{

if(is_vertical ==true)

{

floatViewIdle.swapWidthAndHeight();

is_vertical =false;

}

}

elseif(this.getResources().getConfiguration().orientation==

Configuration.ORIENTATION_PORTRAIT)

{

if(is_vertical ==false)

{

floatViewIdle.swapWidthAndHeight();

is_vertical =true;

}

}

}

}

else

{//否則隱藏floatview

floatViewIdle.hide();

}

}

privatebooleanisHome()

{

ActivityManager mActivityManager =(ActivityManager)

getSystemService(Context.ACTIVITY_SERVICE);

List rti =mActivityManager.getRunningTasks(1);

try{

if(rti.size() ==0)

{

returntrue;

}else

{

if(rti.get(0).topActivity.getPackageName().

equals("com.olami.floatviewdemo"))

returnfalse;

else

returngetHomes().contains(rti.get(0).topActivity.getPackageName());

}

}

catch(Exception e)

{

returntrue;

}

}

privateList getHomes()

{

List names =newArrayList();

PackageManager packageManager =this.getPackageManager();

Intent intent =newIntent(Intent.ACTION_MAIN);

intent.addCategory(Intent.CATEGORY_HOME);

List resolveInfo =packageManager.queryIntentActivities(intent,

PackageManager.MATCH_DEFAULT_ONLY);

for(ResolveInfo ri : resolveInfo) {

names.add(ri.activityInfo.packageName);

}

returnnames;

}

@Override

publicvoidonDestroy() {

super.onDestroy();

if(floatViewIdle !=null)

floatViewIdle.setFloatViewType(0);

}

@Override

publicIBinder onBind(Intent intent) {

returnnull;

}

}

3.啟動(dòng)語(yǔ)音識(shí)別

在另一個(gè)VoiceSdkService(另一個(gè)處理錄音服務(wù)業(yè)務(wù)的service)中鸦泳,當(dāng)接收到懸浮窗按鈕點(diǎn)擊事件消息時(shí),則啟動(dòng)錄音服務(wù)迹卢,錄音結(jié)束后會(huì)在onResult回調(diào)中收到服務(wù)器返回的結(jié)果辽故。

本例用的是olami語(yǔ)音識(shí)別,語(yǔ)義理解引擎腐碱,olami支持強(qiáng)大的用戶自定義語(yǔ)義誊垢,能更好的解決語(yǔ)義理解。

比如同義理解的時(shí)候症见,我要聽三國(guó)演義喂走,我想聽三國(guó)演義,聽三國(guó)演義這本書谋作,類似的說(shuō)法有很多芋肠,olmai就可以為你解決這類的語(yǔ)義理解,olami語(yǔ)音識(shí)別引擎使用比較簡(jiǎn)單遵蚜,只需要簡(jiǎn)單的初始化帖池,然后設(shè)置好回調(diào)listener,在回調(diào)的時(shí)候處理服務(wù)器返回的json字符串即可吭净,當(dāng)然語(yǔ)義還是要用戶自己定義的睡汹。

publicvoidinit()

{

initHandler();

mOlamiVoiceRecognizer =newOlamiVoiceRecognizer(VoiceSdkService.this);

TelephonyManagertelephonyManager=(TelephonyManager)this.getSystemService(

(this.getBaseContext().TELEPHONY_SERVICE);

String imei=telephonyManager.getDeviceId();

mOlamiVoiceRecognizer.init(imei);//設(shè)置身份標(biāo)識(shí),可以填null

mOlamiVoiceRecognizer.setListener(mOlamiVoiceRecognizerListener);//設(shè)置識(shí)別結(jié)果回調(diào)listener

mOlamiVoiceRecognizer.setLocalization(

OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE);//設(shè)置支持的語(yǔ)音類型寂殉,優(yōu)先選擇中文簡(jiǎn)體

mOlamiVoiceRecognizer.setAuthorization("51a4bb56ba954655a4fc834bfdc46af1",

"asr","68bff251789b426896e70e888f919a6d","nli");

//注冊(cè)Appkey囚巴,在olami官網(wǎng)注冊(cè)應(yīng)用后生成的appkey

//注冊(cè)api,請(qǐng)直接填寫“asr”,標(biāo)識(shí)語(yǔ)音識(shí)別類型

//注冊(cè)secret彤叉,在olami官網(wǎng)注冊(cè)應(yīng)用后生成的secret

//注冊(cè)seq庶柿,請(qǐng)?zhí)顚憽皀li”

mOlamiVoiceRecognizer.setVADTailTimeout(2000);//錄音時(shí)尾音結(jié)束時(shí)間,建議填//2000ms

//設(shè)置經(jīng)緯度信息秽浇,不愿上傳位置信息浮庐,可以填0

mOlamiVoiceRecognizer.setLatitudeAndLongitude(31.155364678184498,121.34882432933009);

在VoiceSdkService中定義OlamiVoiceRecognizerListener用于處理錄音時(shí)的回調(diào)

onError(int errCode)//出錯(cuò)回調(diào),可以對(duì)比官方文檔錯(cuò)誤碼看是什么錯(cuò)誤

onEndOfSpeech()//錄音結(jié)束

onBeginningOfSpeech()//錄音開始

onResult(String result, int type)//result是識(shí)別結(jié)果JSON字符串

onCancel()//取消識(shí)別兼呵,不會(huì)再返回識(shí)別結(jié)果

onUpdateVolume(int volume)//錄音時(shí)的音量兔辅,1-12個(gè)級(jí)別大小音量

本文用的是在線聽書的例子,當(dāng)收到服務(wù)器返回的消息是击喂,進(jìn)入如下函數(shù):

在下面的函數(shù)中维苔,通過(guò)解析服務(wù)器返回的json字符串,提取用戶需要的語(yǔ)義理解字段進(jìn)行處理

privatevoidprocessServiceMessage(Stringmessage)

{

Stringinput=null;

StringserverMessage=null;

try{

JSONObject jsonObject=newJSONObject(message);

JSONArray jArrayNli=jsonObject.optJSONObject("data").optJSONArray("nli");

JSONObject jObj=jArrayNli.optJSONObject(0);

JSONArray jArraySemantic=null;

if(message.contains("semantic"))

jArraySemantic=jObj.getJSONArray("semantic");

else{

input=jsonObject.optJSONObject("data").optJSONObject("asr").

optString("result");

sendMessageToActivity(MessageConst.

CLIENT_ACTION_UPDATA_INPUT_TEXT,0,0,null, input);

serverMessage=jObj.optJSONObject("desc_obj").opt("result").toString();

sendMessageToActivity(MessageConst.

CLIENT_ACTION_UPDATA_SERVER_MESSAGE,0,0,null,serverMessage);

return;

}

JSONObject jObjSemantic;

JSONArray jArraySlots;

JSONArray jArrayModifier;

Stringtype=null;

StringsongName=null;

Stringsinger=null;

if(jObj!=null) {

type=jObj.optString("type");

if("musiccontrol".equals(type))

{

jObjSemantic=jArraySemantic.optJSONObject(0);

input=jObjSemantic.optString("input");

jArraySlots=jObjSemantic.optJSONArray("slots");

jArrayModifier=jObjSemantic.optJSONArray("modifier");

Stringmodifier=(String)jArrayModifier.opt(0);

if((jArrayModifier!=null)&&("play".equals(modifier)))

{

if(jArraySlots!=null)

for(int i=0,k=jArraySlots.length(); i

{

JSONObject obj=jArraySlots.getJSONObject(i);

Stringname=obj.optString("name");

if("singer".equals(name))

singer=obj.optString("value");

elseif("songname".equals(name))

songName=obj.optString("value");

}

}elseif((modifier!=null)&&("stop".equals(modifier)))

{

if(mBookUtil!=null)

if(mBookUtil.isPlaying())

mBookUtil.stop();

}elseif((modifier!=null)&&("pause".equals(modifier)))

{

if(mBookUtil!=null)

if(mBookUtil.isPlaying())

mBookUtil.pause();

}elseif((modifier!=null)&&("resume_play".equals(modifier)))

{

if(mBookUtil!=null)

mBookUtil.resumePlay();

}elseif((modifier!=null)&&("add_volume".equals(modifier)))

{

if(mBookUtil!=null)

mBookUtil.addVolume();

}elseif((modifier!=null)&&("del_volume".equals(modifier)))

{

if(mBookUtil!=null)

mBookUtil.delVolume();

}elseif((modifier!=null)&&("next".equals(modifier)))

{

if(mBookUtil!=null)

mBookUtil.next();

}elseif((modifier!=null)&&("previous".equals(modifier)))

{

if(mBookUtil!=null)

mBookUtil.prev();

}elseif((modifier!=null)&&("play_index".equals(modifier)))

{

int position=0;

if(jArraySlots!=null)

for(int i=0,k=jArraySlots.length(); i

{

JSONObjectobj=jArraySlots.getJSONObject(i);

JSONObjectjNumDetial=obj.getJSONObject("num_detail");

Stringindex=jNumDetial.optString("recommend_value");

position=Integer.parseInt(index)-1;

}

if(mBookUtil!=null)

mBookUtil.skipTo(position);

}

}

}

if(songName!=null)

{

if(singer!=null)

{

}else{

mBookUtil.searchBookAndPlay(songName,0,0);

}

}elseif(singer!=null)

{

mBookUtil.searchBookAndPlay(songName,0,0);

}

serverMessage=jObj.optJSONObject("desc_obj").opt("result").toString();

}

catch (Exception e)

{

e.printStackTrace();

}

//發(fā)送消息更新語(yǔ)音識(shí)別的文字

sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_INPUT_TEXT,0,0,null, input);

//發(fā)送消息更新服務(wù)器返回的結(jié)果字符串

sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_SERVER_MESSAGE,

0,0,null,serverMessage);

}

以我要聽三國(guó)演義這句語(yǔ)音懂昂,服務(wù)器返回的數(shù)據(jù)如下:

{

"data": {

"asr": {

"result":"我要聽三國(guó)演義",

"speech_status":0,

"final":true,

"status":0

},

"nli": [

{

"desc_obj": {

"result":"正在努力搜索中介时,請(qǐng)稍等",

"status":0

},

"semantic": [

{

"app":"musiccontrol",

"input":"我要聽三國(guó)演義",

"slots": [

{

"name":"songname",

"value":"三國(guó)演義"

}

],

"modifier": [

"play"

],

"customer":"58df512384ae11f0bb7b487e"

}

],

"type":"musiccontrol"

}

]

},

"status":"ok"

}

1)解析出nli中type類型是musiccontrol,這是語(yǔ)法返回app的類型,而這個(gè)在線聽書的demo只關(guān)心musiccontrol這個(gè)app類型凌彬,其他的忽略沸柔。

2)用戶說(shuō)的話轉(zhuǎn)成文字是在asr中的result中獲取

3)在nli中的semantic中,input值是用戶說(shuō)的話铲敛,同asr中的result褐澎。

modifier代表返回的行為動(dòng)作,此處可以看到是play就是要求播放伐蒋,slots中的數(shù)據(jù)表示歌曲名稱是三國(guó)演義工三。

那么動(dòng)作是play,內(nèi)容是歌曲名稱是三國(guó)演義先鱼,在這個(gè)demo中調(diào)用

mBookUtil.searchBookAndPlay(songName,0,0);會(huì)先查詢俭正,查詢到結(jié)果會(huì)再發(fā)播放消息要求播放,我要聽三國(guó)演義這個(gè)流程就走完了焙畔。

關(guān)于在線聽書請(qǐng)看博文:http://blog.csdn.net/ls0609/article/details/71519203

4.源碼下載鏈接

http://pan.baidu.com/s/1o8OELdC

5.相關(guān)鏈接

語(yǔ)音記賬demo:http://blog.csdn.net/ls0609/article/details/72765789

olami開放平臺(tái)語(yǔ)法編寫簡(jiǎn)介:http://blog.csdn.net/ls0609/article/details/71624340

olami開放平臺(tái)語(yǔ)法官方介紹:https://cn.olami.ai/wiki/?mp=nli&content=nli2.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掸读,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宏多,更是在濱河造成了極大的恐慌儿惫,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伸但,死亡現(xiàn)場(chǎng)離奇詭異姥闪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)砌烁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人函喉,你說(shuō)我怎么就攤上這事避归。” “怎么了管呵?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵梳毙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我捐下,道長(zhǎng)账锹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任坷襟,我火速辦了婚禮奸柬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘婴程。我一直安慰自己廓奕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布档叔。 她就那樣靜靜地躺著桌粉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衙四。 梳的紋絲不亂的頭發(fā)上铃肯,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音传蹈,去河邊找鬼押逼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卡睦,可吹牛的內(nèi)容都是我干的宴胧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼表锻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼恕齐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起瞬逊,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤显歧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后确镊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體士骤,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年蕾域,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拷肌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片到旦。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖巨缘,靈堂內(nèi)的尸體忽然破棺而出添忘,到底是詐尸還是另有隱情,我是刑警寧澤若锁,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布搁骑,位于F島的核電站,受9級(jí)特大地震影響又固,放射性物質(zhì)發(fā)生泄漏仲器。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一仰冠、第九天 我趴在偏房一處隱蔽的房頂上張望乏冀。 院中可真熱鬧,春花似錦沪停、人聲如沸煤辨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)众辨。三九已至,卻和暖如春舷礼,著一層夾襖步出監(jiān)牢的瞬間鹃彻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工妻献, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蛛株,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓育拨,卻偏偏與公主長(zhǎng)得像谨履,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子熬丧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容