fix: stt streaming response handler

This commit is contained in:
jialin
2026-03-17 16:35:55 +08:00
committed by jialin
parent 49a60c25af
commit c29ad1270b
3 changed files with 34 additions and 27 deletions
@@ -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') {
+1 -7
View File
@@ -68,7 +68,6 @@ const GroundSTT: React.FC<MessageProps> = 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<MessageProps> = 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<MessageProps> = 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<MessageProps> = forwardRef((props, ref) => {
<div
style={{
padding: '8px 14px',
lineHeight: '20px',
lineHeight: '22px',
display: 'flex',
justifyContent: 'center',
wordBreak: 'break-word'
+13
View File
@@ -178,6 +178,19 @@ export const readStreamData = async (
try {
textBuffer += decoder.decode(value, { stream: true });
// Check if it's a pure JSON error response (not SSE format)
if (!textBuffer.startsWith('data:') && !textBuffer.startsWith('error:')) {
try {
const jsonData = JSON.parse(textBuffer);
bufferManager.add({ error: jsonData });
textBuffer = '';
throttledCallback();
continue;
} catch {
// Not a complete JSON yet, might be SSE format or incomplete data
}
}
if (textBuffer.startsWith('error:')) {
const errorStr = textBuffer.slice(7).trim();
const jsonData = JSON.parse(errorStr);