MSE Frame Accurate Seek
by dustinkerstein
HTML
<body>
<progress id="progress" value="0"></progress>
<video id="myvideo" width="300px"></video>
</body>
JavaScript
var progressBar = document.getElementById("progress"), display = document.getElementById("display");
var sourceBuffer;
var frameRate;
var index = 0;
var segments = [];
var ms = new MediaSource();
var videoBits, arrayOfBytes, chunk, file;
const LEFTBRACKET = 219;
const RIGHTBRACKET = 221;
getData('sd_dash.mpd');
var video = document.getElementById('myvideo');
video.src = window.URL.createObjectURL(ms);
ms.addEventListener('sourceopen', onMediaSourceOpen);
document.addEventListener('keydown', function (e) {
var key = e.keyCode;
switch (key) {
case LEFTBRACKET:
--index;
if (index < 0) {
index = 0;
}
nextSegment(index);
break;
case RIGHTBRACKET:
++index;
nextSegment(index);
break;
}
});
function videoInit(initBytes) {
videoBits = initBytes;
chunk = initBytes.slice(0, parseInt(segments[0].getAttribute("mediaRange").toString().split('-')[1]) + 1);
appendToBuffer(chunk);
}
function onMediaSourceOpen() {
sourceBuffer = ms.addSourceBuffer('video/mp4; codecs="avc1.640033"');
sourceBuffer.mode = 'sequence';
}
function nextSegment(index) {
if (index < segments.length) {
arrayOfBytes = segments[index].getAttribute("mediaRange").toString().split('-');
chunk = videoBits.slice(arrayOfBytes[0], parseInt(arrayOfBytes[1]) + 1);
appendToBuffer(chunk);
}
}
function appendToBuffer(videoChunk) {
if (sourceBuffer.updating) {
console.log("Buffer not ready");
}
if (videoChunk && !sourceBuffer.updating) {
sourceBuffer.timestampOffset = video.currentTime + 1 / frameRate;
sourceBuffer.appendBuffer(new Uint8Array(videoChunk));
video.currentTime += 1 / frameRate;
}
}
function getData(url) {
if (url !== "") {
url = "https://files.panomoments.com/" + url;
var xhr = new XMLHttpRequest(); // Set up xhr request
xhr.open("GET", url, true); // Open the request
xhr.responseType = "text"; // Set the type of response expected
xhr.send();
//...