- From: guest271314 via GitHub <sysbot+gh@w3.org>
- Date: Fri, 09 Mar 2018 17:48:17 +0000
- To: public-media-capture@w3.org
guest271314 has just created a new issue for https://github.com/w3c/mediacapture-record: == Capturing MediaStream from HTMLMediaElement where src is set to MediaSource crashes tab == Attempting to capture `MediaStream` from `HTMLMediaElement` where `src` is set to `MediaSource` consistently crashes tab at Chromium 64, see https://github.com/w3c/web-platform-tests/issues/9947 ``` <!DOCTYPE html> <html> <head> <title>Record media fragments of any MIME type to single video using HTMLMediaElement.captureStream(), MediaRecorder, and MediaSource</title> </head> <body> <script> class MediaFragmentRecorder { constructor({ urls = [], video = document.createElement("video"), width = 320, height = 280 } = {}) { if (urls.length === 0) { throw new TypeError("no urls passed to MediaFragmentRecorder"); } return (async() => { video.height = height; video.width = width; video.autoplay = true; video.preload = "auto"; const chunks = []; let duration = 0; let media = await Promise.all( urls.map(async({ from, to, src }, index) => { const url = new URL(src); // get media fragment hash from `src` if (url.hash.length) { [from, to] = url.hash.match(/\d+/g); } return { blob: await fetch(src).then(response => response.blob()), from, to } })); // using `Promise.all()` here apparently is not the same // as recording the media in sequence as the next video // is not played when a buffer is added to `MediaSource` for (let { from, to, blob } of media) { await new Promise(async(resolve) => { let recorder; const blobURL = URL.createObjectURL(blob); video.addEventListener("playing", e => { const stream = video.captureStream(); recorder = new MediaRecorder(stream, { mimeType: "video/webm" }); recorder.start(); recorder.addEventListener("stop", e => { resolve(); console.log(e); }, { once: true }); recorder.addEventListener("dataavailable", async(e) => { console.log(e); chunks.push(await new Response(e.data).arrayBuffer()); URL.revokeObjectURL(blobURL); }); video.addEventListener("pause", e => { if (recorder.state === "recording") { recorder.stop(); } else { recorder.requestData(); } duration += video.currentTime - from; }, { once: true }); }, { once: true }); video.src = `${blobURL}#t=${from},${to}`; }) }; // using same `<video>` element at `.then()` does not // return expected result as to `autoplay` video.src = ""; return { chunks, duration, width, height } })() } } let urls = [{ src: "https://upload.wikimedia.org/wikipedia/commons/a/a4/Xacti-AC8EX-Sample_video-001.ogv", from: 0, to: 4 }, { src: "https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=10,20" }, { from: 55, to: 60, src: "https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4" }, { from: 0, to: 5, src: "https://raw.githubusercontent.com/w3c/web-platform-tests/master/media-source/mp4/test.mp4" }, { from: 0, to: 5, src: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4" }, { from: 0, to: 5, src: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4" }, { src: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerMeltdowns.mp4#t=0,6" }]; new MediaFragmentRecorder({ urls }) .then(({ chunks, duration, width, height }) => { let recorder, mediaStream; console.log(chunks, duration); const video = document.createElement("video"); document.body.appendChild(video); video.controls = true; video.preload = "auto"; video.autoplay = true; video.width = width; video.height = height; const mediaSource = new MediaSource(); const mimeCodec = "video/webm;codecs=vp8,opus"; const sourceOpen = e => { console.log(e); const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); sourceBuffer.mode = "sequence"; sourceBuffer.addEventListener("updateend", e => { console.log(e); }); sourceBuffer.appendBuffer(chunks.shift()); } const handleWaiting = e => { console.log(e); if (chunks.length) { mediaSource.sourceBuffers[0].appendBuffer(chunks.shift()) } else { console.log(e); video.autoplay = false; video.removeEventListener("waiting", handleWaiting); // https://bugs.chromium.org/p/chromium/issues/detail?id=642012 // `seeked` is not dispatched here /* video.addEventListener("seeked", e => { video.currentTime = 0; console.info(e, video.duration); }, {once:true}); video.currentTime = 1e5; */ // we do not get this far before tab crashes recorder.stop(); } } mediaSource.sourceBuffers.addEventListener("addsourcebuffer", e => { console.log(e) }); video.addEventListener("canplay", e => { console.log(e, duration, video.buffered.end(0), video.duration, mediaSource.duration); }); video.addEventListener("playing", e => { // consistently crashes tab at Chromium 64 mediaStream = video.captureStream(); recorder = new MediaRecorder(mediaStream, {mimeType:"video/webm"}); recorder.addEventListener("dataavailable", e => { console.log(e); }); recorder.start(); console.log(e, duration, video.buffered.end(0), video.duration, mediaSource.duration); }, { once: true }); video.addEventListener("waiting", handleWaiting); video.addEventListener("pause", e => console.log(e)); mediaSource.addEventListener("sourceopen", sourceOpen); video.src = URL.createObjectURL(mediaSource); }) </script> </body> </html> ``` Please view or discuss this issue at https://github.com/w3c/mediacapture-record/issues/146 using your GitHub account
Received on Friday, 9 March 2018 17:48:20 UTC