Add camera drawer for voice demo
This commit is contained in:
@@ -23,6 +23,19 @@ const WS_LOG_GROUP_KEYS = {
|
||||
TEXT_DELTA: "recv:response.text.delta",
|
||||
AUDIO_SEND: "send:input.audio",
|
||||
};
|
||||
const CAMERA_DONE_TEXT = "【拍摄完成】";
|
||||
const CAMERA_STATE_PROMPTS = {
|
||||
2000: "请对准车辆碰撞部位拍摄照片。",
|
||||
2001: "请对准车辆碰撞部位拍摄照片。",
|
||||
2002: "请对准被撞物品拍摄照片。",
|
||||
2003: "请切换摄像头对准本人拍摄一张正面照片。",
|
||||
2010: "请对准第一辆车碰撞部位拍摄。",
|
||||
2011: "请对准第一辆车碰撞部位拍摄。",
|
||||
2012: "请对准第二辆车碰撞部位拍摄。",
|
||||
2013: "请对准第二方车辆侧后方,看清车牌拍摄。",
|
||||
2014: "请拍摄另一方驾驶人的正面照片。",
|
||||
2015: "请切换前置摄像头对准本人拍摄一张正面照片。",
|
||||
};
|
||||
|
||||
function defaultWsUrl() {
|
||||
const scheme = location.protocol === "https:" ? "wss:" : "ws:";
|
||||
@@ -34,6 +47,7 @@ const els = {
|
||||
connectBtn: document.getElementById("connect-btn"),
|
||||
statusDot: document.getElementById("status-dot"),
|
||||
statusText: document.getElementById("status-text"),
|
||||
conversation: document.getElementById("conversation"),
|
||||
chatLog: document.getElementById("chat-log"),
|
||||
micBtn: document.getElementById("mic-btn"),
|
||||
micSelect: document.getElementById("mic-select"),
|
||||
@@ -42,6 +56,10 @@ const els = {
|
||||
botIndicator: document.getElementById("bot-indicator"),
|
||||
stateIndicator: document.getElementById("state-indicator"),
|
||||
stateLabel: document.getElementById("state-label"),
|
||||
cameraDrawer: document.getElementById("camera-drawer"),
|
||||
cameraState: document.getElementById("camera-state"),
|
||||
cameraQuestion: document.getElementById("camera-question"),
|
||||
cameraDoneBtn: document.getElementById("camera-done-btn"),
|
||||
clearBtn: document.getElementById("clear-btn"),
|
||||
clearWsLogBtn: document.getElementById("clear-ws-log-btn"),
|
||||
wsLog: document.getElementById("ws-log"),
|
||||
@@ -75,6 +93,7 @@ const state = {
|
||||
// Chat state.
|
||||
currentAssistantBubble: null,
|
||||
assistantState: "",
|
||||
cameraState: "",
|
||||
|
||||
// VU meter smoothing.
|
||||
meterLevel: 0,
|
||||
@@ -121,6 +140,7 @@ function setMicSelectEnabled() {
|
||||
function setComposerEnabled(enabled) {
|
||||
els.textInput.disabled = !enabled;
|
||||
els.sendBtn.disabled = !enabled || els.textInput.value.trim().length === 0;
|
||||
setCameraButtonEnabled();
|
||||
}
|
||||
|
||||
function setBotIndicator(active) {
|
||||
@@ -134,6 +154,37 @@ function setAssistantState(value) {
|
||||
els.stateIndicator.classList.toggle("is-active", Boolean(text));
|
||||
els.stateLabel.textContent = label ? `State ${label}` : "State -";
|
||||
els.stateIndicator.title = label ? `Assistant state: ${text}` : "Assistant state";
|
||||
syncCameraDrawer(text);
|
||||
}
|
||||
|
||||
function setCameraButtonEnabled() {
|
||||
if (!els.cameraDoneBtn) return;
|
||||
els.cameraDoneBtn.disabled =
|
||||
!state.connected || !state.cameraState ||
|
||||
!state.ws || state.ws.readyState !== WebSocket.OPEN;
|
||||
}
|
||||
|
||||
function syncCameraDrawer(value) {
|
||||
const prompt = CAMERA_STATE_PROMPTS[value];
|
||||
const open = Boolean(prompt);
|
||||
state.cameraState = open ? value : "";
|
||||
els.cameraDrawer.classList.toggle("is-open", open);
|
||||
els.conversation.classList.toggle("has-camera", open);
|
||||
els.cameraDrawer.setAttribute("aria-hidden", open ? "false" : "true");
|
||||
if (open) {
|
||||
els.cameraState.textContent = `State ${value}`;
|
||||
els.cameraQuestion.textContent = prompt;
|
||||
} else {
|
||||
els.cameraState.textContent = "State -";
|
||||
els.cameraQuestion.textContent = "";
|
||||
}
|
||||
setCameraButtonEnabled();
|
||||
}
|
||||
|
||||
function updateCameraQuestion(text) {
|
||||
const value = typeof text === "string" ? text.trim() : "";
|
||||
if (!state.cameraState || !value) return;
|
||||
els.cameraQuestion.textContent = value;
|
||||
}
|
||||
|
||||
function addBubble(role, text) {
|
||||
@@ -761,6 +812,7 @@ function handleAssistantFinal(text, interrupted) {
|
||||
if (interrupted) {
|
||||
state.currentAssistantBubble.classList.add("bubble--interrupted");
|
||||
}
|
||||
updateCameraQuestion(text);
|
||||
state.currentAssistantBubble = null;
|
||||
scrollChatToBottom();
|
||||
}
|
||||
@@ -883,6 +935,7 @@ async function connect() {
|
||||
wsSend(JSON.stringify(startMessage));
|
||||
addBubble("system", "Session started.");
|
||||
setComposerEnabled(true);
|
||||
setCameraButtonEnabled();
|
||||
els.textInput.focus();
|
||||
});
|
||||
|
||||
@@ -928,6 +981,7 @@ async function connect() {
|
||||
setMicButton();
|
||||
setMicSelectEnabled();
|
||||
setComposerEnabled(false);
|
||||
setCameraButtonEnabled();
|
||||
setBotIndicator(false);
|
||||
finalizeWsLogGroup();
|
||||
addWsLog(
|
||||
@@ -1019,6 +1073,11 @@ els.clearWsLogBtn.addEventListener("click", () => {
|
||||
clearWsLog();
|
||||
});
|
||||
|
||||
els.cameraDoneBtn.addEventListener("click", () => {
|
||||
if (!state.cameraState) return;
|
||||
sendText(CAMERA_DONE_TEXT);
|
||||
});
|
||||
|
||||
function autosizeTextarea() {
|
||||
const ta = els.textInput;
|
||||
ta.style.height = "auto";
|
||||
|
||||
Reference in New Issue
Block a user