let mediaRecorder; let audioChunks = []; let userCount = 0; // 追加されたメンバー数を保持 let isRecording = false; // 録音中かどうかを判定するフラグ let currentRecordingButton = null; // 現在録音中のボタンを保持 let userNames = []; function toggleRecording(button) { button.classList.toggle("recording"); } async function startRecording(button) { if (isRecording && currentRecordingButton !== button) return; // 他の人が録音中なら何もしない isRecording = true; // 録音中に設定 currentRecordingButton = button; // 録音中のボタンを記録 try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, }); mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm" }); audioChunks = []; mediaRecorder.ondataavailable = (e) => audioChunks.push(e.data); mediaRecorder.onstop = () => { sendAudioChunks(audioChunks, button); // ボタン情報を渡す audioChunks = []; isRecording = false; // 録音停止後はフラグを戻す currentRecordingButton = null; // 録音ボタンを解除 }; mediaRecorder.start(); toggleRecording(button); } catch (err) { console.error("マイクアクセスに失敗しました:", err); isRecording = false; // エラー発生時もフラグを戻す currentRecordingButton = null; } } function stopRecording(button) { if (!isRecording) return; // 録音中でない場合は停止しない mediaRecorder.stop(); toggleRecording(button); } function handleRecording(e) { const button = e.target.closest(".record-button"); if (button) { if (isRecording && currentRecordingButton !== button) { // 他の人が録音中なら反応しない return; } if (mediaRecorder && mediaRecorder.state === "recording") { stopRecording(button); } else { startRecording(button); } } } function sendAudioChunks(chunks, button) { // 引数に button を追加 const audioBlob = new Blob(chunks, { type: "audio/wav" }); const reader = new FileReader(); reader.onloadend = () => { const base64String = reader.result.split(",")[1]; // Base64エンコードされた音声データ // フォームの取得方法を変更 const form = button.closest(".user-item")?.querySelector("form") const nameInput = form?.querySelector('input[name="name"]'); const name = nameInput ? nameInput.value : "unknown"; // 名前がない fetch("/upload_base_audio", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ audio_data: base64String, name: name }), }) .then((response) => response.json()) .then((data) => { // エラー処理のみ残す if (data.error) { alert("エラー: " + data.error); console.error(data.details); } // 成功時の処理(ボタンの有効化など) else { console.log("音声データ送信成功:", data); userNames.push(name); // 必要に応じて、ここでUIの変更(ボタンの有効化など)を行う // 例: button.disabled = true; // 送信ボタンを無効化 // 例: button.classList.remove("recording"); //録音中のスタイルを解除 } }) .catch((error) => { console.error("エラー:", error); }); }; reader.readAsDataURL(audioBlob); } // メンバー選択画面表示 function showUserSelect() { window.location.href = "/userselect"; } // Add user function function addUser() { const userName = prompt("ユーザー名を入力してください"); if (userName) { const userList = document.getElementById("people-list"); const userDiv = document.createElement("div"); userDiv.classList.add( "user-item", // 追加 "bg-gray-700", "p-4", "rounded-lg", "text-white", "flex", "justify-between", "items-center", "flex-wrap", // 追加 "gap-3" // 追加 ); userDiv.innerHTML = `
`; userDiv .querySelector(".record-button") .addEventListener("click", handleRecording); userList.appendChild(userDiv); userCount++; } } document.getElementById("add-btn").addEventListener("click", addUser);