Search code examples
htmlhtml5-videomp4media-source

How to download (or get as a blob) a MediaSource used for streaming HTML5 video?


I'm streaming a dynamically-generated MP4 into a webpage over a WebSocket. I assemble a MediaSource (https://developer.mozilla.org/en-US/docs/Web/API/MediaSource) as the fragments come in, use that for the HTML5 video element, and my video plays fine in all major browsers.

What I'd like to do is add the ability for a user to download this video. My first attempt was to see if I could get access to it through the video.src property, which I set with window.URL.createObjectURL(my_media_source). This URL is a blob URL of the form "blob:null/abb348e0-3459-8344-bf1e-063dd001f09a". I don't know why there is a null in that url, but it is consistently there. An XMLHttpRequest to get this blob fails.

So, what is the right way to take my streaming video that plays fine and download it as a single file? The MediaSource seems to contain the entire video stream -- can I get access to that as an arraybuffer or a blob or whatever?


Solution

  • I think I answered this on my own. To my understanding, here is the present situation:

    First off, it appears that getting the binary data back from a MediaSource is actually not currently possible. There is even an issue about this on the W3C standard: https://github.com/w3c/media-source/issues/209

    What is possible is using the relatively new MediaRecorder (https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) API, which is not yet supported by all browsers. The downside of this is that the browser re-encodes the video and you have less control over the output format -- I couldn't get Chrome to produce an mp4, only a webm. Also, if there was a previous request for binary data, every time you request the binary data, it will only give you the data starting from that previous request.

    Of course, one could also manually keep a second copy of the video in memory, but I didn't want to follow that approach as it seemed very wasteful and annoying.