Commit dff91c47 authored by ali's avatar ali

fix: 异常处理

parent 52ba82c4
...@@ -509,9 +509,9 @@ export class PhotoRole extends EventEmitter { ...@@ -509,9 +509,9 @@ export class PhotoRole extends EventEmitter {
} }
async destroy() { async destroy() {
this._liveTaskQueue.length = 0; this._liveTaskQueue.length = 0
await this._stopLive(this.sessionId); await this._stopLive(this.sessionId)
this._liveStatus = 'closing'; this._liveStatus = 'closing'
// this.answerArgs = null; // this.answerArgs = null;
// this._webRTCContainer && document.body.removeChild(this._webRTCContainer) // this._webRTCContainer && document.body.removeChild(this._webRTCContainer)
this._rtc?.stopPlay() this._rtc?.stopPlay()
......
...@@ -49,6 +49,13 @@ onMounted(() => { ...@@ -49,6 +49,13 @@ onMounted(() => {
document.body.style.overflow = 'hidden' document.body.style.overflow = 'hidden'
}) })
const errorSnackbar = ref<boolean>(false)
const errorMsg = ref<string>('');
const showError = (msg: string) => {
errorSnackbar.value = true;
errorMsg.value = msg;
}
function loadImg(): Promise<HTMLImageElement> { function loadImg(): Promise<HTMLImageElement> {
const img = new Image() const img = new Image()
img.src = url img.src = url
...@@ -371,7 +378,7 @@ async function endAudioInput() { ...@@ -371,7 +378,7 @@ async function endAudioInput() {
} }
inputContext.asrPartial = '' inputContext.asrPartial = ''
inputContext.answerArray.length = 0 inputContext.answerArray.length = 0
await photoRole?.destroy(); await photoRole?.destroy()
} }
const checkSteps = async () => { const checkSteps = async () => {
...@@ -411,15 +418,21 @@ async function onQ(question: string) { ...@@ -411,15 +418,21 @@ async function onQ(question: string) {
microphoneState.value = 'loading' microphoneState.value = 'loading'
const ws = await initLLMSocket() const ws = await initLLMSocket()
inputContext.ws = ws const { pose, stepResolve, stepReject } = createStep()
const messageTimeout = setTimeout(async () => {
showError('llm:timeout!')
await endAudioInput()
microphoneState.value = 'waitInput'
}, 5000);
let sliceAnswer = '' let sliceAnswer = ''
let answer = '' let answer = ''
let isTime = true let isTime = true
let sliceAnswerLength = 10 let sliceAnswerLength = 10
inputContext.ws = ws
inputContext.answerArray.length = 0 inputContext.answerArray.length = 0
inputContext.steps.length = 0 inputContext.steps.length = 0
const { pose, stepResolve, stepReject } = createStep()
inputContext.steps.push(pose) inputContext.steps.push(pose)
photoRole!.answerArgs = new PhotoAnswer() photoRole!.answerArgs = new PhotoAnswer()
...@@ -446,6 +459,7 @@ async function onQ(question: string) { ...@@ -446,6 +459,7 @@ async function onQ(question: string) {
photoRole!.answerArgs!._typingAnswer.push(answer) photoRole!.answerArgs!._typingAnswer.push(answer)
isTime && console.time('sliceAnswer') isTime && console.time('sliceAnswer')
isTime = false isTime = false
clearTimeout(messageTimeout);
const textArr = text.split('') const textArr = text.split('')
for (let i = 0; i < textArr.length; i++) { for (let i = 0; i < textArr.length; i++) {
...@@ -461,6 +475,10 @@ async function onQ(question: string) { ...@@ -461,6 +475,10 @@ async function onQ(question: string) {
} }
} }
} catch (error) { } catch (error) {
showError('llm:'+ error)
endAudioInput().then(() => {
microphoneState.value = 'waitInput'
})
stepReject(JSON.stringify(error)) stepReject(JSON.stringify(error))
} }
} }
...@@ -507,6 +525,10 @@ async function runTTSTask() { ...@@ -507,6 +525,10 @@ async function runTTSTask() {
}) })
} }
} catch (error) { } catch (error) {
showError('tts:'+ error)
endAudioInput().then(() => {
microphoneState.value = 'waitInput'
})
stepReject(JSON.stringify(error)) stepReject(JSON.stringify(error))
} }
...@@ -552,7 +574,14 @@ async function down() { ...@@ -552,7 +574,14 @@ async function down() {
await endAudioInput() await endAudioInput()
} }
startVoskWsAudioInput() try {
await startVoskWsAudioInput()
} catch (error) {
showError('start:'+ error)
endAudioInput().then(() => {
microphoneState.value = 'waitInput'
})
}
} }
</script> </script>
...@@ -578,10 +607,7 @@ async function down() { ...@@ -578,10 +607,7 @@ async function down() {
color="#fff" color="#fff"
variant="elevated" variant="elevated"
size="x-large" size="x-large"
:disabled=" :disabled="microphoneState === 'loading' || microphoneState === 'disabled'"
microphoneState === 'loading' ||
microphoneState === 'disabled'
"
@pointerdown="down" @pointerdown="down"
> >
<v-icon v-if="microphoneState === 'waitInput'" icon="mdi-microphone"></v-icon> <v-icon v-if="microphoneState === 'waitInput'" icon="mdi-microphone"></v-icon>
...@@ -604,6 +630,24 @@ async function down() { ...@@ -604,6 +630,24 @@ async function down() {
</template> </template>
</v-btn> </v-btn>
</div> </div>
<v-snackbar
v-model="errorSnackbar"
multi-line
:timeout="3000"
>
{{ errorMsg }}
<template #actions>
<v-btn
color="red"
variant="text"
@click="errorSnackbar = false"
>
Close
</v-btn>
</template>
</v-snackbar>
</template> </template>
<style scoped> <style scoped>
.voice { .voice {
......
...@@ -47,6 +47,13 @@ router.beforeEach((g) => { ...@@ -47,6 +47,13 @@ router.beforeEach((g) => {
if (!g.query.url) return router.push('/error') if (!g.query.url) return router.push('/error')
}) })
const errorSnackbar = ref<boolean>(false)
const errorMsg = ref<string>('');
const showError = (msg: string) => {
errorSnackbar.value = true;
errorMsg.value = msg;
}
async function initVosk({ async function initVosk({
result, result,
partialResult partialResult
...@@ -160,11 +167,11 @@ async function startVoskWsAudioInput() { ...@@ -160,11 +167,11 @@ async function startVoskWsAudioInput() {
if (microphoneState.value === 'loading') return if (microphoneState.value === 'loading') return
if (microphoneState.value === 'input') { if (microphoneState.value === 'input') {
endAudioInput() await endAudioInput()
return return
} }
initVoskWS() await initVoskWS()
sampleRate = 16000 sampleRate = 16000
const mediaStream = await navigator.mediaDevices.getUserMedia({ const mediaStream = await navigator.mediaDevices.getUserMedia({
audio: { audio: {
...@@ -315,25 +322,37 @@ async function onQ(question: string) { ...@@ -315,25 +322,37 @@ async function onQ(question: string) {
if (!role) return if (!role) return
microphoneState.value = 'loading' microphoneState.value = 'loading'
if (await qNLP(question)) { try {
loadVideo(url) const nlpUrl = await qNLP(question)
microphoneState.value = 'reply' if (nlpUrl) {
const videoEle = videos[1].value loadVideo(nlpUrl)
videoEle!.loop = false microphoneState.value = 'reply'
videoEle!.muted = false const videoEle = videos[1].value
videoEle!.onended = () => { videoEle!.loop = false
videoEle!.onended = null videoEle!.muted = false
microphoneState.value = 'input' videoEle!.onended = () => {
// TODO: 是否需要初始化 videoEle!.onended = null
microphoneState.value = 'input'
// TODO: 是否需要初始化
}
return
} }
} catch (error) {
microphoneState.value = 'input'
showError(`nlp:${error}`)
return return
} }
// 视频链接匹配不上,直接走大模型 // 视频链接匹配不上,直接走大模型
const ws = await initLLMSocket() const ws = await initLLMSocket()
const answerArray: string[] = []
const messageTimeout = setTimeout(() => {
showError('llm:timeout!')
endAudioInput()
microphoneState.value = 'waitInput'
}, 5000);
let sliceAnswer = '' let sliceAnswer = ''
let answer = '' let answer = ''
const answerArray: string[] = []
let isTime = true let isTime = true
let sliceAnswerLength = 10 let sliceAnswerLength = 10
inputContext.ws = ws inputContext.ws = ws
...@@ -365,6 +384,7 @@ async function onQ(question: string) { ...@@ -365,6 +384,7 @@ async function onQ(question: string) {
answer += text answer += text
isTime && console.time('sliceAnswer') isTime && console.time('sliceAnswer')
isTime = false isTime = false
clearTimeout(messageTimeout);
const textArr = text.split('') const textArr = text.split('')
for (let i = 0; i < textArr.length; i++) { for (let i = 0; i < textArr.length; i++) {
...@@ -380,8 +400,9 @@ async function onQ(question: string) { ...@@ -380,8 +400,9 @@ async function onQ(question: string) {
} }
} }
} catch (error) { } catch (error) {
console.log('返回答案错误 -----> ' + JSON.stringify(error)) console.error(error);
microphoneState.value = 'input' showError(`message:${error}`)
microphoneState.value = 'waitInput'
} }
} }
...@@ -423,7 +444,8 @@ async function runTTSTask(tasks: string[]) { ...@@ -423,7 +444,8 @@ async function runTTSTask(tasks: string[]) {
runAudioPlay() runAudioPlay()
} }
} catch (error) { } catch (error) {
microphoneState.value = 'input' showError(`tts:${error}`)
microphoneState.value = 'waitInput'
console.error(error) console.error(error)
} }
...@@ -470,12 +492,16 @@ async function xfTTS(text: string) { ...@@ -470,12 +492,16 @@ async function xfTTS(text: string) {
console.log('----------------> tts:', res) console.log('----------------> tts:', res)
} }
function down() { async function down() {
if (microphoneState.value === 'reply') { if (microphoneState.value === 'reply') {
endAudioInput() endAudioInput()
} }
startVoskWsAudioInput() try {
await startVoskWsAudioInput()
} catch (error) {
showError(`${error}`)
}
} }
</script> </script>
...@@ -533,6 +559,24 @@ function down() { ...@@ -533,6 +559,24 @@ function down() {
{{ item.q }} {{ item.q }}
</v-chip> </v-chip>
</div> </div>
<v-snackbar
v-model="errorSnackbar"
multi-line
:timeout="3000"
>
{{ errorMsg }}
<template #actions>
<v-btn
color="red"
variant="text"
@click="errorSnackbar = false"
>
Close
</v-btn>
</template>
</v-snackbar>
</template> </template>
<style scoped> <style scoped>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment