update:为 test 页面增加可配置的本地唤醒词运行时

This commit is contained in:
3030332422
2026-04-10 09:17:22 +08:00
parent c5f82369e5
commit 705b5732a6
23 changed files with 1116 additions and 3 deletions
+3
View File
@@ -3,6 +3,7 @@ import { checkOpusLoaded, initOpusEncoder } from './core/audio/opus-codec.js?v=0
import { getAudioPlayer } from './core/audio/player.js?v=0205';
import { checkMicrophoneAvailability, isHttpNonLocalhost } from './core/audio/recorder.js?v=0205';
import { initMcpTools } from './core/mcp/tools.js?v=0205';
import { startWakewordBridgeListener } from './core/network/wakeword-bridge.js?v=0205';
import { uiController } from './ui/controller.js?v=0205';
import { log } from './utils/logger.js?v=0205';
@@ -43,6 +44,8 @@ class App {
await this.audioPlayer.start();
// 初始化MCP工具
initMcpTools();
// 初始化本地唤醒事件监听
startWakewordBridgeListener();
// 检查麦克风可用性
await this.checkMicrophoneAvailability();
// 检查摄像头可用性
@@ -0,0 +1,92 @@
import { uiController } from '../../ui/controller.js?v=0205';
import { log } from '../../utils/logger.js?v=0205';
const BRIDGE_URL_CANDIDATES = [
`${window.location.origin}/events`
];
let wakewordEventSource = null;
export function startWakewordBridgeListener() {
if (wakewordEventSource) {
return wakewordEventSource;
}
log('正在连接本地唤醒事件桥...', 'info');
tryConnect(0);
return wakewordEventSource;
}
function tryConnect(index) {
if (index >= BRIDGE_URL_CANDIDATES.length) {
log('未能连接到本地唤醒事件桥,请确认 test runtime 已启动', 'warning');
return null;
}
const bridgeUrl = BRIDGE_URL_CANDIDATES[index];
try {
wakewordEventSource = new EventSource(bridgeUrl);
wakewordEventSource.onopen = () => {
log(`本地唤醒事件桥已连接: ${bridgeUrl}`, 'success');
};
wakewordEventSource.onmessage = async (event) => {
try {
const message = JSON.parse(event.data);
if (message.type === 'bridge_connected') {
log('本地唤醒监听已就绪', 'info');
return;
}
if (message.type === 'service_ready') {
log('本地唤醒服务已启动', 'info');
return;
}
if (message.type === 'service_stopping') {
log('本地唤醒服务正在停止', 'warning');
return;
}
if (message.type === 'wake_word_detected') {
const wakeWord = message.payload?.wake_word || '唤醒词';
log(`检测到本地唤醒事件: ${wakeWord}`, 'info');
await uiController.triggerWakewordDial(wakeWord);
}
} catch (error) {
log(`解析本地唤醒事件失败: ${error.message}`, 'error');
}
};
wakewordEventSource.onerror = () => {
log(`本地唤醒事件桥连接异常: ${bridgeUrl}`, 'warning');
if (wakewordEventSource) {
wakewordEventSource.close();
wakewordEventSource = null;
}
if (index + 1 < BRIDGE_URL_CANDIDATES.length) {
log(`尝试备用地址: ${BRIDGE_URL_CANDIDATES[index + 1]}`, 'info');
tryConnect(index + 1);
return;
}
log('请确认当前页面由 test runtime 启动,并且 /events 可访问', 'warning');
};
return wakewordEventSource;
} catch (error) {
log(`启动本地唤醒监听失败: ${error.message}`, 'error');
return tryConnect(index + 1);
}
}
export function stopWakewordBridgeListener() {
if (!wakewordEventSource) {
return;
}
wakewordEventSource.close();
wakewordEventSource = null;
}