Skip to content

Instantly share code, notes, and snippets.

@robwalch
Forked from anonymous/index.html
Created December 8, 2015 01:31
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 robwalch/939f7aa73c40e10d4351 to your computer and use it in GitHub Desktop.
Save robwalch/939f7aa73c40e10d4351 to your computer and use it in GitHub Desktop.
Buffering // source http://jsbin.com/wokoraz
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Buffering</title>
<style>
.ranges {
height: 20px;
position: relative;
width: 400px;
}
.buffered {
background-color: #999;
}
.seekable {
background-color: #777;
}
.played {
background-color: #555;
}
.range {
position: absolute;
display: block;
top: 0;
bottom: 0;
}
.buffered .range {
background-color: #595;
}
.seekable .range {
background: #995;
}
.played .range {
background: #955;
}
.track {
display: block;
cursor: pointer;
background-color: white;
padding-left: 1em;
}
</style>
</head>
<body>
<p>In Safari you will see a video of animals that contains 2 metadata cue points. Browsers that do not support HLS playback will fallback to an mp4 that starts with an animated title "global timoto". There are no cues there. Open in Safari.</p>
<video id="media" preload autoplay controls>
<!-- This source contains valid HLS MPEG-2 Transport ID3 -->
<source src="http://playertest.longtailvideo.com/adaptive/wowzaid3/playlist.m3u8" type="application/x-mpegURL">
!-- This source DOES NOT cotain valid HLS MPEG-2 Transport ID3 -->
<!--
source src="http://playertest.longtailvideo.com/adaptive/redbull/playlist.m3u8" type="application/x-mpegURL"
-->
<source src="http://content.bitsontherun.com/videos/w5VkaqJ1-393434.mp4 " type="video/mp4">
</video>
<div>
<span>buffered: </span>
<span id="buffered-start"></span>-<span id="buffered-end"></span>
<span>of: </span>
<span id="buffered-count"></span>
</div>
<div class="buffered ranges">
<span id="buffered-range-0" class="range"></span>
</div>
<div>
<span>seekable: </span>
<span id="seekable-start"></span>-<span id="seekable-end"></span>
<span>of: </span>
<span id="seekable-count"></span>
</div>
<div class="seekable ranges">
<span id="seekable-range-0" class="range"></span>
</div>
<div>
<span>played: </span>
<span id="played-start"></span>-<span id="played-end"></span>
<span>of: </span>
<span id="played-count"></span>
</div>
<div class="played ranges">
<span id="played-range-0" class="range"></span>
</div>
<div>
<span>currentTime: </span><span id="current-time"></span>
</div>
<div>
<span>duration: </span><span id="duration"></span>
</div>
<div>
<div>
<span>seekable duration: </span><span id="seekable-duration"></span>
</div>
<span>ranges start to end: </span><span id="ranges-start"></span>-<span id="ranges-end"></span>
</div>
<button id="seek-button">seek</button> to <input id="seek-time"></input>
<div>
<span>video tracks: </span><span id="video-track-count"></span>
</div>
<div>
<span>audio tracks: </span><span id="audio-track-count"></span>
</div>
<div>
<span>text tracks: </span><span id="text-track-count"></span>
</div>
</html>
<script id="jsbin-javascript">
window.onload = function(){
var el = document.getElementById.bind(document);
var create = function(name, id, classes) {
var element = document.createElement(name);
element.id = id;
element.className = classes || '';
return element;
};
var media = el('media');
media.addEventListener('progress', update);
media.addEventListener('loadeddata', update);
//media.addEventListener('canplay', update);
//media.addEventListener('canplaythrough', update);
//media.addEventListener('playing', update);
media.addEventListener('timeupdate', update);
media.addEventListener('seeked', update);
el('seek-button').addEventListener('click', function() {
media.currentTime = parseFloat(el('seek-time').value) || 0;
});
function update(e) {
var start = Infinity;
var end = 0;
if (media.buffered.length) {
start = Math.min(start, media.buffered.start(0));
end = Math.max(end, media.buffered.end(media.buffered.length - 1));
}
if (media.seekable.length) {
start = Math.min(start, media.seekable.start(0));
end = Math.max(end, media.seekable.end(media.seekable.length - 1));
el('seekable-duration').textContent = media.seekable.end(media.seekable.length - 1) - media.seekable.start(0);
}
if (media.played.length) {
start = Math.min(start, media.played.start(0));
end = Math.max(end, media.played.end(media.played.length - 1));
}
describeRange('buffered');
describeRange('seekable');
describeRange('played');
drawRange('buffered', start, end);
drawRange('seekable', start, end);
drawRange('played', start, end);
el('current-time').textContent = media.currentTime;
el('duration').textContent = media.duration;
el('ranges-start').textContent = start;
el('ranges-end').textContent = end;
listTracks('video');
listTracks('audio');
listTracks('text');
}
function listTracks(trackType) {
var tracksName = trackType + 'Tracks';
var tracks = media[tracksName];
if (tracks) {
var len = tracks.length;
el(trackType+'-track-count').textContent = len;
//tracks.onchange
//tracks.onaddtrack
//tracks.onremovetrack
for (var i=0; i<len; i++) {
var track = tracks.item(i);
var element = el(trackType+'-track-'+i);
if (!element) {
element = create('span', trackType+'-track-'+i, 'track');
el(trackType+'-track-count').appendChild(element);
element.onclick = element.ontouchstart = (function(tr) {
return function() {
console.log(tr);
if (tr.enabled !== undefined) {
tr.enabled = true;
} else if (tr.selected !== undefined) {
tr.selected = true;
} else if (tr.mode) {
tr.mode = (tr.mode === 'showing') ?
'hidden' : (tr.mode === 'hidden' ? 'disabled': 'showing');
}
};
})(track);
// enable metadata tracks
if (track.kind === 'metadata') {
track.mode = 'showing';
}
}
element.textContent = JSON.stringify({
id: track.id || undefined,
kind: track.kind,
language: track.language || undefined,
label: track.label || undefined,
mode: track.mode,
enabled: track.enabled,
selected: track.selected,
cues: track.cues ? ([track.cues.length, track.cues]) : undefined
}, null, 1).replace(/"|}|{/g, '');
}
} else {
el(trackType+'-track-count').textContent = 'unknown';
}
}
function describeRange(rangesName) {
el(rangesName+'-count').textContent = media[rangesName].length;
if (media[rangesName].length) {
el(rangesName+'-start').textContent = media[rangesName].start(media[rangesName].length - 1);
el(rangesName+'-end').textContent = media[rangesName].end(media[rangesName].length - 1);
}
}
function drawRange(rangesName, start, end) {
var len = media[rangesName].length;
if (len) {
var rangeSize = end - start;
for (var i=0; i<len; i++) {
var a = media[rangesName].start(i) - start;
var b = media[rangesName].end(i) - start;
var element = el(rangesName+'-range-'+i);
if (!element) {
element = create('span', rangesName+'-range-'+i, 'range');
el(rangesName+'-range-0').parentNode.appendChild(element);
}
element.style.left = ''+(a*100/rangeSize)+'%';
element.style.right = ''+(100-(b*100/rangeSize))+'%';
}
}
}
};
</script>
<script id="jsbin-source-javascript" type="text/javascript">window.onload = function(){
var el = document.getElementById.bind(document);
var create = function(name, id, classes) {
var element = document.createElement(name);
element.id = id;
element.className = classes || '';
return element;
};
var media = el('media');
media.addEventListener('progress', update);
media.addEventListener('loadeddata', update);
//media.addEventListener('canplay', update);
//media.addEventListener('canplaythrough', update);
//media.addEventListener('playing', update);
media.addEventListener('timeupdate', update);
media.addEventListener('seeked', update);
el('seek-button').addEventListener('click', function() {
media.currentTime = parseFloat(el('seek-time').value) || 0;
});
function update(e) {
var start = Infinity;
var end = 0;
if (media.buffered.length) {
start = Math.min(start, media.buffered.start(0));
end = Math.max(end, media.buffered.end(media.buffered.length - 1));
}
if (media.seekable.length) {
start = Math.min(start, media.seekable.start(0));
end = Math.max(end, media.seekable.end(media.seekable.length - 1));
el('seekable-duration').textContent = media.seekable.end(media.seekable.length - 1) - media.seekable.start(0);
}
if (media.played.length) {
start = Math.min(start, media.played.start(0));
end = Math.max(end, media.played.end(media.played.length - 1));
}
describeRange('buffered');
describeRange('seekable');
describeRange('played');
drawRange('buffered', start, end);
drawRange('seekable', start, end);
drawRange('played', start, end);
el('current-time').textContent = media.currentTime;
el('duration').textContent = media.duration;
el('ranges-start').textContent = start;
el('ranges-end').textContent = end;
listTracks('video');
listTracks('audio');
listTracks('text');
}
function listTracks(trackType) {
var tracksName = trackType + 'Tracks';
var tracks = media[tracksName];
if (tracks) {
var len = tracks.length;
el(trackType+'-track-count').textContent = len;
//tracks.onchange
//tracks.onaddtrack
//tracks.onremovetrack
for (var i=0; i<len; i++) {
var track = tracks.item(i);
var element = el(trackType+'-track-'+i);
if (!element) {
element = create('span', trackType+'-track-'+i, 'track');
el(trackType+'-track-count').appendChild(element);
element.onclick = element.ontouchstart = (function(tr) {
return function() {
console.log(tr);
if (tr.enabled !== undefined) {
tr.enabled = true;
} else if (tr.selected !== undefined) {
tr.selected = true;
} else if (tr.mode) {
tr.mode = (tr.mode === 'showing') ?
'hidden' : (tr.mode === 'hidden' ? 'disabled': 'showing');
}
};
})(track);
// enable metadata tracks
if (track.kind === 'metadata') {
track.mode = 'showing';
}
}
element.textContent = JSON.stringify({
id: track.id || undefined,
kind: track.kind,
language: track.language || undefined,
label: track.label || undefined,
mode: track.mode,
enabled: track.enabled,
selected: track.selected,
cues: track.cues ? ([track.cues.length, track.cues]) : undefined
}, null, 1).replace(/"|}|{/g, '');
}
} else {
el(trackType+'-track-count').textContent = 'unknown';
}
}
function describeRange(rangesName) {
el(rangesName+'-count').textContent = media[rangesName].length;
if (media[rangesName].length) {
el(rangesName+'-start').textContent = media[rangesName].start(media[rangesName].length - 1);
el(rangesName+'-end').textContent = media[rangesName].end(media[rangesName].length - 1);
}
}
function drawRange(rangesName, start, end) {
var len = media[rangesName].length;
if (len) {
var rangeSize = end - start;
for (var i=0; i<len; i++) {
var a = media[rangesName].start(i) - start;
var b = media[rangesName].end(i) - start;
var element = el(rangesName+'-range-'+i);
if (!element) {
element = create('span', rangesName+'-range-'+i, 'range');
el(rangesName+'-range-0').parentNode.appendChild(element);
}
element.style.left = ''+(a*100/rangeSize)+'%';
element.style.right = ''+(100-(b*100/rangeSize))+'%';
}
}
}
};</script>
window.onload = function(){
var el = document.getElementById.bind(document);
var create = function(name, id, classes) {
var element = document.createElement(name);
element.id = id;
element.className = classes || '';
return element;
};
var media = el('media');
media.addEventListener('progress', update);
media.addEventListener('loadeddata', update);
//media.addEventListener('canplay', update);
//media.addEventListener('canplaythrough', update);
//media.addEventListener('playing', update);
media.addEventListener('timeupdate', update);
media.addEventListener('seeked', update);
el('seek-button').addEventListener('click', function() {
media.currentTime = parseFloat(el('seek-time').value) || 0;
});
function update(e) {
var start = Infinity;
var end = 0;
if (media.buffered.length) {
start = Math.min(start, media.buffered.start(0));
end = Math.max(end, media.buffered.end(media.buffered.length - 1));
}
if (media.seekable.length) {
start = Math.min(start, media.seekable.start(0));
end = Math.max(end, media.seekable.end(media.seekable.length - 1));
el('seekable-duration').textContent = media.seekable.end(media.seekable.length - 1) - media.seekable.start(0);
}
if (media.played.length) {
start = Math.min(start, media.played.start(0));
end = Math.max(end, media.played.end(media.played.length - 1));
}
describeRange('buffered');
describeRange('seekable');
describeRange('played');
drawRange('buffered', start, end);
drawRange('seekable', start, end);
drawRange('played', start, end);
el('current-time').textContent = media.currentTime;
el('duration').textContent = media.duration;
el('ranges-start').textContent = start;
el('ranges-end').textContent = end;
listTracks('video');
listTracks('audio');
listTracks('text');
}
function listTracks(trackType) {
var tracksName = trackType + 'Tracks';
var tracks = media[tracksName];
if (tracks) {
var len = tracks.length;
el(trackType+'-track-count').textContent = len;
//tracks.onchange
//tracks.onaddtrack
//tracks.onremovetrack
for (var i=0; i<len; i++) {
var track = tracks.item(i);
var element = el(trackType+'-track-'+i);
if (!element) {
element = create('span', trackType+'-track-'+i, 'track');
el(trackType+'-track-count').appendChild(element);
element.onclick = element.ontouchstart = (function(tr) {
return function() {
console.log(tr);
if (tr.enabled !== undefined) {
tr.enabled = true;
} else if (tr.selected !== undefined) {
tr.selected = true;
} else if (tr.mode) {
tr.mode = (tr.mode === 'showing') ?
'hidden' : (tr.mode === 'hidden' ? 'disabled': 'showing');
}
};
})(track);
// enable metadata tracks
if (track.kind === 'metadata') {
track.mode = 'showing';
}
}
element.textContent = JSON.stringify({
id: track.id || undefined,
kind: track.kind,
language: track.language || undefined,
label: track.label || undefined,
mode: track.mode,
enabled: track.enabled,
selected: track.selected,
cues: track.cues ? ([track.cues.length, track.cues]) : undefined
}, null, 1).replace(/"|}|{/g, '');
}
} else {
el(trackType+'-track-count').textContent = 'unknown';
}
}
function describeRange(rangesName) {
el(rangesName+'-count').textContent = media[rangesName].length;
if (media[rangesName].length) {
el(rangesName+'-start').textContent = media[rangesName].start(media[rangesName].length - 1);
el(rangesName+'-end').textContent = media[rangesName].end(media[rangesName].length - 1);
}
}
function drawRange(rangesName, start, end) {
var len = media[rangesName].length;
if (len) {
var rangeSize = end - start;
for (var i=0; i<len; i++) {
var a = media[rangesName].start(i) - start;
var b = media[rangesName].end(i) - start;
var element = el(rangesName+'-range-'+i);
if (!element) {
element = create('span', rangesName+'-range-'+i, 'range');
el(rangesName+'-range-0').parentNode.appendChild(element);
}
element.style.left = ''+(a*100/rangeSize)+'%';
element.style.right = ''+(100-(b*100/rangeSize))+'%';
}
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment