實(shí)現(xiàn)循環(huán)語音識(shí)別、合成簡單封裝
需求背景
最近項(xiàng)目上遇到一個(gè)需求:語音識(shí)別獲取文字后后臺(tái)交互獲取結(jié)果并語音合成播報(bào)
需求拆解
- 語音識(shí)別(可打斷識(shí)別)
-
語音播報(bào)(可打斷,打斷后開啟語音識(shí)別)
image.png
graph LR
A[開始識(shí)別]-->B[是否識(shí)別成功]
B-->|是|C[識(shí)別成功]
B-->|否|D[識(shí)別失敗]
D-->|重新識(shí)別|A
C-->E[語音合成]
E-->A
代碼解析
1、此demo中集成了訊飛和云知聲兩個(gè)平臺(tái),此處解析以訊飛為例展開,云知聲解析在代碼中有注釋;
/**
* iflytek訊飛
* @param results
* @param isLast
*/
@Override
public void onResult(RecognizerResult results, boolean isLast) {
String text = JsonParser.parseIatResult(results.getResultString());
result += text;
if (isLast) {
if (result.trim().length() > 0) {
onResult(result);//識(shí)別到結(jié)果
result = "";
} else {
result = "";
Logger.i("Listener start");
RecognizerManager.getInstance().startListening();//若沒有識(shí)別到結(jié)果再次開啟識(shí)別
}
}
}
識(shí)別失敗再次開啟識(shí)別
@Override
public void onError(SpeechError error) {
// Tips:
// 錯(cuò)誤碼:10118(您沒有說話),可能是錄音機(jī)權(quán)限被禁,需要提示用戶打開應(yīng)用的錄音權(quán)限。
// 10114 網(wǎng)絡(luò)異常
// 20002 獲取結(jié)果超時(shí)
Logger.i(error.getPlainDescription(true));
if (error.getErrorCode() == 10118 || error.getErrorCode() == 10114
|| error.getErrorCode() == 20002) {
Logger.i("Listener start");
RecognizerManager.getInstance().startListening();
}
}
音量回調(diào)方法
@Override
public void onVolumeChanged(int volume, byte[] data) {
onVolumeChanged(volume);
}
2、語音合成部分
播放完成開始識(shí)別
@Override
public void onCompleted(SpeechError error) {
if (error == null) {
Logger.i("播放完成");
}
completed();
SpeechManager.getInstance().setStatus(Status.STATES_STOP);
Logger.i("Listener start");
RecognizerManager.getInstance().startListening();
}
3、簡單封裝的語音管理類RecognizerManager、SpeechManager實(shí)現(xiàn)邏輯上的切換
RecognizerManager
1、初始化
private void init() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM)) {//可配置的語音引擎
mUnderstander = new SpeechUnderstander(AppUtils.getAppContext(), UscConfig.appKey,
UscConfig.secret);
mUnderstander.setListener(mSpeechUnderstanderListener);
setUscParam();
mUnderstander.start();
} else {
mIat = SpeechRecognizer.createRecognizer(AppUtils.getAppContext(), mInitListener);
Logger.d(mIat);
}
}
2、生命周期綁定
public void startListening() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM)) {
if (mUnderstander == null) {
init();
return;
}
mUnderstander.start();
} else {
if (mIat == null) {
init();
return;
}
int ret = mIat.startListening(mRecognizerListener);
if (ret != ErrorCode.SUCCESS) {
Logger.i("聽寫失敗,錯(cuò)誤碼:" + ret);
} else {
Logger.i(AppUtils.getAppContext().getString(R.string.text_begin));
}
}
}
public void pause() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM_USC)) {
if (mUnderstander != null) {
mUnderstander.stop();
mUnderstander.cancel();
}
} else {
if (null != mIat) {
mIat.stopListening();
}
}
}
public void release() {
if (PlatformConfig.PLATFORM.equals(PlatformConfig.PLATFORM_USC)) {
if (mUnderstander != null) {
mUnderstander.stop();
mUnderstander.cancel();
mUnderstander.release(SpeechConstants.ASR_RELEASE_ENGINE, "");
}
} else {
if (mIat != null) {
mIat.stopListening();
mIat.cancel();
mIat.destroy();
}
}
}
SpeechManager
1、合成方法
private void play() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM)) {
int code = uscTts.playText(text);
setStatus(Status.STATES_PLAYING);
Logger.i("Listener stop");
RecognizerManager.getInstance().release();
} else {
int code = iflytekTts.startSpeaking(text, synthesizer);
if (code != ErrorCode.SUCCESS) {
setStatus(Status.STATES_STOP);
Logger.i("語音合成失敗,錯(cuò)誤碼: " + code);
} else {
setStatus(Status.STATES_PLAYING);
Logger.i("Listener stop");
RecognizerManager.getInstance().release();
}
}
}
2、生命周期綁定
/**
* 暫停
*/
public void pause() {
pauseSpeak();
if (getStatus() == Status.STATES_PLAYING) {
setStatus(Status.STATES_PAUSE);
}
Logger.i("Listener start");
// RecognizerManager.getInstance().startListening();
}
/**
* 停止播報(bào)
*
* @param isListen 停止播報(bào)是否開啟監(jiān)聽
*/
public void stop(boolean isListen) {
stopSpeak();
if (getStatus() == Status.STATES_PAUSE || getStatus() == Status.STATES_PLAYING) {
setStatus(Status.STATES_STOP);
}
if (isListen) {
Logger.i("Listener start");
RecognizerManager.getInstance().startListening();
}
}
/**
* 恢復(fù)播報(bào)
*/
public void resume() {
getInstance().resumeSpeak();
if (getStatus() == Status.STATES_PAUSE) {
getInstance().setStatus(Status.STATES_PLAYING);
}
Logger.i("Listener stop");
RecognizerManager.getInstance().release();
}
private void resumeSpeak() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM)) {
if (uscTts != null) {
uscTts.resume();
}
} else {
if (iflytekTts != null) {
iflytekTts.resumeSpeaking();
}
}
}
private void stopSpeak() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM)) {
if (uscTts != null) {
uscTts.stop();
uscTts.cancel();
}
} else {
if (iflytekTts != null) {
iflytekTts.stopSpeaking();
}
}
}
private void pauseSpeak() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM)) {
if (uscTts != null) {
uscTts.pause();
}
} else {
if (iflytekTts != null) {
iflytekTts.pauseSpeaking();
}
}
}
public void release() {
if (PlatformConfig.PLATFORM_USC.equals(PlatformConfig.PLATFORM)) {
if (uscTts != null) {
uscTts.stop();
uscTts.release(SpeechConstants.TTS_RELEASE_ENGINE, null);
}
} else {
if (iflytekTts != null) {
iflytekTts.stopSpeaking();
iflytekTts.destroy();
}
}
}
SDK替換
demo的訊飛可直接使用,云知聲需要申請(qǐng)appkey
