Flowplayer · Video timeline thumbnail

Disclaimer: With longer videos this is can fail in Chrome, because Chrome gets stuck when it tries to load the same video more than once. Also note that this can only work with the html5 engine.

Compare with the image based solution using the thumbnails plugin.

<head/>

<style>

.flowplayer {
background-color: #000;
background-image: url(//flowplayer.org/media/img/demos/minimalist.jpg);
margin-bottom: 30px;
}
@media(-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.flowplayer {
background-image: url(//flowplayer.org/media/img/demos/minimalist@x2.jpg);
}
}
/* hide standard time tool tip */
.flowplayer .fp-tooltip {
display: none !important;
}
 
/* the preview canvas */
.flowplayer canvas {
outline: 4px solid #fff;
position: absolute;
z-index: 9999;
display: none;
}

CSS

<script>

flowplayer(function (api, root) {
api.on("ready", function (e, api, video) {
var thumbheight = Math.round($(root).height() / 8);
$(root).append($("<canvas/>").attr({
height: thumbheight,
width: Math.round(thumbheight * video.width / video.height)
}));
});
});
 

$(function() {
 
var withThumbnail = function (fpVideo, callback) {
var thumb = $("video.fp-thumbnail");
if (!thumb.length) {
thumb = fpVideo.clone().addClass("fp-thumbnail").appendTo($("body")).css({
position: "absolute",
left: -9999
}).on("loadedmetadata", function () {
callback(thumb);
});
thumb[0].muted = true;
thumb[0].load();
} else if (thumb[0].readyState !== 4) {
thumb.on("loadedmetadata", function () {
callback(thumb);
});
} else {
callback(thumb);
}
}
 
$(".fp-timeline").on("mousemove", function (ev) {
var timelineOffset = $(".fp-timeline").offset(),
percentage = (ev.pageX - timelineOffset.left) / $(".fp-timeline").width(),
canv = $(".flowplayer canvas"),
canvWidth = canv.width(),
canvHeight = canv.height(),
fpVideo = $(".flowplayer video");
 
canv.show().css({
left: Math.round(ev.pageX - (flowplayer().isFullscreen ? canvWidth / 2 : canvWidth + 4 * 2)),
bottom: Math.round($(".flowplayer .fp-controls").height() + 4 * 2)
});
withThumbnail(fpVideo, function (thumb) {
thumb[0].currentTime = fpVideo[0].duration * percentage;
thumb.one("seeked", function () {
var canvas = canv[0],
ctx = canvas.getContext("2d");
ctx.drawImage(thumb[0], 0, 0, canvWidth, canvHeight);
});
})
}).on("mouseleave", function () {
$(".flowplayer canvas").hide();
});
});

JavaScript

<body/>

<div class="flowplayer" data-swf-hls="false" data-ratio="0.4167">
<video>
<source type="application/x-mpegurl" src="//edge.flowplayer.org/bauhaus.m3u8">
<source type="video/webm" src="//edge.flowplayer.org/bauhaus.webm">
<source type="video/mp4" src="//edge.flowplayer.org/bauhaus.mp4">
</video>
</div>

HTML