Download script.js from LabSoft/LabSoft-AI-Voice-Assistent: direct link, hf CLI and curl.
- Browser
- Download file 5.03 kB
-
https://huggingface.co/spaces/LabSoft/LabSoft-AI-Voice-Assistent/resolve/main/script.js
- Command line
-
hf download hf://spaces/LabSoft/LabSoft-AI-Voice-Assistent/script.js
-
curl -L -o script.js https://huggingface.co/spaces/LabSoft/LabSoft-AI-Voice-Assistent/resolve/main/script.js
5.03 kB
| let audioContext; | |
| let analyser; | |
| let sourceNode; | |
| let mediaRecorder; | |
| let audioChunks = []; | |
| document.addEventListener("DOMContentLoaded", () => { | |
| const audioResponseElement = document.getElementById("audioResponse"); | |
| const micButton = document.getElementById("micButton"); | |
| const blobs = document.querySelectorAll(".blob"); | |
| initAudioContext(audioResponseElement); | |
| function initAudioContext(audioElement) { | |
| audioContext = new (window.AudioContext || window.webkitAudioContext)(); | |
| analyser = audioContext.createAnalyser(); | |
| analyser.fftSize = 64; | |
| if (audioElement && !sourceNode) { | |
| sourceNode = audioContext.createMediaElementSource(audioElement); | |
| sourceNode.connect(analyser); | |
| analyser.connect(audioContext.destination); | |
| } | |
| } | |
| function startWaitAnimation() { | |
| document.getElementById("thought-bubble").style.display = "block"; | |
| micButton.classList.add("disabled"); | |
| micButton.disabled = true; | |
| } | |
| function stopWaitAnimation() { | |
| document.getElementById("thought-bubble").style.display = "none"; | |
| micButton.classList.remove("disabled"); | |
| micButton.disabled = false; | |
| } | |
| function enableMicButton() { | |
| micButton.classList.remove("disabled"); | |
| micButton.disabled = false; | |
| } | |
| function hideBlobs() { | |
| document.querySelector(".blob-container").style.display = "none"; | |
| } | |
| function showBlobs() { | |
| document.querySelector(".blob-container").style.display = "flex"; | |
| } | |
| async function startRecording() { | |
| audioChunks = []; | |
| try { | |
| const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); | |
| mediaRecorder = new MediaRecorder(stream); | |
| mediaRecorder.ondataavailable = (event) => audioChunks.push(event.data); | |
| mediaRecorder.start(); | |
| } catch (error) { | |
| console.error("Error accessing audio devices:", error); | |
| micButton.checked = false; // Uncheck the button in case of an error | |
| stopWaitAnimation(); | |
| } | |
| } | |
| function stopRecording() { | |
| mediaRecorder.stop(); | |
| mediaRecorder.onstop = async () => { | |
| const audioBlob = new Blob(audioChunks, { type: "audio/webm" }); | |
| const audioBase64 = await blobToBase64(audioBlob); | |
| sendAudioToServer(audioBase64); | |
| }; | |
| } | |
| function blobToBase64(blob) { | |
| const reader = new FileReader(); | |
| return new Promise((resolve) => { | |
| reader.onloadend = () => resolve(reader.result.split(",")[1]); | |
| reader.readAsDataURL(blob); | |
| }); | |
| } | |
| function sendAudioToServer(audioBase64) { | |
| fetch( | |
| "https://wnuy6xzt3e.execute-api.eu-central-1.amazonaws.com/Prod/sts/question", | |
| { | |
| method: "POST", | |
| headers: { "Content-Type": "text/plain" }, | |
| body: audioBase64, | |
| } | |
| ) | |
| .then((response) => response.text()) | |
| .then((data) => { | |
| if (data.message === "Question not provided in POST body") { | |
| console.error("Question not provided in POST body"); | |
| stopWaitAnimation(); | |
| enableMicButton(); // Re-enable the microphone button | |
| return; // Stop further processing | |
| } | |
| const audioSrc = `data:audio/wav;base64,${data}`; | |
| audioResponseElement.src = audioSrc; | |
| audioResponseElement.play().then(() => { | |
| visualize(); // Start the visualizer after the audio starts playing | |
| }); | |
| }) | |
| .catch((error) => { | |
| console.error("Error:", error); | |
| stopWaitAnimation(); | |
| }); | |
| } | |
| micButton.addEventListener("change", () => { | |
| hideBlobs(); | |
| if (micButton.checked) { | |
| startRecording(); | |
| } else { | |
| stopRecording(); | |
| startWaitAnimation(); | |
| } | |
| }); | |
| function visualize() { | |
| if (!audioContext) { | |
| console.error("AudioContext not initialized"); | |
| return; | |
| } | |
| if (!sourceNode) { | |
| console.error("SourceNode not initialized"); | |
| return; | |
| } | |
| const bufferLength = analyser.frequencyBinCount; | |
| const dataArray = new Uint8Array(bufferLength); | |
| function draw() { | |
| requestAnimationFrame(draw); | |
| analyser.getByteFrequencyData(dataArray); | |
| const segmentLength = Math.floor(bufferLength / blobs.length); | |
| for (let i = 0; i < blobs.length; i++) { | |
| // Use an average value of a segment of the dataArray for each blob | |
| const dataValue = dataArray[(i * segmentLength) / 2] || 0; | |
| // Fallback to 0 if undefined | |
| const height = (dataValue / 128.0) * 50 + 50; | |
| blobs[i].style.height = `${height}px`; | |
| } | |
| } | |
| draw(); | |
| } | |
| audioResponseElement.onended = () => { | |
| hideBlobs(); // Hide the blobs once the audio has finished playing | |
| stopWaitAnimation(); | |
| enableMicButton(); // Ensure thought bubble is not showing | |
| }; | |
| audioResponseElement.onplay = () => { | |
| showBlobs(); // Show the blobs when audio starts playing | |
| stopWaitAnimation(); // Hide the thought bubble when audio starts playing | |
| }; | |
| document.body.addEventListener("click", () => { | |
| if (audioContext && audioContext.state === "suspended") { | |
| audioContext.resume(); | |
| } | |
| }); | |
| }); | |