Skip to content

Instantly share code, notes, and snippets.

@tchakabam
Last active August 16, 2018 16:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tchakabam/228f9415fd1c1d1cc8537d768b114e61 to your computer and use it in GitHub Desktop.
Save tchakabam/228f9415fd1c1d1cc8537d768b114e61 to your computer and use it in GitHub Desktop.
Example / Benchmark for switching MSE SourceBuffers content while playing
<!--
*
* Example / Benchmark for switching MSE SourceBuffers content while playing
*
* Logs time needed for operations to browser console
*
* Replace the MEDIA_LIST array with resources present in your environment (fragmented mp4s with video expected)
*
*
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Buffer switch between two streams</title>
</head>
<body>
<video height=720></video>
<center><button onclick="switchStream()" id="switch">Switch!</button></center>
<script type="text/javascript">
var MEDIA_LIST = [
'/media/car-20120827-85.mp4',
'/media/motion-20120802-85.mp4'
];
var state = null;
var now = Date.now();
var sourceBuffer = null;
function switchStream() {
console.log('stream switch requested after ' + nowDiffTime() + ' ms');
state = 'REMOVING';
sourceBuffer.remove(0, Infinity);
}
function nowDiffTime() {
var diff = Date.now() - now;
now = Date.now();
return diff;
}
var dataList_ = null;
var video = null;
var mediaSource = null;
var currentTrack = 0;
(function() {
loadAllMedia(onMediaLoaded);
})();
function nextTrackIndex() {
return currentTrack++ % dataList_.length;
}
function onMediaLoaded(dataList) {
mediaSource = new MediaSource();
window.player = video = document.querySelector('video');
video.src = URL.createObjectURL(mediaSource);
video.addEventListener('playing', onPlaying, false);
dataList_ = dataList;
console.log('loading data took: ' + nowDiffTime() + ' ms');
mediaSource.addEventListener('sourceopen', onSourceOpen, false);
}
function onSourceOpen() {
sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"');
sourceBuffer.addEventListener('updateend', onSourceBufferUpdateEnd);
console.log('creating mediasource took: ' + nowDiffTime() + ' ms');
appendData(nextTrackIndex());
}
function onPlaying() {
switch(state) {
case 'APPENDED':
state = 'PLAYING';
console.log('seeking/playing took: ' + nowDiffTime() + ' ms');
break;
}
}
function onSourceBufferUpdateEnd() {
console.log('SourceBuffer update ended');
switch(state) {
case 'APPENDING':
state = 'APPENDED';
console.log('segment data appended, playing out');
console.log('appending to buffer took ' + nowDiffTime() + ' ms');
video.currentTime = 30;
video.play();
break;
case 'REMOVING':
console.log('flushing buffer took ' + nowDiffTime() + ' ms');
state = 'REMOVED';
appendData(nextTrackIndex());
break;
}
}
function appendData(index) {
state = 'APPENDING';
sourceBuffer.timestampOffset = 0;
console.log('appending ' + dataList_[index].length + ' bytes');
sourceBuffer.appendBuffer(dataList_[index]);
}
function loadAllMedia(done) {
var mediaList = MEDIA_LIST;
var dataList = [];
var mediaIndex = 0;
console.log('loading all media');
var continueLoading = function() {
loadBinary(mediaList[mediaIndex], function(data) {
dataList.push(data);
mediaIndex++;
if (mediaIndex >= mediaList.length) {
done(dataList);
return;
}
continueLoading();
});
}
continueLoading();
}
function loadBinary(url, done) {
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response; // Note: not oReq.responseText
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
/*
for (var i = 0; i < byteArray.byteLength; i++) {
// do something with each byte in the array
}
*/
done(byteArray);
}
};
oReq.send(null);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment