From c29ad1270ba12fb957f40bc2f2a634f00820aa3b Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 4 Mar 2026 17:14:55 +0800 Subject: [PATCH] fix: stt streaming response handler --- .../playground/speech/hooks/use-stream-stt.ts | 40 +++++++++---------- src/pages/playground/speech/stt.tsx | 8 +--- src/utils/fetch-chunk-data.ts | 13 ++++++ 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/pages/playground/speech/hooks/use-stream-stt.ts b/src/pages/playground/speech/hooks/use-stream-stt.ts index af2552fa..e5d9305c 100644 --- a/src/pages/playground/speech/hooks/use-stream-stt.ts +++ b/src/pages/playground/speech/hooks/use-stream-stt.ts @@ -2,6 +2,7 @@ import { fetchChunkedDataPostFormData, readStreamData } from '@/utils/fetch-chunk-data'; +import _ from 'lodash'; import { useCallback, useRef, useState } from 'react'; import { AUDIO_SPEECH_TO_TEXT_API } from '../../apis'; import { extractErrorMessage } from '../../config'; @@ -72,30 +73,29 @@ export const useStreamSTT = (params?: UseStreamSTTParams) => { await readStreamData( reader, decoder, - (chunks: any[]) => { - chunks.forEach((chunk) => { - if (chunk.error) { - const errorMessage = extractErrorMessage(chunk.error); - setError({ - error: true, - errorMessage - }); - params?.onError?.(errorMessage); - return; - } + (chunk: any) => { + if (chunk.error) { + const errorMessage = extractErrorMessage(chunk.error); + setError({ + error: true, + errorMessage + }); + params?.onError?.(errorMessage); + return; + } else { + const deltaContent = + _.get(chunk, 'choices.0.delta.content', '') === null + ? '' + : _.get(chunk, 'choices.0.delta.content', ''); - // STT stream response format: { text: "..." } - if (chunk.text) { - fullText += chunk.text; - params?.onChunk?.(fullText); - setProgress((prev) => prev + 1); - } - }); + fullText += deltaContent; + params?.onChunk?.(fullText); + setProgress((prev) => prev + 1); + } }, - 100 // throttle delay + 100 ); - // Stream completed params?.onComplete?.(fullText); } catch (err: any) { if (err.name === 'AbortError') { diff --git a/src/pages/playground/speech/stt.tsx b/src/pages/playground/speech/stt.tsx index 31fa5180..1fb0dc44 100644 --- a/src/pages/playground/speech/stt.tsx +++ b/src/pages/playground/speech/stt.tsx @@ -68,7 +68,6 @@ const GroundSTT: React.FC = forwardRef((props, ref) => { const { initialize, updateScrollerPosition } = useOverlayScroller(); - // Initialize non-stream STT hook const nonStreamSTT = useNonStreamSTT({ onSuccess: (result) => { setMessageList([ @@ -86,10 +85,8 @@ const GroundSTT: React.FC = forwardRef((props, ref) => { } }); - // Initialize stream STT hook const streamSTT = useStreamSTT({ onChunk: (text) => { - // Update message list with streaming text setMessageList([ { content: text, @@ -158,12 +155,9 @@ const GroundSTT: React.FC = forwardRef((props, ref) => { }) }; - // Choose stream or non-stream based on parameters if (parameters.stream) { - // Stream mode: text will be updated in real-time await streamSTT.generate(params); } else { - // Non-stream mode: get complete text at once await nonStreamSTT.generate(params, getCanceltToken()); } } catch (error: any) { @@ -417,7 +411,7 @@ const GroundSTT: React.FC = forwardRef((props, ref) => {