Created
November 5, 2019 15:39
-
-
Save ftence/8d2c0cd48bb8278e6b6eb77fb7ac05ea to your computer and use it in GitHub Desktop.
Serve a simple web page with a player
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<' | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"/> | |
<title>WarpTV #1: What is Warp10™?</title> | |
</head> | |
<body> | |
<video controls></video> | |
<script> | |
var video = document.querySelector('video'); // The HTML-5 video element | |
var sourceBuffer; // The SourceBuffer used in the MediaSource | |
var data_url = window.location.href + '/data'; // URL of the data API | |
var CHUNK_DURATION = 2; // 2-second chunks | |
var buffers_to_be_appended = []; // Fetched data to be appended, waiting for source buffer to by ready | |
var last_seeked_chunk = -1; // Last chunk requested by a seek | |
var fetched_chunks = []; // Already fetched chunk, not to be fetched again | |
// Codec definition, use mp4info and look for `Codecs String`. | |
var mimeCodec = 'video/mp4; codecs="avc1.64001F, mp4a.40.2"'; | |
// Check browser-compatibility and initialize the MediaSource and add the event listeners | |
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) { | |
var mediaSource = new MediaSource; | |
video.src = URL.createObjectURL(mediaSource); | |
video.addEventListener('timeupdate', timeupdate); | |
video.addEventListener('seeking', seeking); | |
mediaSource.addEventListener('sourceopen', sourceOpen); | |
} else { | |
console.error('Unsupported MIME type or codec: ', mimeCodec); | |
} | |
// Called at the MediaSource initialization. Load the init segmenent and the first chunk of video. | |
function sourceOpen(_) { | |
var mediaSource = this; | |
sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); | |
sourceBuffer.addEventListener('updateend', onupdateend); | |
getData(data_url, function (buf) { | |
sourceBuffer.appendBuffer(buf); | |
addChunk(0); | |
}); | |
// Check if a seek has been done every 500ms. Avoid calling too much times addChunk. | |
var t = setInterval(checkSeek, 500); | |
}; | |
function timeupdate(_) { | |
var next_chunk = Math.round(video.currentTime / CHUNK_DURATION + 1); | |
addChunk(next_chunk); | |
} | |
function seeking() { | |
last_seeked_chunk = Math.round(video.currentTime / CHUNK_DURATION); | |
} | |
function checkSeek() { | |
if (last_seeked_chunk >= 0) { | |
addChunk(last_seeked_chunk); | |
addChunk(last_seeked_chunk - 1); // Also load the previous chunk because it could span after the current time. | |
last_seeked_chunk = -1; | |
} | |
} | |
// Fetch the requested chunk if needed and add it the SourceBuffer. | |
function addChunk(chunk) { | |
if (!fetched_chunks.includes(chunk)) { | |
fetched_chunks.push(chunk); | |
var end = (chunk + 1) * CHUNK_DURATION * 1000000 - 1; // Timestamp in us, end excluded | |
end = Math.round(end); | |
var start = chunk * CHUNK_DURATION * 1000000; // Timestamp in us, start included | |
start = Math.round(start); | |
var query = data_url + '?start=' + start + '&end=' + end; | |
getData(query, function (buf) { | |
// Add to the SourceBuffer or the the waiting list if not available for add. | |
if (sourceBuffer.updating) { | |
buffers_to_be_appended.push(buf); | |
} else { | |
sourceBuffer.appendBuffer(buf); | |
} | |
}); | |
} | |
} | |
// Load the next chunk on the waiting list if possible. | |
function onupdateend() { | |
if (!sourceBuffer.updating && buffers_to_be_appended.length > 0) { | |
sourceBuffer.appendBuffer(buffers_to_be_appended.shift()); | |
} | |
} | |
// Get the data with XMLHttpRequest | |
function getData(url, cb) { | |
// console.log(url); | |
var xhr = new XMLHttpRequest; | |
xhr.open('get', url); | |
xhr.responseType = 'arraybuffer'; | |
xhr.onload = function () { | |
cb(xhr.response); | |
}; | |
xhr.send(); | |
}; | |
</script> | |
</body> | |
</html> | |
'> | |
'page' STORE | |
{ | |
'path' '/warpflix' | |
'prefix' false // Only respond to http(s)://endpoint/warpflix | |
'macro' | |
<% | |
{ | |
'status' 200 | |
'headers' | |
{ 'Content-Type' 'text/html' } | |
'body' !$page | |
} | |
%> | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment