let words = []; let currentIndex = 0; let mediaRecorder; let audioChunks = []; let socket; const recordBtn = document.getElementById("recordBtn"); const wordDisplay = document.getElementById("word"); const okBtn = document.getElementById("okBtn"); const ngBtn = document.getElementById("ngBtn"); async function init() { try { const res = await fetch("words.json"); words = await res.json(); if (!Array.isArray(words) || words.length === 0) { console.error("words.json is empty or invalid"); return; } showWord(); // ✅ Correct WebSocket for reverse proxy socket = new WebSocket( `${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}/ws` ); socket.onopen = () => { console.log("WebSocket connected"); }; socket.onerror = (err) => { console.error("WebSocket error:", err); }; socket.onclose = () => { console.warn("WebSocket closed"); }; } catch (err) { console.error("Init error:", err); } } function showWord() { if (!words || words.length === 0) { console.log("words not loaded yet"); return; } if (currentIndex >= words.length) { alert("終了"); return; } const current = words[currentIndex]; if (!current || !current.word) { console.error("Invalid word object:", current); return; } if (current.word === "end") { alert("終了"); return; } wordDisplay.innerText = current.word; } recordBtn.onclick = async () => { if (!mediaRecorder || mediaRecorder.state === "inactive") { startRecording(); } else { mediaRecorder.stop(); } }; async function startRecording() { try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream); mediaRecorder.start(); recordBtn.style.background = "red"; audioChunks = []; mediaRecorder.ondataavailable = e => { audioChunks.push(e.data); }; mediaRecorder.onstop = async () => { recordBtn.style.background = "green"; const blob = new Blob(audioChunks); const arrayBuffer = await blob.arrayBuffer(); // ✅ Safe WebSocket send if (socket && socket.readyState === WebSocket.OPEN) { socket.send(arrayBuffer); console.log("Audio sent"); } else { console.error("WebSocket not connected"); } }; } catch (err) { console.error("Recording error:", err); } } okBtn.onclick = () => { if (currentIndex < words.length - 1) { currentIndex++; showWord(); } else { alert("終了"); } }; ngBtn.onclick = () => { alert("再録音してください"); }; init();