// ================ CONFIG =================== const BASE_WS = "wss://tricuspidate-tournois-michale.ngrok-free.dev"; // THAY BẰNG NGROK CỦA BẠN // =========================================== let ws = null; let mediaRecorder = null; let currentEmotion = "wenrou"; function setEmotion(e) { currentEmotion = e; const map = { "wenrou": "wenrou(温柔)", "sajiao": "sajiao(撒娇)", "tiaopi": "tiaopi(调皮)", "nuanxin": "nuanxin(暖心)", }; document.getElementById("emotionLabel").textContent = map[e]; } document.getElementById("startBtn").onclick = async () => { const WS_URL = `${BASE_WS}/ws?emotion=${currentEmotion}`; ws = new WebSocket(WS_URL); ws.onopen = () => console.log("WS connected:", WS_URL); ws.onmessage = async (event) => { let data = JSON.parse(event.data); // update subtitles document.getElementById("userSubtitle").textContent = data.user; document.getElementById("aiSubtitle").textContent = data.ai; // play audio const audio = new Audio("data:audio/mp3;base64," + data.audio); audio.play(); }; // setup microphone const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm" }); mediaRecorder.ondataavailable = async (e) => { const arrayBuffer = await e.data.arrayBuffer(); ws.send(arrayBuffer); }; mediaRecorder.start(300); // 300ms chunk }; document.getElementById("stopBtn").onclick = () => { if (mediaRecorder) mediaRecorder.stop(); if (ws) ws.close(); };