gUM browser+audioCapture
by jib1
HTML
<video id="video" controls width="160" height="120" autoplay></video><br>
<button id="button">Go!</button>
<div id="container"></div>
<div id="div"></div>
JavaScript
const console = {log: msg => div.innerHTML += `${msg}<br>`};
// Requires media.getusermedia.audiocapture.enabled=true
button.onclick = async () => {
try {
const stream =await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true,
});
video.srcObject = stream;
spectrum(stream);
} catch (e) {
console.log(e);
}
};
function spectrum(stream) {
const [track] = stream.getAudioTracks();
if (!track) return stream;
const audioCtx = new AudioContext();
const analyser = audioCtx.createAnalyser();
audioCtx.createMediaStreamSource(stream).connect(analyser);
track.onended = () => audioCtx.close();
track.stop_ = track.stop;
track.stop = () => track.stop_(audioCtx.close());
const canvas = container.appendChild(document.createElement("canvas"));
canvas.width = video.clientWidth;
canvas.height = 200;
const ctx = canvas.getContext("2d");
const data = new Uint8Array(canvas.width);
ctx.strokeStyle = 'rgb(0, 125, 0)';
setInterval(() => {
ctx.fillStyle = "#a0a0a0";
ctx.fillRect(0, 0, canvas.width, canvas.height);
analyser.getByteFrequencyData(data);
ctx.lineWidth = 2;
let x = 0;
for (let d of data) {
const y = canvas.height - (d / 128) * canvas.height / 4;
const c = Math.floor((x*255)/canvas.width);
ctx.fillStyle = `rgb(${c},0,${255-x})`;
ctx.fillRect(x++, y, 2, canvas.height - y)
}
analyser.getByteTimeDomainData(data);
ctx.lineWidth = 5;
ctx.beginPath();
x = 0;
for (let d of data) {
const y = canvas.height - (d / 128) * canvas.height / 2;
x ? ctx.lineTo(x++, y) : ctx.moveTo(x++, y);
}
ctx.stroke();
}, 1000 * canvas.width / audioCtx.sampleRate);
return stream;
};
function log(msg) { div.innerHTML += "<br>" + msg; }