JusTalk_compleate / static /register_record.js
mizzzuno's picture
Update static/register_record.js
480db73 verified
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 = `
<form
action="/submit"
method="POST"
class="flex items-center space-x-2 w-full sm:w-auto"
onsubmit="event.preventDefault();"
>
<input
type="text"
name="name"
placeholder="名前を入力"
value="${userName}"
class="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 bg-gray-700 text-white"
/>
<button type="button" class="record-button" aria-label="音声録音開始">
<div class="record-icon"></div>
</button>
</form>
`;
userDiv
.querySelector(".record-button")
.addEventListener("click", handleRecording);
userList.appendChild(userDiv);
userCount++;
}
}
document.getElementById("add-btn").addEventListener("click", addUser);