Commit 38df065c authored by ali's avatar ali

fix: 优化相关异常处理

parent dff91c47
...@@ -50,10 +50,10 @@ onMounted(() => { ...@@ -50,10 +50,10 @@ onMounted(() => {
}) })
const errorSnackbar = ref<boolean>(false) const errorSnackbar = ref<boolean>(false)
const errorMsg = ref<string>(''); const errorMsg = ref<string>('')
const showError = (msg: string) => { const showError = (msg: string) => {
errorSnackbar.value = true; errorSnackbar.value = true
errorMsg.value = msg; errorMsg.value = msg
} }
function loadImg(): Promise<HTMLImageElement> { function loadImg(): Promise<HTMLImageElement> {
...@@ -77,17 +77,7 @@ async function init() { ...@@ -77,17 +77,7 @@ async function init() {
canvasEle.height = img.naturalHeight canvasEle.height = img.naturalHeight
const item = photo.list.find((i) => i.url === url) const item = photo.list.find((i) => i.url === url)
photoRole = new PhotoRole(settings.liveHost, `${item?.liveUrl}`, canvasEle) photoRole = new PhotoRole(settings.liveHost, `${item?.liveUrl}`, canvasEle)
photoRole.on('asyncAnswer', onAsyncAnswer)
photoRole.on('asyncAnswer', async (ans) => {
if (ans.playState === 'playing') {
microphoneState.value = 'reply'
return
}
if (microphoneState.value === 'reply' && ans.playState === 'pause' && (await checkSteps())) {
microphoneState.value = 'input'
}
})
// initPlayer(videoEle); // initPlayer(videoEle);
...@@ -112,6 +102,17 @@ async function init() { ...@@ -112,6 +102,17 @@ async function init() {
requestAnimationFrame(updateFrame) requestAnimationFrame(updateFrame)
} }
async function onAsyncAnswer(ans: PhotoAnswer) {
if (ans.playState === 'playing') {
microphoneState.value = 'reply'
return
}
if (microphoneState.value === 'reply' && ans.playState === 'pause' && (await checkSteps())) {
microphoneState.value = 'input'
}
}
function draw( function draw(
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
img: HTMLImageElement, img: HTMLImageElement,
...@@ -273,7 +274,7 @@ async function startVoskWsAudioInput() { ...@@ -273,7 +274,7 @@ 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
} }
...@@ -378,6 +379,9 @@ async function endAudioInput() { ...@@ -378,6 +379,9 @@ async function endAudioInput() {
} }
inputContext.asrPartial = '' inputContext.asrPartial = ''
inputContext.answerArray.length = 0 inputContext.answerArray.length = 0
inputContext.steps.length = 0
// @ts-ignore
photoRole?.off('asyncAnswer', onAsyncAnswer)
await photoRole?.destroy() await photoRole?.destroy()
} }
...@@ -417,13 +421,14 @@ async function onQ(question: string) { ...@@ -417,13 +421,14 @@ async function onQ(question: string) {
microphoneState.value = 'loading' microphoneState.value = 'loading'
try {
const ws = await initLLMSocket() const ws = await initLLMSocket()
const { pose, stepResolve, stepReject } = createStep() const { pose, stepResolve, stepReject } = createStep()
const messageTimeout = setTimeout(async () => { const messageTimeout = setTimeout(async () => {
showError('llm:timeout!') showError('llm:timeout!')
await endAudioInput() await endAudioInput()
microphoneState.value = 'waitInput' microphoneState.value = 'waitInput'
}, 5000); }, 10000)
let sliceAnswer = '' let sliceAnswer = ''
let answer = '' let answer = ''
...@@ -435,6 +440,7 @@ async function onQ(question: string) { ...@@ -435,6 +440,7 @@ async function onQ(question: string) {
inputContext.steps.length = 0 inputContext.steps.length = 0
inputContext.steps.push(pose) inputContext.steps.push(pose)
photoRole!.answerArgs = new PhotoAnswer() photoRole!.answerArgs = new PhotoAnswer()
photoRole!.on('asyncAnswer', onAsyncAnswer)
ws.onmessage = (message) => { ws.onmessage = (message) => {
try { try {
...@@ -459,7 +465,7 @@ async function onQ(question: string) { ...@@ -459,7 +465,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); 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++) {
...@@ -475,7 +481,7 @@ async function onQ(question: string) { ...@@ -475,7 +481,7 @@ async function onQ(question: string) {
} }
} }
} catch (error) { } catch (error) {
showError('llm:'+ error) showError('llm:' + error)
endAudioInput().then(() => { endAudioInput().then(() => {
microphoneState.value = 'waitInput' microphoneState.value = 'waitInput'
}) })
...@@ -484,6 +490,11 @@ async function onQ(question: string) { ...@@ -484,6 +490,11 @@ async function onQ(question: string) {
} }
ws.send(JSON.stringify({ prompt: question, historys_list: [] })) ws.send(JSON.stringify({ prompt: question, historys_list: [] }))
} catch (error) {
console.error(error)
microphoneState.value = 'input'
showError(`llm${JSON.stringify(error)}`)
}
} }
let isTTSRunning = false let isTTSRunning = false
...@@ -525,7 +536,7 @@ async function runTTSTask() { ...@@ -525,7 +536,7 @@ async function runTTSTask() {
}) })
} }
} catch (error) { } catch (error) {
showError('tts:'+ error) showError('tts:' + error)
endAudioInput().then(() => { endAudioInput().then(() => {
microphoneState.value = 'waitInput' microphoneState.value = 'waitInput'
}) })
...@@ -577,7 +588,7 @@ async function down() { ...@@ -577,7 +588,7 @@ async function down() {
try { try {
await startVoskWsAudioInput() await startVoskWsAudioInput()
} catch (error) { } catch (error) {
showError('start:'+ error) showError('start:' + error)
endAudioInput().then(() => { endAudioInput().then(() => {
microphoneState.value = 'waitInput' microphoneState.value = 'waitInput'
}) })
...@@ -631,21 +642,11 @@ async function down() { ...@@ -631,21 +642,11 @@ async function down() {
</v-btn> </v-btn>
</div> </div>
<v-snackbar <v-snackbar v-model="errorSnackbar" multi-line :timeout="3000">
v-model="errorSnackbar"
multi-line
:timeout="3000"
>
{{ errorMsg }} {{ errorMsg }}
<template #actions> <template #actions>
<v-btn <v-btn color="red" variant="text" @click="errorSnackbar = false"> Close </v-btn>
color="red"
variant="text"
@click="errorSnackbar = false"
>
Close
</v-btn>
</template> </template>
</v-snackbar> </v-snackbar>
</template> </template>
......
...@@ -35,8 +35,10 @@ const inputContext: { ...@@ -35,8 +35,10 @@ const inputContext: {
voskWs?: WebSocket voskWs?: WebSocket
asrPartial: string asrPartial: string
playingAudio?: HTMLAudioElement playingAudio?: HTMLAudioElement
answerArray: string[]
} = { } = {
asrPartial: '' asrPartial: '',
answerArray: []
} }
onMounted(() => { onMounted(() => {
...@@ -48,10 +50,10 @@ router.beforeEach((g) => { ...@@ -48,10 +50,10 @@ router.beforeEach((g) => {
}) })
const errorSnackbar = ref<boolean>(false) const errorSnackbar = ref<boolean>(false)
const errorMsg = ref<string>(''); const errorMsg = ref<string>('')
const showError = (msg: string) => { const showError = (msg: string) => {
errorSnackbar.value = true; errorSnackbar.value = true
errorMsg.value = msg; errorMsg.value = msg
} }
async function initVosk({ async function initVosk({
...@@ -275,6 +277,7 @@ function endAudioInput() { ...@@ -275,6 +277,7 @@ function endAudioInput() {
videos[1].value?.pause() videos[1].value?.pause()
videos[0].value?.pause() videos[0].value?.pause()
isPlayRunning = false isPlayRunning = false
inputContext.answerArray.length = 0
} }
const canplay = () => { const canplay = () => {
...@@ -344,19 +347,18 @@ async function onQ(question: string) { ...@@ -344,19 +347,18 @@ async function onQ(question: string) {
} }
// 视频链接匹配不上,直接走大模型 // 视频链接匹配不上,直接走大模型
try {
const ws = await initLLMSocket() const ws = await initLLMSocket()
const answerArray: string[] = []
const messageTimeout = setTimeout(() => { const messageTimeout = setTimeout(() => {
showError('llm:timeout!') showError('llm:timeout!')
endAudioInput() endAudioInput()
microphoneState.value = 'waitInput' microphoneState.value = 'waitInput'
}, 5000); }, 10000)
let sliceAnswer = '' let sliceAnswer = ''
let answer = '' let answer = ''
let isTime = true let isTime = true
let sliceAnswerLength = 10 let sliceAnswerLength = 10
inputContext.ws = ws inputContext.ws = ws
ws.onmessage = (message) => { ws.onmessage = (message) => {
if (microphoneState.value === 'input') { if (microphoneState.value === 'input') {
return return
...@@ -370,11 +372,11 @@ async function onQ(question: string) { ...@@ -370,11 +372,11 @@ async function onQ(question: string) {
} }
if (event === 'stream_end') { if (event === 'stream_end') {
answerArray.push(sliceAnswer) inputContext.answerArray.push(sliceAnswer)
runTTSTask(answerArray) runTTSTask()
sliceAnswer = '' sliceAnswer = ''
answerArray.push(sliceAnswer) inputContext.answerArray.push(sliceAnswer)
sliceAnswer = '' sliceAnswer = ''
inputContext.ws?.close() inputContext.ws?.close()
console.log('----------------> answer: ', answer) console.log('----------------> answer: ', answer)
...@@ -384,7 +386,7 @@ async function onQ(question: string) { ...@@ -384,7 +386,7 @@ async function onQ(question: string) {
answer += text answer += text
isTime && console.time('sliceAnswer') isTime && console.time('sliceAnswer')
isTime = false isTime = false
clearTimeout(messageTimeout); 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++) {
...@@ -393,32 +395,34 @@ async function onQ(question: string) { ...@@ -393,32 +395,34 @@ async function onQ(question: string) {
if (/[。,?!;,.?!;]/.test(t) && sliceAnswer.length >= sliceAnswerLength) { if (/[。,?!;,.?!;]/.test(t) && sliceAnswer.length >= sliceAnswerLength) {
console.timeEnd('sliceAnswer') console.timeEnd('sliceAnswer')
sliceAnswerLength = settings.llmToTTSSliceLength sliceAnswerLength = settings.llmToTTSSliceLength
answerArray.push(sliceAnswer) inputContext.answerArray.push(sliceAnswer)
runTTSTask(answerArray) runTTSTask()
sliceAnswer = '' sliceAnswer = ''
isTime = true isTime = true
} }
} }
} catch (error) { } catch (error) {
console.error(error); console.error(error)
showError(`message:${error}`) showError(`message:${error}`)
microphoneState.value = 'waitInput' microphoneState.value = 'waitInput'
} }
} }
ws.send(JSON.stringify({ prompt: question, historys_list: [] })) ws.send(JSON.stringify({ prompt: question, historys_list: [] }))
} catch (error) {
console.error(error)
microphoneState.value = 'input'
showError(`llm:${JSON.stringify(error)}`)
}
} }
let isTTSRunning = false let isTTSRunning = false
async function runTTSTask(tasks: string[]) { async function runTTSTask() {
if (isTTSRunning) return if (isTTSRunning) return
isTTSRunning = true isTTSRunning = true
microphoneState.value = 'loading'
try { try {
while (tasks.length) { while (inputContext.answerArray.length) {
const task = tasks.shift() const task = inputContext.answerArray.shift()
if (!task) break if (!task) break
if (task.trim().length < 1) continue if (task.trim().length < 1) continue
...@@ -560,21 +564,11 @@ async function down() { ...@@ -560,21 +564,11 @@ async function down() {
</v-chip> </v-chip>
</div> </div>
<v-snackbar <v-snackbar v-model="errorSnackbar" multi-line :timeout="3000">
v-model="errorSnackbar"
multi-line
:timeout="3000"
>
{{ errorMsg }} {{ errorMsg }}
<template #actions> <template #actions>
<v-btn <v-btn color="red" variant="text" @click="errorSnackbar = false"> Close </v-btn>
color="red"
variant="text"
@click="errorSnackbar = false"
>
Close
</v-btn>
</template> </template>
</v-snackbar> </v-snackbar>
</template> </template>
......
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