feat:语音对话优化

This commit is contained in:
2026-06-14 19:54:22 +08:00
parent 16105f5ac6
commit c3118dd72a
11 changed files with 156 additions and 52 deletions

View File

@@ -13,6 +13,9 @@ interface ChatPanelProps {
messages: ChatMessage[];
currentReply?: string;
connectionStatus: ConnectionStatus;
isProcessing?: boolean;
isVADReady?: boolean;
vadError?: string;
isMicOn?: boolean;
isSpeaking?: boolean;
onSendText?: (text: string) => void;
@@ -34,6 +37,9 @@ export function ChatPanel({
messages,
currentReply,
connectionStatus,
isProcessing,
isVADReady,
vadError,
isMicOn,
isSpeaking,
onSendText,
@@ -144,6 +150,44 @@ export function ChatPanel({
</div>
)}
{/* 连接中状态 */}
{connectionStatus === "connecting" && (
<div className="system-message system-message--info">
<span className="typing-indicator">
<span className="typing-indicator__dot" />
<span className="typing-indicator__dot" />
<span className="typing-indicator__dot" />
</span>
<span>{t("chat.connecting")}</span>
</div>
)}
{/* VAD 初始化中 */}
{isConnected && isVADReady === false && !vadError && (
<div className="system-message system-message--info">
<span className="typing-indicator">
<span className="typing-indicator__dot" />
<span className="typing-indicator__dot" />
<span className="typing-indicator__dot" />
</span>
<span>{t("chat.vadInit")}</span>
</div>
)}
{/* AI 处理中(尚未开始流式输出) */}
{isProcessing && !currentReply && (
<div className="chat-message chat-message--assistant">
<div className="chat-message__role">AI</div>
<div className="chat-message__content">
<span className="typing-indicator">
<span className="typing-indicator__dot" />
<span className="typing-indicator__dot" />
<span className="typing-indicator__dot" />
</span>
</div>
</div>
)}
<div ref={bottomRef} />
</div>

View File

@@ -132,7 +132,7 @@ function getOffscreen(): HTMLCanvasElement {
export function sampleFrame(video: HTMLVideoElement): Uint8ClampedArray | null {
if (video.readyState < 2) return null;
const canvas = getOffscreen();
const ctx = canvas.getContext("2d");
const ctx = canvas.getContext("2d", { willReadFrequently: true });
if (!ctx) return null;
ctx.drawImage(video, 0, 0, DETECT_WIDTH, DETECT_HEIGHT);
return ctx.getImageData(0, 0, DETECT_WIDTH, DETECT_HEIGHT).data;