mainBlock = {
if (navigator.mediaDevices.getUserMedia) {
const constraints = { audio: true };
let chunks = [];
let onSuccess = function (stream) {
const mediaRecorder = new MediaRecorder(stream);
visualize(stream, mediaRecorder);
record.onclick = function () {
mediaRecorder.start();
record.style.background = "red";
stop.disabled = false;
record.disabled = true;
mutable debug = [];
};
stop.onclick = function () {
mediaRecorder.stop();
record.style.background = "";
record.style.color = "";
stop.disabled = true;
record.disabled = false;
};
mediaRecorder.onstop = function (e) {
const clipName = "My Unnamed clip";
const clipContainer = htl.html`<article class="clip">`;
const clipLabel = htl.html`<input type=text value=${clipName} >`;
const audio = htl.html`<audio controls="">`;
const saveButton = htl.html`<button class="save">Save`;
const deleteButton = htl.html`<button class="delete">Delete`;
clipContainer.append(audio, clipLabel, deleteButton, saveButton);
soundClips.append(clipContainer);
audio.controls = true;
const blob = new Blob(chunks, { type: "audio/ogg; codecs=opus" });
chunks = [];
const audioURL = URL.createObjectURL(blob);
audio.src = audioURL;
saveButton.onclick = function (e) {
let link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `${clipLabel.value}.ogg`;
link.click();
document.removeChild(link);
};
deleteButton.onclick = function (e) {
let evtTgt = e.target;
evtTgt.parentNode.parentNode.removeChild(evtTgt.parentNode);
};
};
mediaRecorder.ondataavailable = function (e) {
chunks.push(e.data);
mutable debug.push(e);
};
};
let onError = function (err) {
console.log("The following error occured: " + err);
};
navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
} else {
throw "getUserMedia not supported on your browser!";
}
const audioCtx = new AudioContext();
const canvasCtx = canvas.getContext("2d");
let animationFrameId = null;
invalidation.then(() => {
if (animationFrameId) cancelAnimationFrame(animationFrameId);
});
function visualize(stream, recorder) {
const source = audioCtx.createMediaStreamSource(stream);
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
source.connect(analyser);
//analyser.connect(audioCtx.destination);
const silenceDetect = document.querySelector("#silencedetect");
let silenceCount = 0;
draw();
function draw() {
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
animationFrameId = requestAnimationFrame(draw);
analyser.getByteTimeDomainData(dataArray);
canvasCtx.fillStyle = "rgb(200, 200, 200)";
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
canvasCtx.lineWidth = 2;
canvasCtx.strokeStyle = "rgb(0, 0, 0)";
canvasCtx.beginPath();
let sliceWidth = (WIDTH * 1.0) / bufferLength;
let x = 0;
let silence = true;
for (let i = 0; i < bufferLength; i++) {
let v = dataArray[i] / 128.0;
if (Math.abs(v - 1) > 0.01) silence = false;
let y = (v * HEIGHT) / 2;
if (i === 0) {
canvasCtx.moveTo(x, y);
} else {
canvasCtx.lineTo(x, y);
}
x += sliceWidth;
}
canvasCtx.lineTo(canvas.width, canvas.height / 2);
canvasCtx.stroke();
if (silenceDetect.checked) {
if (silence) silenceCount++;
else silenceCount = 0;
if (silenceCount > 60) {
// Half a second
if (recorder.state == "recording") recorder.pause();
} else {
if (recorder.state == "paused") recorder.resume();
}
canvasCtx.fillStyle = "red";
canvasCtx.fillText(
(silence ? "silence " : "") + recorder.state,
10,
20
);
} else {
if (recorder.state == "paused") recorder.resume();
silenceCount = 0;
}
}
}
}