I have a video (webm) capture script that works fine. It records video then offers it as a download. The pertinent part of the code is this:
stopBtn.addEventListener('click', function() { recorder.ondataavailable = e => { ul.style.display = 'block'; var a = document.createElement('a'), li = document.createElement('li'); a.download = ['video_', (new Date() + '').slice(4, 28), '.'+vid_format].join(''); a.textContent = a.download; a.href = URL.createObjectURL(stream); //<-- deprecated usage? li.appendChild(a); ul.appendChild(li); }; recorder.stop(); startBtn.removeAttribute('disabled'); stopBtn.disabled = true; }, false);
This works, as I say. However, the console says that passing media streams to URL.createObjectURL
is deprecated, and I should use HTMLMediaElement srcObject
instead.
So I changed it to:
a.href = URL.createObjectURL(video.srcObject);
…and although everything still works, I get the same warning.
Does anyone know how I can get a URL or blob data without this deprecated way?
I have also tried reading the src
and currentSrc
properties from the video element, but they come back empty where a stream is involved.
Advertisement
Answer
I am really surprised that your code did even work…
If stream
is really a MediaStream
, then the browser should not even know what size it would have to download, thus not when to stop downloading (it’s a stream).
MediaRecorder#ondataavailable
will expose an Event with a data
property filled with a chunk of the recorded MediaStream. In this event, you will have to store these chunks in an Array, and then you will download the concatenation of these Blobs chunks, usually in the MediaRecorder#onstop event.
const stream = getCanvasStream(); // we'll use a canvas stream so that it works in stacksnippet const chunks = []; // this will store our Blobs chunks const recorder = new MediaRecorder(stream); recorder.ondataavailable = e => chunks.push(e.data); // a new chunk Blob is given in this event recorder.onstop = exportVid; // only when the recorder stops, we do export the whole; setTimeout(() => recorder.stop(), 5000); // will stop in 5s recorder.start(1000); // all chunks will be 1s function exportVid() { var blob = new Blob(chunks); // here we concatenate all our chunks in a single Blob var url = URL.createObjectURL(blob); // we creat a blobURL from this Blob var a = document.createElement('a'); a.href = url; a.innerHTML = 'download'; a.download = 'myfile.webm'; document.body.appendChild(a); stream.getTracks().forEach(t => t.stop()); // never bad to close the stream when not needed anymore } function getCanvasStream() { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); ctx.fillStyle = 'red'; // a simple animation to be recorded let x = 0; const anim = t => { x = (x + 2) % 300; ctx.clearRect(0, 0, 300, 150); ctx.fillRect(x, 0, 10, 10); requestAnimationFrame(anim); } anim(); document.body.appendChild(canvas); return canvas.captureStream(30); }
URL.createObjectURL(MediaStream)
was used for <video>
elements. But this also led to some difficulties for browsers to close physical devices access, since BlobURLs can have a longer lifetime than the current document.
So it is now deprecated to call createObjectURL
with a MediaStream, and one should use MediaElement.srcObject = MediaStream
instead.