MeysamSh's picture
Update Web/script.js
24a731a verified
/* ============================================================
SoundCloud-Style Audio Recorder + Waveform Display + Analyzer
============================================================
*/
// Global variables
let audioContext;
let gumStream;
let rec;
let input;
// DOM Elements
const recordBtn = document.getElementById("recordButton");
const stopBtn = document.getElementById("stopButton");
const pauseBtn = document.getElementById("pauseButton");
const recordingsList = document.getElementById("recordingsList");
const uploadButton = document.getElementById("upload-button");
const uploadInput = document.getElementById("audio-file");
const responseBox = document.getElementById("response");
const metadataBox = document.getElementById("metadata-display");
// ==============================
// Recording Controls
// ==============================
recordBtn.addEventListener("click", startRecording);
stopBtn.addEventListener("click", stopRecording);
pauseBtn.addEventListener("click", pauseRecording);
// Start recording
function startRecording() {
console.log("Recording started...");
recordBtn.disabled = true;
stopBtn.disabled = false;
pauseBtn.disabled = false;
navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
document.getElementById("formats").innerText =
"Sample rate: " + audioContext.sampleRate + " Hz";
gumStream = stream;
input = audioContext.createMediaStreamSource(stream);
rec = new Recorder(input, { numChannels: 1 });
rec.record();
}).catch(function (e) {
console.error("Could not start recording:", e);
recordBtn.disabled = false;
stopBtn.disabled = true;
pauseBtn.disabled = true;
});
}
// Pause recording
function pauseRecording() {
if (rec.recording) {
rec.stop();
pauseBtn.innerText = "Resume";
} else {
rec.record();
pauseBtn.innerText = "Pause";
}
}
// Stop recording
function stopRecording() {
console.log("Recording stopped.");
stopBtn.disabled = true;
recordBtn.disabled = false;
pauseBtn.disabled = true;
pauseBtn.innerText = "Pause";
rec.stop();
gumStream.getAudioTracks()[0].stop();
rec.exportWAV(createWaveformItem);
}
// ==============================
// File Upload
// ==============================
uploadButton.addEventListener("click", () => {
if (!uploadInput.files.length) {
alert("Select at least one file.");
return;
}
Array.from(uploadInput.files).forEach((file) => handleUploadedFile(file));
});
function handleUploadedFile(file) {
const url = URL.createObjectURL(file);
createWaveformItem(file, url);
}
// ==============================
// Create SoundCloud-like Waveform
// ==============================
function createWaveformItem(blob, forcedUrl = null) {
const url = forcedUrl || URL.createObjectURL(blob);
const li = document.createElement("li");
li.className = "wave-item";
const container = document.createElement("div");
container.className = "wave-canvas";
const meta = document.createElement("div");
meta.className = "wave-meta";
meta.innerHTML = `<div class="file-title">${blob.name || "recording.wav"}</div>`;
// Play button
const playBtn = document.createElement("button");
playBtn.className = "btn btn-play btn-sm";
playBtn.innerText = "Play";
// Analyze button
const analyzeBtn = document.createElement("button");
analyzeBtn.className = "btn btn-outline-secondary btn-sm";
analyzeBtn.innerText = "Analyze";
const controls = document.createElement("div");
controls.className = "wave-controls";
controls.appendChild(analyzeBtn);
controls.appendChild(playBtn);
li.appendChild(controls);
li.appendChild(container);
li.appendChild(meta);
recordingsList.appendChild(li);
// Create WaveSurfer
const wavesurfer = WaveSurfer.create({
container,
autoCenter: true,
waveColor: "#bbb",
progressColor: "#ff5500",
cursorColor: "#333",
barWidth: 2,
height: 70,
responsive: true,
});
// Analyze
analyzeBtn.addEventListener("click", () => {
analyzeAudio(blob);
});
// Toggle play/pause
playBtn.addEventListener("click", () => {
wavesurfer.playPause();
playBtn.innerText = wavesurfer.isPlaying() ? "Pause" : "Play";
});
wavesurfer.load(url);
// Metadata
blob.arrayBuffer().then((buffer) => {
const ctx = new AudioContext();
ctx.decodeAudioData(buffer).then((decoded) => {
metadataBox.innerHTML = `
<strong>Channels:</strong> ${decoded.numberOfChannels}<br>
<strong>Duration:</strong> ${decoded.duration.toFixed(2)}s<br>
<strong>Sample Rate:</strong> ${decoded.sampleRate} Hz
`;
});
});
}
// ==============================
// Audio Analysis API (placeholder)
// ==============================
async function analyzeAudio(blob) {
// Check if the response element exists
const responseBox = document.getElementById('response');
if (!responseBox) return;
responseBox.innerHTML = "<em>Analyzing...</em>";
// Convert Blob to File
const file = new File([blob], blob.name || "recording.wav", { type: blob.type });
const formData = new FormData();
formData.append("files", file);
try {
// Replace the URL with your real backend endpoint
const res = await fetch("/predict/", {
method: "POST",
body: formData,
});
const data = await res.json();
let message = "Prediction Failed!";
if (data[0]?.status === "success") {
const item = data[0];
const confidencePercent = Math.round(item.confidence * 100);
message = `${item.filename} is ${item.label} with confidence of ${confidencePercent}%`;
}
let messageVolume = "... ";
if (data[0]?.volume === "silent") {
messageVolume = "The audio appears to be silent or contains no detectable speech. Please record/select another file! ";
message = ""
}
if (data[0]?.volume === "augmented") {
messageVolume = "The detected speech volume was low, so a volume augmentation was applied before analysis. ";
}
const volumeColor = "orange";
let predictionColor = message.includes("Genuine") ? "green" : "red";
responseBox.innerHTML = `
<div style="font-size: 1.1rem; margin-bottom: 6px; color:${volumeColor};">
${messageVolume}
</div>
<div style="font-size: 1.25rem; font-weight:600; color:${predictionColor};">
${message}
</div>
`;
} catch (err) {
responseBox.innerHTML = `<div style="font-size: 1.25rem; font-weight:600; color:red;">/!\ Analysis failed.</div>`;
console.error(err);
}
}