Skip to content
tezvyn:

Use MediaRecorder to capture a canvas stream and download as WebM

Source: developer.mozilla.orgMediumHow cards are made

Use MediaRecorder to capture a canvas stream and download as WebM

Tests MediaRecorder lifecycle and blob assembly. Answer: canvas.captureStream() into new MediaRecorder with video/webm, start(), collect chunks via dataavailable, stop(), then build a Blob and object URL for download.

What's really being asked

This question probes whether you understand the MediaStream Recording API end-to-end, specifically how to bridge a CanvasRenderingContext2D animation into a recorded WebM file without server involvement. Interviewers care that you know the difference between a MediaStream, a MediaRecorder, and the resulting Blob, and that you recognize the asynchronous event-driven nature of the API. It also surfaces whether you think about MIME type support, memory management, and user-initiated download patterns.

The full answer

A good answer hits four things in order. First, obtain the stream by calling canvas.captureStream(framesPerSecond) which returns a MediaStream. Second, instantiate MediaRecorder with the stream and an options object containing mimeType set to video/webm, and optionally guard the call with MediaRecorder.isTypeSupported. Third, attach a dataavailable listener that pushes event.data into a chunks array, then call recorder.start(). Fourth, in the stop listener or after calling recorder.stop(), concatenate the chunks with new Blob(chunks, {type: 'video/webm'}), generate a URL with URL.createObjectURL, assign it to an anchor tag, set the download attribute, and programmatically click it. Mention that stop() itself does not return data; it merely signals the end, and the final chunk arrives via the dataavailable event.

The mistakes people make

Common wrong answers include trying to create the download URL immediately after calling stop() without waiting for the terminal dataavailable event, which yields an incomplete or empty file. Another red flag is ignoring isTypeSupported and hard-coding video/webm on a browser that might default to video/mp4 or refuse the type. Some candidates suggest reading from the canvas pixel data directly via toBlob in a loop, which misses the point of the MediaRecorder API entirely. Forgetting to revoke the object URL afterward is a minor but notable leak.

What usually comes next

Interviewers often ask how you would handle a timeslice argument to start() to produce chunked uploads instead of a single large Blob. They may ask what happens if the canvas stops drawing or the tab loses focus, or how to record audio alongside the canvas using a mixed MediaStream from MediaStream.addTrack. You might also be asked about performance implications of high frame-rate capture or how to offer a preview of the recorded video before download.

A concrete example

Imagine a 30 FPS canvas animation. You call const stream = canvas.captureStream(30), then const recorder = new MediaRecorder(stream, {mimeType: 'video/webm'}). You declare const chunks = [], then recorder.ondataavailable = e => { if (e.data.size > 0) chunks.push(e.data); }. You call recorder.start(). Five seconds later you call recorder.stop(). In recorder.onstop you build const blob = new Blob(chunks, {type: 'video/webm'}), then const url = URL.createObjectURL(blob), then set a.href = url and a.download = 'capture.webm', and call a.click(). Finally you call URL.revokeObjectURL(url) after a short delay or on the next user interaction.

Interview question

Which sequence correctly records a canvas animation to a downloadable WebM using MediaRecorder?

  • a.Use canvas.toBlob inside the animation loop to manually collect frames, then concatenate them into a WebM file after stopping.
  • b.Capture the canvas stream, collect chunks in ondataavailable, call stop, then assemble the Blob in the onstop handler to trigger the download.Correct
  • c.Pass the MediaStream directly to URL.createObjectURL after calling recorder.stop() to generate the download link.
  • d.Start the recorder, call stop, then immediately build a Blob from the chunks array and trigger a download.
Why?

MediaRecorder is event-driven: ondataavailable delivers chunks during capture, and onstop fires after the final chunk arrives, so assembling the Blob inside onstop guarantees a complete file. Option D is tempting but wrong because it builds the Blob synchronously after stop(), before the terminal chunk has been received.

Just read this? Test yourself on what you have been reading.

Read the original → developer.mozilla.org

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.

See open roles