Back to feed
Dev.to
Dev.to
5/10/2026
TIL canvas.captureStream() is video-only — here's how I mixed voiceover + music into a MediaRecorder export" published: true

TIL canvas.captureStream() is video-only — here's how I mixed voiceover + music into a MediaRecorder export" published: true

Short summary

canvas.captureStream() exports video only; to include audio, bind HTMLMediaElements to a singleton AudioContext using createMediaElementSource() exactly once per element, with careful MediaStreamDestination cleanup to prevent phantom echoes. Key gotchas: <video>.muted silences both speakers and export (use a master gain node instead), AudioContext.resume() requires timing before MediaRecorder.start(), and Chrome's gesture requirement can auto-suspend the context.

  • canvas.captureStream() only captures video; audio requires an AudioContext graph
  • createMediaElementSource() can only bind once per element and reroutes speaker output through the graph
  • Six critical gotchas documented with working code: single-call binding, muted behavior, destination cleanup, speaker/export independence, context suspension timing

Generated with AI, which can make mistakes.

Is this a good recommendation for you?

Explore more