From cb51e7c2ef95851dcedef4ff4ed50c3dfbd097a8 Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Fri, 29 May 2026 20:57:29 +0800 Subject: [PATCH 1/8] Use room input audio by default --- app-config.ts | 12 ++++++++---- hooks/useRoom.ts | 41 ++++++++++++++++++----------------------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/app-config.ts b/app-config.ts index 08c0c8c16..fdcb0c076 100644 --- a/app-config.ts +++ b/app-config.ts @@ -46,6 +46,9 @@ export interface AppConfig { defaultVideoTrack?: string; // 默认选择的视频轨道ID } +const frontdeskVideoTrackName = + process.env.NEXT_PUBLIC_FRONTDESK_VIDEO_TRACK_NAME || 'xunfei_video_track'; + export const APP_CONFIG_DEFAULTS: AppConfig = { companyName: 'Lexmount', pageTitle: 'Lexmount Voice Agent', @@ -68,7 +71,8 @@ export const APP_CONFIG_DEFAULTS: AppConfig = { // 音频过滤配置 excludeAudioTracks: [ - 'xunfei_audio_track' + 'xunfei_audio_track', + 'room_audio' ], // 要排除的音频轨道名称列表 // 调试配置 @@ -95,14 +99,14 @@ export const APP_CONFIG_DEFAULTS: AppConfig = { description: '系统默认摄像头设备', }, { - id: 'xunfei_video_track', + id: frontdeskVideoTrackName, label: '人脸检测频道', type: 'livekit', - livekitTrackName: 'xunfei_video_track', + livekitTrackName: frontdeskVideoTrackName, enabled: true, icon: '📡', description: '讯飞人脸检测预览', }, ], - defaultVideoTrack: 'xunfei_video_track', // 默认选择用户指定的轨道 + defaultVideoTrack: frontdeskVideoTrackName, // 默认选择用户指定的轨道 }; diff --git a/hooks/useRoom.ts b/hooks/useRoom.ts index 177a5d55c..5ea5a945f 100644 --- a/hooks/useRoom.ts +++ b/hooks/useRoom.ts @@ -72,31 +72,26 @@ export function useRoom(appConfig: AppConfig) { setIsSessionActive(true); if (room.state === 'disconnected') { - const { isPreConnectBufferEnabled } = appConfig; - Promise.all([ - room.localParticipant.setMicrophoneEnabled(true, undefined, { - preConnectBuffer: isPreConnectBufferEnabled, - }), - tokenSource - .fetch({ agentName: appConfig.agentName }) - .then((connectionDetails) => - room.connect(connectionDetails.serverUrl, connectionDetails.participantToken) - ), - ]).catch((error) => { - if (aborted.current) { - // Once the effect has cleaned up after itself, drop any errors - // - // These errors are likely caused by this effect rerunning rapidly, - // resulting in a previous run `disconnect` running in parallel with - // a current run `connect` - return; - } + tokenSource + .fetch({ agentName: appConfig.agentName }) + .then((connectionDetails) => + room.connect(connectionDetails.serverUrl, connectionDetails.participantToken) + ) + .catch((error) => { + if (aborted.current) { + // Once the effect has cleaned up after itself, drop any errors + // + // These errors are likely caused by this effect rerunning rapidly, + // resulting in a previous run `disconnect` running in parallel with + // a current run `connect` + return; + } - toastAlert({ - title: 'There was an error connecting to the agent', - description: `${error.name}: ${error.message}`, + toastAlert({ + title: 'There was an error connecting to the agent', + description: `${error.name}: ${error.message}`, + }); }); - }); } }, [room, appConfig, tokenSource]); From 131a74c027af6e2addfd45a62abb25b8efa9cd40 Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Tue, 2 Jun 2026 11:17:40 +0800 Subject: [PATCH 2/8] fix: Recognize room input transcriptions --- app-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-config.ts b/app-config.ts index fdcb0c076..c23a3fd68 100644 --- a/app-config.ts +++ b/app-config.ts @@ -85,7 +85,7 @@ export const APP_CONFIG_DEFAULTS: AppConfig = { enableSmartParticipantMatching: true, // 启用智能参与者匹配,解决自定义音频track的字幕显示问题 enableTranscriptionDebug: process.env.NEXT_PUBLIC_SHOW_TRANSCRIPTION_DEBUG === 'true' || false, // 转录调试日志 showTranscriptByDefault: true, // 默认显示字幕窗口,交互时直接可见 - userTranscriptionIdentities: ['xunfei_service_agent'], // 用户转录身份标识(自定义音频track) + userTranscriptionIdentities: ['xunfei_service_agent', 'room_input'], // 用户转录身份标识(自定义音频track) showParticipantNames: false, // 默认不显示参与者名称(user、agent-xxx等) // 视频轨道配置 From 85843763a59deffbce0dc1db048edac785c61155 Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Tue, 2 Jun 2026 11:24:02 +0800 Subject: [PATCH 3/8] fix: Document frontdesk env defaults --- .env.example | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 4b7e54680..5b4713124 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,19 @@ -# Enviroment variables needed to connect to the LiveKit server. +# Environment variables needed to connect to the LiveKit server. LIVEKIT_API_KEY= LIVEKIT_API_SECRET= LIVEKIT_URL=wss://.livekit.cloud +# Optional API endpoint override. +NEXT_PUBLIC_CONN_DETAILS_ENDPOINT=/api/connection-details + +# Frontdesk room input tracks. +# Defaults to xunfei_video_track when omitted. +NEXT_PUBLIC_FRONTDESK_VIDEO_TRACK_NAME=room_video + +# Optional debug flags. +NEXT_PUBLIC_SHOW_AUDIO_DEBUG=false +NEXT_PUBLIC_ENABLE_GLOBAL_DEBUG=false +NEXT_PUBLIC_SHOW_TRANSCRIPTION_DEBUG=false # Internally used environment variables NEXT_PUBLIC_APP_CONFIG_ENDPOINT= From 377cb073672e22c94d9594beb061ee34afb03cb2 Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Tue, 2 Jun 2026 11:26:09 +0800 Subject: [PATCH 4/8] fix: Keep frontdesk env example focused --- .env.example | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.env.example b/.env.example index 5b4713124..f5a97baf3 100644 --- a/.env.example +++ b/.env.example @@ -10,11 +10,6 @@ NEXT_PUBLIC_CONN_DETAILS_ENDPOINT=/api/connection-details # Defaults to xunfei_video_track when omitted. NEXT_PUBLIC_FRONTDESK_VIDEO_TRACK_NAME=room_video -# Optional debug flags. -NEXT_PUBLIC_SHOW_AUDIO_DEBUG=false -NEXT_PUBLIC_ENABLE_GLOBAL_DEBUG=false -NEXT_PUBLIC_SHOW_TRANSCRIPTION_DEBUG=false - # Internally used environment variables NEXT_PUBLIC_APP_CONFIG_ENDPOINT= SANDBOX_ID= From 97f92f4b2a268a8ce7c3d0936821f4d41583355b Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Tue, 2 Jun 2026 20:01:28 +0800 Subject: [PATCH 5/8] fix: route xunfei frontdesk input UI --- app-config.ts | 19 ++++------ components/app/session-view.tsx | 2 +- components/livekit/chat-entry.tsx | 14 +++++-- hooks/useRoom.ts | 61 +++++++++++++++++++------------ 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/app-config.ts b/app-config.ts index c23a3fd68..a87316062 100644 --- a/app-config.ts +++ b/app-config.ts @@ -30,10 +30,10 @@ export interface AppConfig { excludeAudioTracks: string[]; showAudioFilterDebug?: boolean; - + // 全局调试配置 enableGlobalDebug?: boolean; // 全局调试开关,控制所有调试信息的显示 - + // 字幕和转录配置 enableSmartParticipantMatching?: boolean; // 启用智能参与者匹配 enableTranscriptionDebug?: boolean; // 启用转录调试日志 @@ -68,24 +68,21 @@ export const APP_CONFIG_DEFAULTS: AppConfig = { // for LiveKit Cloud Sandbox sandboxId: undefined, agentName: undefined, - + // 音频过滤配置 - excludeAudioTracks: [ - 'xunfei_audio_track', - 'room_audio' - ], // 要排除的音频轨道名称列表 - + excludeAudioTracks: ['xunfei_audio_track', 'room_audio'], // 要排除的音频轨道名称列表 + // 调试配置 showAudioFilterDebug: process.env.NEXT_PUBLIC_SHOW_AUDIO_DEBUG === 'true' || false, // 是否显示音频过滤调试组件 - + // 全局调试配置 enableGlobalDebug: process.env.NEXT_PUBLIC_ENABLE_GLOBAL_DEBUG === 'true' || false, // 全局调试开关 - + // 字幕和转录配置 enableSmartParticipantMatching: true, // 启用智能参与者匹配,解决自定义音频track的字幕显示问题 enableTranscriptionDebug: process.env.NEXT_PUBLIC_SHOW_TRANSCRIPTION_DEBUG === 'true' || false, // 转录调试日志 showTranscriptByDefault: true, // 默认显示字幕窗口,交互时直接可见 - userTranscriptionIdentities: ['xunfei_service_agent', 'room_input'], // 用户转录身份标识(自定义音频track) + userTranscriptionIdentities: ['xunfei_service_agent', 'room_input', 'room_audio_input'], // 用户转录身份标识(自定义音频track) showParticipantNames: false, // 默认不显示参与者名称(user、agent-xxx等) // 视频轨道配置 diff --git a/components/app/session-view.tsx b/components/app/session-view.tsx index 0acb3157f..b25fdc1f8 100644 --- a/components/app/session-view.tsx +++ b/components/app/session-view.tsx @@ -78,7 +78,7 @@ export const SessionView = ({ const controls: ControlBarControls = { leave: true, - microphone: true, + microphone: false, chat: appConfig.supportsChatInput, camera: appConfig.supportsVideoInput, screenShare: appConfig.supportsVideoInput, diff --git a/components/livekit/chat-entry.tsx b/components/livekit/chat-entry.tsx index c9a7fbfad..93678273f 100644 --- a/components/livekit/chat-entry.tsx +++ b/components/livekit/chat-entry.tsx @@ -33,13 +33,17 @@ export const ChatEntry = ({
  • {name && {name}} @@ -50,8 +54,10 @@ export const ChatEntry = ({
    {message} diff --git a/hooks/useRoom.ts b/hooks/useRoom.ts index 5ea5a945f..4e1830125 100644 --- a/hooks/useRoom.ts +++ b/hooks/useRoom.ts @@ -5,7 +5,13 @@ import { toastAlert } from '@/components/livekit/alert-toast'; export function useRoom(appConfig: AppConfig) { const aborted = useRef(false); - const room = useMemo(() => new Room(), []); + const room = useMemo( + () => + new Room({ + reconnectPolicy: { nextRetryDelayInMs: () => null }, + }), + [] + ); const [isSessionActive, setIsSessionActive] = useState(false); useEffect(() => { @@ -68,36 +74,45 @@ export function useRoom(appConfig: AppConfig) { [appConfig] ); - const startSession = useCallback(() => { - setIsSessionActive(true); + const startSession = useCallback(async () => { + try { + if (room.state !== 'disconnected') { + await room.disconnect(); + } - if (room.state === 'disconnected') { - tokenSource - .fetch({ agentName: appConfig.agentName }) - .then((connectionDetails) => - room.connect(connectionDetails.serverUrl, connectionDetails.participantToken) - ) - .catch((error) => { - if (aborted.current) { - // Once the effect has cleaned up after itself, drop any errors - // - // These errors are likely caused by this effect rerunning rapidly, - // resulting in a previous run `disconnect` running in parallel with - // a current run `connect` - return; - } + setIsSessionActive(true); + const connectionDetails = await tokenSource.fetch({ agentName: appConfig.agentName }); + await room.connect(connectionDetails.serverUrl, connectionDetails.participantToken); + await room.localParticipant.setMicrophoneEnabled(false); + } catch (error) { + if (aborted.current) { + // Once the effect has cleaned up after itself, drop any errors + // + // These errors are likely caused by this effect rerunning rapidly, + // resulting in a previous run `disconnect` running in parallel with + // a current run `connect` + return; + } - toastAlert({ - title: 'There was an error connecting to the agent', - description: `${error.name}: ${error.message}`, - }); + setIsSessionActive(false); + if (error instanceof Error) { + toastAlert({ + title: 'There was an error connecting to the agent', + description: `${error.name}: ${error.message}`, + }); + } else { + toastAlert({ + title: 'There was an error connecting to the agent', + description: String(error), }); + } } }, [room, appConfig, tokenSource]); const endSession = useCallback(() => { setIsSessionActive(false); - }, []); + room.disconnect(); + }, [room]); return { room, isSessionActive, startSession, endSession }; } From e5781d2db34b07e4137769a6119b3e58be784c8d Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Tue, 2 Jun 2026 20:10:12 +0800 Subject: [PATCH 6/8] revert: keep chat entry styling unchanged --- components/livekit/chat-entry.tsx | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/components/livekit/chat-entry.tsx b/components/livekit/chat-entry.tsx index 93678273f..c9a7fbfad 100644 --- a/components/livekit/chat-entry.tsx +++ b/components/livekit/chat-entry.tsx @@ -33,17 +33,13 @@ export const ChatEntry = ({
  • {name && {name}} @@ -54,10 +50,8 @@ export const ChatEntry = ({
    {message} From b7b99f542a97be6a910b5e1feda59e14ca56baff Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Tue, 2 Jun 2026 20:39:02 +0800 Subject: [PATCH 7/8] fix: keep frontend microphone control available --- components/app/session-view.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/app/session-view.tsx b/components/app/session-view.tsx index b25fdc1f8..0acb3157f 100644 --- a/components/app/session-view.tsx +++ b/components/app/session-view.tsx @@ -78,7 +78,7 @@ export const SessionView = ({ const controls: ControlBarControls = { leave: true, - microphone: false, + microphone: true, chat: appConfig.supportsChatInput, camera: appConfig.supportsVideoInput, screenShare: appConfig.supportsVideoInput, From 8f962db8aefbb7c1f7ff6e1900fb47c3f6ae8e67 Mon Sep 17 00:00:00 2001 From: jinfeng66 Date: Thu, 4 Jun 2026 16:11:10 +0800 Subject: [PATCH 8/8] fix: align room video env example --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index f5a97baf3..a47ae1af0 100644 --- a/.env.example +++ b/.env.example @@ -7,7 +7,7 @@ LIVEKIT_URL=wss://.livekit.cloud NEXT_PUBLIC_CONN_DETAILS_ENDPOINT=/api/connection-details # Frontdesk room input tracks. -# Defaults to xunfei_video_track when omitted. +# Backend room input publishes room_video by default. NEXT_PUBLIC_FRONTDESK_VIDEO_TRACK_NAME=room_video # Internally used environment variables