fix: 语音输出改为边生成边播报,不再等整段答案完成
TtsPlayer 本来就实现了完整的流式播报能力(append() 按句子边界切分 入队、flush() 收尾剩余文本),只是 ChatPanel 一直没接上,只在 querying 结束后调用一次 speakWithAnnouncement(全文)。 改为在 onDelta 里实时 append(delta),onDone/onError 里 flush() 收尾。删除了原来 querying 结束时整段朗读的 watch(不删会导致 整段答案被朗读两遍)。效果:不用等生成完,第一句话生成出来就 开始播,播放速度跟不上文字输出时 TtsPlayer 自带的自适应语速会 自动降速跟上。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
ab01effd5b
commit
ec634c4133
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import { NModal, NCard, NScrollbar, useMessage } from 'naive-ui'
|
||||
import { marked } from 'marked'
|
||||
import { useRagStore } from '../stores/rag'
|
||||
@ -199,13 +199,16 @@ async function sendQuery(): Promise<void> {
|
||||
const onContext = (data: unknown) => { store.chunks = (data as { chunks: Chunk[] }).chunks }
|
||||
const onDelta = (data: unknown) => {
|
||||
if (firstDelta) { firstDelta = false; stopWaitTimer() }
|
||||
store.rawAnswer += (data as { delta: string }).delta
|
||||
const delta = (data as { delta: string }).delta
|
||||
store.rawAnswer += delta
|
||||
if (ttsEnabled.value) ttsPlayer.append(delta)
|
||||
scrollToBottom()
|
||||
}
|
||||
const onDone = (data: unknown) => {
|
||||
stopWaitTimer()
|
||||
store.querying = false
|
||||
queryStage.value = ''
|
||||
if (ttsEnabled.value) ttsPlayer.flush()
|
||||
const stats = (data as { stats?: InferStats | null }).stats
|
||||
if (stats) inferStats.value = stats
|
||||
cleanup()
|
||||
@ -214,6 +217,7 @@ async function sendQuery(): Promise<void> {
|
||||
stopWaitTimer()
|
||||
store.querying = false
|
||||
queryStage.value = ''
|
||||
if (ttsEnabled.value) ttsPlayer.flush()
|
||||
message.error((data as { message: string }).message)
|
||||
cleanup()
|
||||
}
|
||||
@ -255,13 +259,16 @@ async function sendVisionQuery(): Promise<void> {
|
||||
|
||||
const onDelta = (data: unknown) => {
|
||||
if (firstDelta) { firstDelta = false; stopWaitTimer() }
|
||||
store.rawAnswer += (data as { delta: string }).delta
|
||||
const delta = (data as { delta: string }).delta
|
||||
store.rawAnswer += delta
|
||||
if (ttsEnabled.value) ttsPlayer.append(delta)
|
||||
scrollToBottom()
|
||||
}
|
||||
const onDone = (data: unknown) => {
|
||||
stopWaitTimer()
|
||||
store.querying = false
|
||||
queryStage.value = ''
|
||||
if (ttsEnabled.value) ttsPlayer.flush()
|
||||
const stats = (data as { stats?: InferStats | null }).stats
|
||||
if (stats) inferStats.value = stats
|
||||
cleanup()
|
||||
@ -270,6 +277,7 @@ async function sendVisionQuery(): Promise<void> {
|
||||
stopWaitTimer()
|
||||
store.querying = false
|
||||
queryStage.value = ''
|
||||
if (ttsEnabled.value) ttsPlayer.flush()
|
||||
message.error((data as { message: string }).message)
|
||||
cleanup()
|
||||
}
|
||||
@ -545,13 +553,6 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => store.querying, (querying) => {
|
||||
// 答案流式生成结束后,整段朗读(先播"开始播报")
|
||||
if (!querying && ttsEnabled.value && store.rawAnswer) {
|
||||
ttsPlayer.speakWithAnnouncement(store.rawAnswer)
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
stopWaitTimer()
|
||||
if (hoverTimer) clearTimeout(hoverTimer)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user