<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <title>Chromeless THEOplayer</title> <script type="text/javascript" src="//cdn.theoplayer.com/dash/theoplayer/THEOplayer.js" ></script> <style> .theoplayer-container { width: 500px; height: 280px; background: orange; position: relative; } .controls { width: 100%; height: 50%; position: absolute; z-index: 2; bottom: 0; background: grey; opacity: 0.7; } .control-bar { width: 100%; height: 40%; position: relative; background: yellow; opacity: 0.7; } .subtitles-container { height: 30%; width: 100%; background: grey; } .timeline-container { height: 30%; width: 100%; background: green; } .playhead-position { display: inline-block; width: 10%; } .seekbar-container { display: inline-block; width: 70%; background: lawngreen; position: relative; } .seekbar-container .slider-seek { width: 100%; } .duration { display: inline-block; width: 10%; } .buffered-block { position: absolute; background: darkolivegreen; height: 10px; } .hidden { display: none; } .theoplayer-container .theoplayer-texttracks { display: none !important; } </style> </head> <body> <div class="theoplayer-container"> <div class="controls"> <div class="subtitles-container"></div> <div class="timeline-container"> <div class="playhead-position">0</div> <div class="seekbar-container"> <input class="slider-seek" type="range" min="0" max="100" step="0.01" value="0" /> </div> <div class="duration">0</div> </div> <div class="control-bar"> <button class="button-play">Play</button> <button class="button-pause hidden">Pause</button> <button class="button-muted">Mute</button> <button class="button-unmuted hidden">Unmute</button> <input class="slider-volume" type="range" min="0" max="1" step="0.01" value="1" /> <button class="button-fullscreen">Fullscreen</button> <button class="button-inline">Inline</button> <button class="button-picture-in-picture"> Toggle Picture-in-Picture </button> <select class="select-video-qualities" ><option value="">Auto</option></select > <select class="select-audio-track" ><option value="">Default</option></select > <select class="select-subtitle-track" ><option value="">Off</option></select > </div> </div> </div> <script type="text/javascript"> var element = document.querySelector(".theoplayer-container"); var player = new THEOplayer.ChromelessPlayer(element, { libraryLocation: "//cdn.theoplayer.com/dash/theoplayer/", license: "sZP7IYe6T6P1Cl46TDX136z_0lAlFSxeTu0-Cl4K3ZzkTS3lCoBoISUlCS06FOPlUY3zWokgbgjNIOf9fKaZTux10LUlFDXgTSb-3QIg06k1IKhrFSBrISCo0QPeCo0i36fVfK4_bQgZCYxNWoryIQXzImf90SCZ3l5_3u5i0u5i0Oi6Io4pIYP1UQgqWgjeCYxgflEc3l5_3lhz0lRo3SBLFOPeWok1dDrLYtA1Ioh6TgV6UQ1gWtAVCYggb6rlWoz6FOPVWo31WQ1qbta6FOPZIYAVFKgzf6i6bK4iWOrlWZfVfK3qIQ4LCDreCKj_FKgqf6i6Ct36FKXibOfVfGPgbQcNUw4LIYPlWorzIDrzFK3qWmfVfKNLIKgeIQcgFKrgUOfVfKNLdQ4VWOrpIYa6FOPZIYAVdYapCoj-fgzVfKxqWDXNWG3ybojkbK3gflNWfGxEIDjiWQXrIYfpCoj-f6i6WQjlCDcEWt3zf6i6v6PUFOPLIQ-LflNWfK1zWDikfgzVfG3gWKxydDkibK4LbogqW6f9UwPkIYz" }); registerControlBarComponents(); player.src = "//cdn.theoplayer.com/video/elephants-dream/playlist.m3u8"; function registerControlBarComponents() { /** * Play, Pause, Muted, Unmuted, Volume, Fullscreen, Inline, Picture-in-Picture * */ var buttonPlay = document.querySelector(".button-play"), buttonPause = document.querySelector(".button-pause"), buttonMuted = document.querySelector(".button-muted"), buttonUnmuted = document.querySelector(".button-unmuted"), sliderVolume = document.querySelector(".slider-volume"), buttonFullscreen = document.querySelector(".button-fullscreen"), buttonInline = document.querySelector(".button-inline"), buttonPictureInPicture = document.querySelector( ".button-picture-in-picture" ); buttonPlay.addEventListener("click", function() { player.play(); }); buttonPause.addEventListener("click", function() { player.pause(); }); buttonMuted.addEventListener("click", function() { player.muted = true; }); buttonUnmuted.addEventListener("click", function() { player.muted = false; }); sliderVolume.addEventListener("input", function(e) { player.volume = e.target.value; }); buttonFullscreen.addEventListener("click", function() { openFullscreen(); }); buttonInline.addEventListener("click", function() { closeFullscreen(); }); var video = element.querySelectorAll("video")[1], isPictureInPictureEnabled = false; buttonPictureInPicture.addEventListener("click", function() { if (!isPictureInPictureEnabled) { console.log("is not yet enabled"); video = element.querySelectorAll("video")[1] video.requestPictureInPicture(); } else { document.exitPictureInPicture(); } }); video.addEventListener("enterpictureinpicture", function() { isPictureInPictureEnabled = true; }); video.addEventListener("leavepictureinpicture", function() { isPictureInPictureEnabled = false; }); player.addEventListener("play", function(e) { buttonPlay.classList.toggle("hidden"); buttonPause.classList.toggle("hidden"); }); player.addEventListener("pause", function(e) { buttonPause.classList.toggle("hidden"); buttonPlay.classList.toggle("hidden"); }); var wasPreviouslyMuted = false; player.addEventListener("volumechange", function(e) { if (player.muted != wasPreviouslyMuted) { wasPreviouslyMuted = player.muted; buttonMuted.classList.toggle("hidden"); buttonUnmuted.classList.toggle("hidden"); } }); function openFullscreen() { if (element.requestFullscreen) { element.requestFullscreen(); } else if (element.mozRequestFullScreen) { /* Firefox */ element.mozRequestFullScreen(); } else if (element.webkitRequestFullscreen) { /* Chrome, Safari and Opera */ element.webkitRequestFullscreen(); } else if (element.msRequestFullscreen) { /* IE/Edge */ element.msRequestFullscreen(); } } function closeFullscreen() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { /* Firefox */ document.mozCancelFullScreen(); } else if (document.webkitExitFullscreen) { /* Chrome, Safari and Opera */ document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { /* IE/Edge */ document.msExitFullscreen(); } } /** * Video quality */ var selectVideoQualities = document.querySelector( ".select-video-qualities" ); selectVideoQualities.addEventListener("change", function() { var value = selectVideoQualities.value; if (value == "") { player.videoTracks[0].targetQuality = null; } else { player.videoTracks[0].targetQuality = player.videoTracks[0].qualities[value]; } }); player.videoTracks.addEventListener("addtrack", function(e) { e.track.qualities.forEach(function(quality, index) { var option = document.createElement("option"); option.value = index; option.innerText = quality.height; selectVideoQualities.appendChild(option); }); }); /** * Audio quality */ var selectAudioTrack = document.querySelector(".select-audio-track"), defaultAudioTrack; selectAudioTrack.addEventListener("change", function() { var value = selectAudioTrack.value; player.audioTracks.forEach(function(track) { track.enabled = false; }); if (value == "") { player.audioTracks[0].enabled = true; } else { player.audioTracks[value].enabled = true; } }); player.audioTracks.addEventListener("addtrack", function(e) { var option = document.createElement("option"); option.value = player.audioTracks.indexOf(e.track); option.innerText = e.track.label || e.track.kind; selectAudioTrack.appendChild(option); if (e.track.enabled) { defaultAudioTrack = option.value; } }); /** * Subtitle track */ var selectSubtitleTrack = document.querySelector( ".select-subtitle-track" ), subtitlesContainer = document.querySelector(".subtitles-container"); selectSubtitleTrack.addEventListener("change", function() { var value = selectSubtitleTrack.value; player.textTracks.forEach(function(track) { track.mode = "disabled"; }); if (value == "") { subtitlesContainer.style.display = "none"; } else { player.textTracks[value].mode = "showing"; subtitlesContainer.style.display = "block"; } }); player.textTracks.addEventListener("addtrack", function(e) { var option = document.createElement("option"); option.value = player.textTracks.indexOf(e.track); option.innerText = e.track.label; if (e.track.mode == "showing") { option.selected = true; } selectSubtitleTrack.appendChild(option); e.track.addEventListener("addcue", function(e1) { e1.cue.addEventListener("enter", function(e2) { subtitlesContainer.innerText = e2.cue.content; }); e1.cue.addEventListener("exit", function(e2) { subtitlesContainer.innerText = ""; }); }); }); /** * Seekbar */ var sliderSeek = document.querySelector(".slider-seek"); var divPlayheadPosition = document.querySelector(".playhead-position"); var divDuration = document.querySelector(".duration"); var isSliding = false; sliderSeek.addEventListener("input", function(e) { isSliding = true; var value = e.target.value; var playheadPosition = calculateNewPlayHeadPosition(value); player.currentTime = playheadPosition; }); sliderSeek.addEventListener("change", function(e) { isSliding = false; }); function calculateNewPlayHeadPosition(value) { if (player.seekable.length > 0) { var start = player.seekable.start(0); var end = player.seekable.end(player.seekable.length - 1); var range = end - start; var playheadPosition = start + range * (value / 100); return playheadPosition; } else { return 0; } } /** * Playhead position */ player.addEventListener("timeupdate", function(e) { var isLive = player.duration === Infinity; if (!isLive) { divPlayheadPosition.innerText = formatSecondsToHHMMSS( player.currentTime ); } else if (player.currentProgramDateTime) { divPlayheadPosition.innerText = formatDate( player.currentProgramDateTime ); divDuration.innerText = formatDate( calculateLiveDuration( player.currentTime, player.currentProgramDateTime, player.seekable.end(player.seekable.length - 1) ) ); } else { divPlayheadPosition.innerText = formatDate( calculateLivePlayheadPosition( player.currentTime, player.seekable.end(player.seekable.length - 1) ) ); divDuration.innerText = formatDate(new Date()); } if (!isSliding) { sliderSeek.value = calculateSliderValue(); // or e.currentTime } }); function calculateSliderValue() { if (player.seekable.length > 0) { var start = player.seekable.start(0); var end = player.seekable.end(player.seekable.length - 1); var range = end - start; var sliderValue = (100 * (player.currentTime - start)) / range; return sliderValue; } else { return 0; } } /** * Duration */ player.addEventListener("durationchange", function(e) { var isLive = player.duration === Infinity; if (!isLive) { divDuration.innerText = formatSecondsToHHMMSS(player.duration); } else if (player.currentProgramDateTime) { divDuration.innerText = formatDate( calculateLiveDuration( player.currentTime, player.currentProgramDateTime, player.seekable.end(player.seekable.length - 1) ) ); } else { divDuration.innerText = player.duration; } }); function formatDate(date) { var seconds = (date.getSeconds() < 10 ? "0" : "") + date.getSeconds(); var minutes = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes(); var hour = (date.getHours() < 10 ? "0" : "") + date.getHours(); return hour + ":" + minutes + ":" + seconds; } function formatSecondsToHHMMSS(seconds) { var hrs = Math.floor(seconds / 3600); var min = Math.floor((seconds - hrs * 3600) / 60); var sec = seconds - hrs * 3600 - min * 60; sec = Math.round(Math.round(sec * 100) / 100); var result = hrs == 0 ? "" : (hrs < 10 ? "0" + hrs : hrs) + ":"; result += (min < 10 ? "0" + min : min) + ":"; result += sec < 10 ? "0" + sec : sec; return result; } function calculateLiveDuration( currentTime, currentProgramDateTime, seekableEnd ) { var toAdd = seekableEnd - currentTime; var date = new Date(currentProgramDateTime); date.setSeconds(date.getSeconds() + toAdd); return date; } function calculateLivePlayheadPosition(currentTime, seekableEnd) { var toDeduct = seekableEnd - currentTime; var date = new Date(); date.setSeconds(date.getSeconds() - toDeduct); return date; } /** * Buffered */ var seekBarContainer = document.querySelector(".seekbar-container"); player.addEventListener("progress", function(e) { clearAllBufferedBlocks(); for (var i = 0; i < player.buffered.length; i++) { insertBufferedBlock( player.buffered.start(i), player.buffered.end(i) ); } }); function clearAllBufferedBlocks() { var bufferedBlocks = document.querySelectorAll(".buffered-block"); for (var i = 0; i < bufferedBlocks.length; i++) { var bufferedBlock = bufferedBlocks[i]; bufferedBlock.parentNode.removeChild(bufferedBlock); } } function insertBufferedBlock(start, end) { var length = end - start; var lengthPerc = length / player.duration; var offset = start / player.duration; var bufferedBlock = document.createElement("div"); bufferedBlock.className = "buffered-block"; bufferedBlock.style.width = Math.round(100 * lengthPerc) + "%"; bufferedBlock.style.left = Math.round(100 * offset) + "%"; seekBarContainer.appendChild(bufferedBlock); } } </script> </body> </html>