How to add two video file files to source buffer using api media source?

I have two videos: v11.webm and v12.webm.

What I want is that these two videos should work without problems.

I follow the api application of the media source to add data to the source buffer.

I mean the demo in this link

I modified this example and removed some of the fragmentation of the video, and also tried to add data to the source buffer file.

My code is as follows:

<script> var video = document.querySelector('video'); window.MediaSource = window.MediaSource || window.WebKitMediaSource; if (!!!window.MediaSource) { alert('MediaSource API is not available'); } var mediaSource = new MediaSource(); video.src = window.URL.createObjectURL(mediaSource); mediaSource.addEventListener('webkitsourceopen', function(e) { var sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"'); for(i=1;i<=2;i++) { (function(i){ GET('v1'+i+'.webm', function(uInt8Array) { var file = new Blob([uInt8Array], {type: 'video/webm'}); var reader = new FileReader(); reader.onload = function(e) { sourceBuffer.append(new Uint8Array(e.target.result)); }; reader.readAsArrayBuffer(file); }); })(i); } }, false); mediaSource.addEventListener('webkitsourceended', function(e) { logger.log('mediaSource readyState: ' + this.readyState); }, false); function GET(url, callback) { // alert(url); var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.send(); xhr.onload = function(e) { if (xhr.status != 200) { alert("Unexpected status code " + xhr.status + " for " + url); return false; } callback(new Uint8Array(xhr.response)); }; } </script> 

Currently, the code does not work as desired.

There is an inconsistent mix of v11.webm and v12.webm files.

It works without a glitch.

+9
javascript api html5 video streaming
source share
5 answers

Maybe a little late, but I was able to figure it out. Your new video overwrites the old because they both start at time 0. You must indicate that your new video starts at time X before adding it, so your event function "webkitsourceopen" should be:

 /* forget the sourcebuffer variable, we'll just manipulate mediaSource */ mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"'); /* it seems ok to set initial duration 0 */ var duration = 0; var totalVideos = 2; /* use this type of loop to ensure that that a single video is downloaded and appended before moving on to the next video, mediasource seems picky about these being in order */ var i = 0; (function readChunk_(i){ /* the GET function already returns a Uint8Array. the demo you linked reads it in filereader in order to manipulate it; you just want to immediately append it */ GET('v1' + (i + 1) + '.webm', function(uint8Array){ if(i == totalVideos) { mediaSource.endOfStream(); } else { /* assuming your videos are put together correctly (ie duration is correct), set the timestamp offset to the length of the total video */ mediaSource.sourceBuffers[0].timestampOffset = duration; mediaSource.sourceBuffers[0].append(uint8Array); /* set new total length */ duration = mediaSource.duration; readChunk(++i); } }); })(i); 

Now, unless MediaSource was so upset about the structure of the video that it takes. I have yet to find one .webm sample that works besides the same as the Eric Bidelman Demo that you linked.

EDIT: After doing more tests, the way I set the duration may be wrong. If you seem to get an exponential increase in duration after each addition, try setting the timestampoffset value to 0 and not changing it. I have no idea why this seems to fix it, and it could be a problem with the way I create webm files.

+10
source share

What I miss in your code: mediaSource.endOfStream ();

Can you talk about an inconsistent mixing problem?

+1
source share

The specification states that the gap between playback should not be larger than the smallest audio frame, do you agree with this? I donโ€™t think he says what to do if there is no sound, unfortunately.

0
source share

I think I was a little late to ask you, but did you manage to add the MP4 multiples file to the source media source buffer?

0
source share

I get a great example to solve this problem in a simple and short way ...

I use three static files, but you can also add data from a socket or any API.

 <!DOCTYPE html> <html> <head> </head> <body> <br> <video controls="true" autoplay="true"></video> <script> (async() => { const mediaSource = new MediaSource(); const video = document.querySelector("video"); // video.oncanplay = e => video.play(); const urls = ["https://nickdesaulniers.imtqy.com/netfix/demo/frag_bunny.mp4", "https://raw.githubusercontent.com/w3c/web-platform-tests/master/media-source/mp4/test.mp4","https://nickdesaulniers.imtqy.com/netfix/demo/frag_bunny.mp4"]; const request = url => fetch(url).then(response => response.arrayBuffer()); // 'urls.reverse()' stops at '.currentTime' : '9' const files = await Promise.all(urls.map(request)); /* '.webm' files Uncaught DOMException: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source. Uncaught DOMException: Failed to set the 'timestampOffset' property on 'SourceBuffer': This SourceBuffer has been removed from the parent media source. */ // const mimeCodec = "video/webm; codecs=opus"; // https://stackoverflow.com/questions/14108536/how-do-i-append-two-video-files-data-to-a-source-buffer-using-media-source-api/ const mimeCodec = "video/mp4; codecs=avc1.42E01E, mp4a.40.2"; const media = await Promise.all(files.map(file => { return new Promise(resolve => { let media = document.createElement("video"); let blobURL = URL.createObjectURL(new Blob([file])); media.onloadedmetadata = async e => { resolve({ mediaDuration: media.duration, mediaBuffer: file }) } media.src = blobURL; }) })); console.log(media); mediaSource.addEventListener("sourceopen", sourceOpen); video.src = URL.createObjectURL(mediaSource); async function sourceOpen(event) { if (MediaSource.isTypeSupported(mimeCodec)) { const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); for (let chunk of media) { await new Promise(resolve => { sourceBuffer.appendBuffer(chunk.mediaBuffer); sourceBuffer.onupdateend = e => { sourceBuffer.onupdateend = null; sourceBuffer.timestampOffset += chunk.mediaDuration; console.log(mediaSource.duration); resolve() } }) } mediaSource.endOfStream(); } else { console.warn(mimeCodec + " not supported"); } }; })() </script> </body> </html> 

All merit belongs to this person https://github.com/guest271314 , who printed the information.

0
source share

All Articles