let mediaRecorder; let audioChunks = []; let audioContext; let dataArray; let animationId; let audioOutSource; console.log("Asking for Audio permissions..."); window.addEventListener("load", async (event) => { await navigator.mediaDevices.getUserMedia({ audio: true }); }); function startButtonPulse(analyser) { const button = document.querySelector('#recordbutton'); function updateScale(analyser) { if (!analyser) return; analyser.getByteTimeDomainData(dataArray); let sum = 0; for (let i = 0; i < dataArray.length; i++) { const value = dataArray[i] - 128; sum += value * value; } const volume = Math.sqrt(sum / dataArray.length); const scale = 1 + Math.min(volume / 25, 0.4); // Scales from 1.0 to 1.2 button.style.transform = `scale(${scale})`; animationId = requestAnimationFrame(function() { updateScale(analyser); }); } updateScale(analyser); } function stopButtonPulse() { cancelAnimationFrame(animationId); const button = document.querySelector('#recordbutton'); button.style.transform = 'scale(1)'; } const startPlayback = async () => { const audio_out = document.querySelector('#audioout'); try { console.log("Started playback!"); // Audio analysis if (!audioOutSource) { audioContext = new AudioContext(); audioOutSource = audioContext.createMediaElementSource(audio_out); analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; dataArray = new Uint8Array(analyser.frequencyBinCount); audioOutSource.connect(analyser); analyser.connect(audioContext.destination); } startButtonPulse(analyser); await audio_out.play(); } catch (err) { console.error('Something happend oh no!', err); alert('Some error happened during playback! :('); } } const stopPlayback = async () => { const audio_out = document.querySelector('#audioout'); if (audio_out) { stopButtonPulse(); } } const startRecording = async () => { try { navigator.permissions.query({ name: "microphone" }).then(async (result) => { if (result.state === "granted") { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream); audioChunks = []; console.log("Started recording!"); // Audio analysis audioContext = new AudioContext(); analyser = audioContext.createAnalyser(); const source = audioContext.createMediaStreamSource(stream); analyser.fftSize = 2048; dataArray = new Uint8Array(analyser.frequencyBinCount); source.connect(analyser); startButtonPulse(analyser); mediaRecorder.ondataavailable = async event => { if (event.data.size > 0) { console.log("audio available!"); audioChunks.push(event.data); url = "/api/v1/upload"; if (mediaRecorder.state === 'inactive') { url = "/api/v1/send"; } fetch(url, { method: 'POST', body: event.data, }); } }; mediaRecorder.onstop = async () => { console.log("Stopped recording!"); stopButtonPulse(); }; mediaRecorder.start(1000); } }); } catch (err) { console.error('Microphone access denied or error:', err); alert('Please allow microphone access to record audio.'); } }; const stopRecording = () => { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); } };