[Feat]TTS支持按优先级排队和打断机制

This commit is contained in:
chenfufeng
2022-10-21 11:18:51 +08:00
parent c0ab0408b1
commit 6e0e117e0e
3 changed files with 101 additions and 2 deletions

View File

@@ -90,6 +90,17 @@ public class AIAssist {
}
}
/**
* 等级由低到高为0、1、2、3分别对应p3、p2、p1、p0
* @param text
* @param level
*/
public void speakTTSVoiceWithLevel(String text, int level) {
if (mTTS != null) {
mTTS.speakTTSVoiceWithLevel(text, level);
}
}
/**
* 语音播报
*

View File

@@ -39,6 +39,8 @@ interface IMogoTTS extends IProvider {
*/
void speakTTSVoice( String tts );
void speakTTSVoiceWithLevel( String tts, int level);
/**
* 播放 tts 语音
*

View File

@@ -8,6 +8,9 @@ import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Pair;
import androidx.annotation.MainThread;
import com.aispeech.AIError;
import com.aispeech.DUILiteConfig;
@@ -20,8 +23,6 @@ import com.aispeech.export.engines.AILocalTTSEngine;
import com.aispeech.export.intent.AILocalTTSIntent;
import com.aispeech.export.listeners.AITTSListener;
import com.aispeech.lite.AuthType;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.cloud.commons.BuildConfig;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.ThreadUtils;
@@ -39,6 +40,7 @@ import com.zhidao.voicesdk.callback.OnTtsListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -59,6 +61,10 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack, OnTtsList
private boolean mInitReady = true;
private Context mContext;
// 等级由低到高为0、1、2、3默认为-1表示没有正在tts的
private int curTtsLevel = -1;
private LinkedList<Pair<String, Integer>> linkedList = new LinkedList<>();
public void release() {
CallerLogger.INSTANCE.d(TAG, "release");
ThreadUtils.runOnUiThread(() -> {
@@ -73,6 +79,7 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack, OnTtsList
}
mQAndAMap.clear();
mVoiceClient.release();
curTtsLevel = -1;
if (mEngine != null) {
mEngine.destroy();
mEngine = null;
@@ -344,12 +351,15 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack, OnTtsList
if (mSpeakVoiceMap.containsKey(text)) {
mSpeakVoiceMap.remove(text);
}
curTtsLevel = -1;
mEngine.stop();
}
}
public void stopTts() {
if (mEngine != null && mHasAuth) {
// tts过程中调用stop不会有回调事件
curTtsLevel = -1;
mEngine.stop();
}
}
@@ -367,6 +377,67 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack, OnTtsList
}
}
@MainThread
public void speakTTSVoiceWithLevel(String text, int ttsLevel) {
if (mEngine != null) {
if (ttsLevel == curTtsLevel) {
// 对应p3、p2级别的排队
if (ttsLevel == 0 || ttsLevel == 1) {
CallerLogger.INSTANCE.d(TAG, "===================");
CallerLogger.INSTANCE.d(TAG, "插入消息:" + text + ",level为" + ttsLevel);
insertTts(text, ttsLevel);
return;
} else {
// 打断并合成新的
stopTts();
CallerLogger.INSTANCE.d(TAG, "非Level1同级别打断!");
}
} else {
// 将要TTS的比现在正在TTS的优先级高
if (ttsLevel > curTtsLevel) {
if (curTtsLevel >= 0) {
// 打断并合成高优先级的
stopTts();
}
CallerLogger.INSTANCE.d(TAG, "高优先级打断低级别的!");
} else {
if (ttsLevel == 0 || ttsLevel == 1) {
CallerLogger.INSTANCE.d(TAG, "===================");
CallerLogger.INSTANCE.d(TAG, "插入消息:" + text + ",level为" + ttsLevel);
insertTts(text, ttsLevel);
}
return;
}
}
curTtsLevel = ttsLevel;
// 合成并播放
CallerLogger.INSTANCE.d(TAG, "tts准备合成" + text + ",curTtsLevel为" + curTtsLevel);
mEngine.speak(text, text, mAILocalTTSIntent);
}
}
// 降序插入Tts(目前Level0、1可排队)
private void insertTts(String text, int level) {
int index = -1;
for (int i = linkedList.size() - 1; i >= 0; i--) {
int nodeLevel = linkedList.get(i).second;
// 只有高优先级才插入到前面,等于的情况下是插到后面
if (level > nodeLevel) {
index = i;
}
}
if (index >= 0) {
linkedList.add(index, new Pair(text, level));
} else {
linkedList.addLast(new Pair(text, level));
}
for (Pair<String, Integer> ttsPair:
linkedList) {
CallerLogger.INSTANCE.d(TAG, "tts文本为" + ttsPair.first + ",level为" + ttsPair.second);
}
CallerLogger.INSTANCE.d(TAG, "===================");
}
/**
* 语音播报
*
@@ -669,6 +740,7 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack, OnTtsList
@Override
public void onError(String utteranceId, AIError aiError) {
CallerLogger.INSTANCE.d(TAG, "检测到错误:" + aiError.toString());
curTtsLevel = -1;
IMogoTTSCallback callBack = PadTTS.this.mSpeakVoiceMap.remove(utteranceId);
if (callBack != null) {
callBack.onSpeakError(utteranceId, aiError.getError());
@@ -682,7 +754,9 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack, OnTtsList
@Override
public void onCompletion(String utteranceId) {
curTtsLevel = -1;
CallerLogger.INSTANCE.d(TAG, "播放完成");
ttsNext();
IMogoTTSCallback callBack = PadTTS.this.mSpeakVoiceMap.remove(utteranceId);
if (callBack != null) {
callBack.onSpeakEnd(utteranceId);
@@ -711,6 +785,18 @@ public class PadTTS implements IMogoTTS, VoiceClient.VoiceCmdCallBack, OnTtsList
}
}
@MainThread
private void ttsNext() {
if (!linkedList.isEmpty()) {
Pair<String, Integer> ttsPair = linkedList.removeFirst();
CallerLogger.INSTANCE.i(TAG, "排队播放的下一条文本为:" + ttsPair.first + ",级别为:" + ttsPair.second);
curTtsLevel = ttsPair.second;
speakTTSVoice(ttsPair.first);
} else {
CallerLogger.INSTANCE.i(TAG, "队列为空");
}
}
public static boolean isProcessRunning(Context context, int uid) {
if (context == null) {
return false;