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;
  }
});

document.addEventListener('touchstart', function (e) {
	++index;
  nextSegment(index);
});

function videoInit(initBytes) {
  videoBits = initBytes;
  chunk = initBytes.slice(0, parseInt(segments[0].getAttribute("mediaRange").toString().split('-')[1]) + 1);
  appendToBuffer(chunk);
  playVideo();  
}

function playVideo() {
  setTimeout(() => {
      if (++index > 240) {
        index = 0;
      }
      nextSegment(index);
      console.log("Appending Frame");
      playVideo();
    }, 100);
}

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);
    console.log(chunk.byteLength)
    appendToBuffer(chunk);
  }
}

function appendToBuffer(videoChunk) {
  if (sourceBuffer.updating) {
    console.log("Buffer not ready");
  }
  if (videoChunk && !sourceBuffer.updating) {
      video.currentTime += 1 / frameRate;
   		sourceBuffer.timestampOffset = video.currentTime;
    	sourceBuffer.appendBuffer(new...