Spaces:
Running
Running
disable audio buffer
Browse files- src/app/components/Main.tsx +47 -51
src/app/components/Main.tsx
CHANGED
|
@@ -11,8 +11,8 @@ import {
|
|
| 11 |
streamChat,
|
| 12 |
type ChatSource,
|
| 13 |
} from "../../services/api";
|
| 14 |
-
import { textToSpeech } from "../../services/voiceApi";
|
| 15 |
-
import { replayAudio } from "../../audio/AudioPlayer";
|
| 16 |
import ChatLayout from "./chat/ChatLayout";
|
| 17 |
import Sidebar from "./chat/Sidebar";
|
| 18 |
import ChatWindow from "./chat/ChatWindow";
|
|
@@ -401,62 +401,58 @@ export default function Main() {
|
|
| 401 |
}
|
| 402 |
}, [user, ensureRoom]);
|
| 403 |
|
| 404 |
-
const cancelTtsRef = useRef<(() => void) | null>(null);
|
| 405 |
-
|
| 406 |
-
const playTtsAudio = useCallback(async (
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
): Promise<{ chunks: ArrayBuffer[]; sampleRate: number }> => {
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
// TTS failure is non-fatal
|
| 427 |
-
return { chunks: [], sampleRate: 24000 };
|
| 428 |
-
}
|
| 429 |
-
}, []);
|
| 430 |
|
| 431 |
const { voiceState, start, stop, stopRecording, setStateExternal, isActive: isVoiceActive } = useVoiceSession({
|
| 432 |
onTranscript: async (text: string) => {
|
| 433 |
// console.log("[onTranscript] received:", text);
|
| 434 |
// Pass skipReload=true so handleSend returns immediately after streaming
|
| 435 |
// without waiting for GET /room — TTS starts with zero extra delay.
|
| 436 |
-
|
| 437 |
-
const { audioText = "", assistantMsgId } = result ?? {};
|
| 438 |
// console.log("[onTranscript] handleSend done, audioText:", audioText ? audioText.slice(0, 40) : "(empty)");
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
}
|
|
|
|
| 460 |
if (isVoiceActiveRef.current) setVoiceStateRef.current?.("IDLE");
|
| 461 |
},
|
| 462 |
sessionParams: {},
|
|
|
|
| 11 |
streamChat,
|
| 12 |
type ChatSource,
|
| 13 |
} from "../../services/api";
|
| 14 |
+
// import { textToSpeech } from "../../services/voiceApi";
|
| 15 |
+
// import { replayAudio } from "../../audio/AudioPlayer";
|
| 16 |
import ChatLayout from "./chat/ChatLayout";
|
| 17 |
import Sidebar from "./chat/Sidebar";
|
| 18 |
import ChatWindow from "./chat/ChatWindow";
|
|
|
|
| 401 |
}
|
| 402 |
}, [user, ensureRoom]);
|
| 403 |
|
| 404 |
+
// const cancelTtsRef = useRef<(() => void) | null>(null);
|
| 405 |
+
|
| 406 |
+
// const playTtsAudio = useCallback(async (
|
| 407 |
+
// ttsText: string,
|
| 408 |
+
// onStarted?: () => void,
|
| 409 |
+
// ): Promise<{ chunks: ArrayBuffer[]; sampleRate: number }> => {
|
| 410 |
+
// cancelTtsRef.current?.();
|
| 411 |
+
// cancelTtsRef.current = null;
|
| 412 |
+
// try {
|
| 413 |
+
// const { pcm, sampleRate } = await textToSpeech(ttsText);
|
| 414 |
+
// const durationMs = (pcm.byteLength / 2 / sampleRate) * 1000;
|
| 415 |
+
// const cancel = replayAudio([pcm], sampleRate);
|
| 416 |
+
// cancelTtsRef.current = cancel;
|
| 417 |
+
// onStarted?.();
|
| 418 |
+
// await new Promise<void>((resolve) => setTimeout(resolve, durationMs + 150));
|
| 419 |
+
// cancel();
|
| 420 |
+
// cancelTtsRef.current = null;
|
| 421 |
+
// return { chunks: [pcm], sampleRate };
|
| 422 |
+
// } catch {
|
| 423 |
+
// return { chunks: [], sampleRate: 24000 };
|
| 424 |
+
// }
|
| 425 |
+
// }, []);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
const { voiceState, start, stop, stopRecording, setStateExternal, isActive: isVoiceActive } = useVoiceSession({
|
| 428 |
onTranscript: async (text: string) => {
|
| 429 |
// console.log("[onTranscript] received:", text);
|
| 430 |
// Pass skipReload=true so handleSend returns immediately after streaming
|
| 431 |
// without waiting for GET /room — TTS starts with zero extra delay.
|
| 432 |
+
await handleSend(text, true);
|
|
|
|
| 433 |
// console.log("[onTranscript] handleSend done, audioText:", audioText ? audioText.slice(0, 40) : "(empty)");
|
| 434 |
+
// TTS playback after tap-to-speak is disabled
|
| 435 |
+
// if (audioText && isVoiceActiveRef.current) {
|
| 436 |
+
// const { chunks, sampleRate } = await playTtsAudio(audioText, () => {
|
| 437 |
+
// if (isVoiceActiveRef.current) setVoiceStateRef.current?.("SPEAKING");
|
| 438 |
+
// });
|
| 439 |
+
// if (assistantMsgId && chunks.length > 0) {
|
| 440 |
+
// setChats((prev) =>
|
| 441 |
+
// prev.map((chat) =>
|
| 442 |
+
// chat.id === currentChatIdRef.current
|
| 443 |
+
// ? {
|
| 444 |
+
// ...chat,
|
| 445 |
+
// messages: chat.messages.map((m) =>
|
| 446 |
+
// m.id === assistantMsgId
|
| 447 |
+
// ? { ...m, audioChunks: chunks, audioSampleRate: sampleRate }
|
| 448 |
+
// : m
|
| 449 |
+
// ),
|
| 450 |
+
// }
|
| 451 |
+
// : chat
|
| 452 |
+
// )
|
| 453 |
+
// );
|
| 454 |
+
// }
|
| 455 |
+
// }
|
| 456 |
if (isVoiceActiveRef.current) setVoiceStateRef.current?.("IDLE");
|
| 457 |
},
|
| 458 |
sessionParams: {},
|