File size: 1,671 Bytes
05fac2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// ================ 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();
};