1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-06 03:50:04 +02:00

Add DVR support

This commit is contained in:
daniel 2019-04-23 10:20:27 -03:00
parent d86a2abab0
commit b60f9cc760
81 changed files with 1638 additions and 39 deletions

View file

@ -67,6 +67,7 @@ class Live extends PluginAbstract {
// for secure connections
//$obj->playerServer = "https://{$server['host']}:444/live";
$obj->stats = "{$scheme}://{$server['host']}:{$port}/stat";
$obj->disableDVR = false;
$obj->disableGifThumbs = false;
$obj->useAadaptiveMode = false;
$obj->experimentalWebcam = false;

0
plugin/Live/Objects/LiveTransmitionHistory.php Normal file → Executable file
View file

0
plugin/Live/Objects/LiveTransmitionHistoryLog.php Normal file → Executable file
View file

0
plugin/Live/install/install.sql Normal file → Executable file
View file

0
plugin/Live/install/nginx.conf Normal file → Executable file
View file

0
plugin/Live/install/nginx.old.conf Normal file → Executable file
View file

0
plugin/Live/install/updateV2.0.sql Normal file → Executable file
View file

0
plugin/Live/install/updateV3.0.sql Normal file → Executable file
View file

0
plugin/Live/on_play.php Normal file → Executable file
View file

0
plugin/Live/on_publish.php Normal file → Executable file
View file

0
plugin/Live/on_record_done.php Normal file → Executable file
View file

0
plugin/Live/report.php Normal file → Executable file
View file

0
plugin/Live/sample-player.zip Normal file → Executable file
View file

0
plugin/Live/sample-player/index.html Normal file → Executable file
View file

0
plugin/Live/sample-player/poster.jpg Normal file → Executable file
View file

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Before After
Before After

0
plugin/Live/sample-player/video.js/font/VideoJS.eot Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/font/VideoJS.svg Normal file → Executable file
View file

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before After
Before After

0
plugin/Live/sample-player/video.js/font/VideoJS.ttf Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/font/VideoJS.woff Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/ie8/videojs-ie8.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/ie8/videojs-ie8.min.js vendored Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/ar.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/ba.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/bg.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/ca.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/cs.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/da.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/de.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/el.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/en.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/es.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/fa.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/fi.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/fr.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/hr.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/hu.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/it.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/ja.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/ko.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/nb.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/nl.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/nn.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/pl.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/pt-BR.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/ru.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/sr.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/sv.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/tr.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/uk.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/vi.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/zh-CN.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/lang/zh-TW.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/video-js.css Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/video-js.min.css vendored Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/video-js.swf Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/video.js Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/video.min.js vendored Normal file → Executable file
View file

0
plugin/Live/sample-player/video.js/videojs-contrib-hls.min.js vendored Normal file → Executable file
View file

0
plugin/Live/saveLive.php Normal file → Executable file
View file

View file

@ -0,0 +1,3 @@
videojs.addLanguage('en', {
"Include your own strings in JSON files.": "Include your own strings in JSON files."
});

View file

@ -0,0 +1,523 @@
/*! @name videojs-dvrseekbar @version 0.0.1 @license Apache-2.0 */
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var videojs = _interopDefault(require('video.js'));
var version = "0.0.1";
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var DVRSeekBar = function () {
function DVRSeekBar(player, options) {
classCallCheck(this, DVRSeekBar);
if (!options) {
options = {};
}
this.vjsPlayer_ = player;
this.options_ = options;
if (this.vjsPlayer_.dash && this.vjsPlayer_.dash.shakaPlayer) {
this.player_ = this.vjsPlayer_.dash.shakaPlayer;
this.player_.addEventListener('buffering', this.onBufferingStateChange_.bind(this));
// window.setInterval(this.updateTimeAndSeekRange_.bind(this), 125);
} else {
this.player_ = this.vjsPlayer_;
}
window.setInterval(this.updateTimeAndSeekRange_.bind(this), 125);
/** @private {HTMLMediaElement} */
this.video_ = this.vjsPlayer_.tech_.el_;
/** @private {boolean} */
this.enabled_ = true;
/** @private {?number} */
this.seekTimeoutId_ = null;
var seekBarEl = document.createElement('input');
seekBarEl.setAttribute('type', 'range');
seekBarEl.setAttribute('step', 'any');
seekBarEl.setAttribute('min', '0');
seekBarEl.setAttribute('max', '1');
seekBarEl.setAttribute('value', '0');
seekBarEl.setAttribute('id', 'seekBar');
seekBarEl.addEventListener('mousedown', this.onSeekStart_.bind(this));
seekBarEl.addEventListener('touchstart', this.onSeekStart_.bind(this), {
passive: true
});
seekBarEl.addEventListener('input', this.onSeekInput_.bind(this));
seekBarEl.addEventListener('touchend', this.onSeekEnd_.bind(this));
seekBarEl.addEventListener('mouseup', this.onSeekEnd_.bind(this));
this.dvrSeekBar_ = seekBarEl;
this.currentTime_ = document.getElementById('dvr-current-time');
this.currentTime_.addEventListener('click', this.onCurrentTimeClick_.bind(this));
this.firstSeekRangeStart = null;
if (options.flowMode) ;
}
DVRSeekBar.prototype.getEl = function getEl() {
return this.dvrSeekBar_;
};
/** @private */
DVRSeekBar.prototype.onSeekStart_ = function onSeekStart_() {
if (!this.enabled_) return;
this.isSeeking_ = true;
this.video_.pause();
};
/** @private */
DVRSeekBar.prototype.onSeekInput_ = function onSeekInput_() {
if (!this.enabled_) return;
if (!this.video_.duration) {
// Can't seek yet. Ignore.
return;
}
// Update the UI right away.
this.updateTimeAndSeekRange_();
// Collect input events and seek when things have been stable for 125ms.
if (this.seekTimeoutId_ != null) {
window.clearTimeout(this.seekTimeoutId_);
}
this.seekTimeoutId_ = window.setTimeout(this.onSeekInputTimeout_.bind(this), 125);
};
/** @private */
DVRSeekBar.prototype.onSeekInputTimeout_ = function onSeekInputTimeout_() {
var seekVal = parseFloat(this.dvrSeekBar_.value);
var lastStartPoint = this.getSeekRange().start;
this.dvrSeekBar_.min = lastStartPoint;
this.seekTimeoutId_ = null;
//TODO: Hack para evitar que se cuelgue al cambiarse el starter point mientras es en vivo:
this.video_.currentTime = seekVal <= lastStartPoint ? lastStartPoint + 30 : seekVal;
};
/** @private */
DVRSeekBar.prototype.onSeekEnd_ = function onSeekEnd_() {
if (!this.enabled_) return;
if (this.seekTimeoutId_ != null) {
// They just let go of the seek bar, so end the timer early.
window.clearTimeout(this.seekTimeoutId_);
this.onSeekInputTimeout_();
}
this.isSeeking_ = false;
this.video_.play();
};
/** @private */
DVRSeekBar.prototype.onCurrentTimeClick_ = function onCurrentTimeClick_() {
if (!this.enabled_) return;
// Jump to LIVE if the user clicks on the current time.
if (this.player_.isLive && this.player_.isLive()) {
this.video_.currentTime = this.dvrSeekBar_.max;
}
};
/**
* Iniciar desde el comienzo el contenido live
* con FlowMode activado.
*
* @memberof DVRSeekBar
*/
DVRSeekBar.prototype.onFlowModePlaying_ = function onFlowModePlaying_(e) {
if (this.player_.isLive()) {
this.video_.currentTime = this.getSeekRange().start + 30;
}
};
/**
* @param {Event} event
* @private
*/
DVRSeekBar.prototype.onBufferingStateChange_ = function onBufferingStateChange_(event) {}
//this.bufferingSpinner_.style.display =
// event.buffering ? 'inherit' : 'none';
/**
* @return {boolean}
* @private
*/
;
DVRSeekBar.prototype.isOpaque_ = function isOpaque_() {
if (!this.enabled_) return false;
return this.vjsPlayer_.userActive();
};
/**
* @return {number}
* @private
*/
DVRSeekBar.prototype.getMediaSeekRangeSize_ = function getMediaSeekRangeSize_() {
return this.getSeekRange().end - this.getSeekRange().start;
};
/**
* Builds a time string, e.g., 01:04:23, from |displayTime|.
*
* @param {number} displayTime
* @param {boolean} showHour
* @return {string}
* @private
*/
DVRSeekBar.prototype.buildTimeString_ = function buildTimeString_(displayTime, showHour) {
var h = Math.floor(displayTime / 3600);
var m = Math.floor(displayTime / 60 % 60);
var s = Math.floor(displayTime % 60);
if (s < 10) s = '0' + s;
var text = m + ':' + s;
if (showHour) {
if (m < 10) text = '0' + text;
text = h + ':' + text;
}
return text;
};
/**
* Called when the seek range or current time need to be updated.
* @private
* @memberof DVRSeekBar
*/
DVRSeekBar.prototype.updateTimeAndSeekRange_ = function updateTimeAndSeekRange_() {
// Suppress updates if the controls are hidden.
if (!this.isOpaque_()) {
return;
}
var seekRange = this.getSeekRange();
// Suppress updates if seekable range are not loaded.
if (seekRange.end === 0 && seekRange.start === seekRange.end) {
return;
}
this.dvrSeekBar_.min = seekRange.start;
this.dvrSeekBar_.max = seekRange.end;
var seekRangeSize = this.getMediaSeekRangeSize_();
var displayTime = this.isSeeking_ ? this.dvrSeekBar_.value : this.video_.currentTime;
var duration = this.video_.duration;
var bufferedLength = this.video_.buffered.length;
var bufferedStart = bufferedLength ? this.video_.buffered.start(0) : 0;
var bufferedEnd = bufferedLength ? this.video_.buffered.end(bufferedLength - 1) : 0;
if (this.player_.isLive && this.player_.isLive()) {
// The amount of time we are behind the live edge.
var behindLive = Math.floor(seekRange.end - displayTime);
displayTime = Math.max(0, behindLive);
var _showHour = seekRangeSize >= 3600;
// Consider "LIVE" when less than 1 second behind the live-edge. Always
// show the full time string when seeking, including the leading '-';
// otherwise, the time string "flickers" near the live-edge.
if (displayTime >= 15 || this.isSeeking_) {
// Si es con experiencia Flow:
if (this.options_.flowMode) {
if (!this.firstSeekRangeStart) ;
//player.vjsPlayer.currentTime(seekRange.start);
// Fill firstSeekRangeStart
if (this.isSeeking_ || !this.firstSeekRangeStart) {
this.firstSeekRangeStart = seekRange.start;
}
this.currentTime_.textContent = this.buildTimeString_(this.video_.currentTime - this.firstSeekRangeStart, _showHour);
console.log('SeekRangeStart: ' + seekRange.start + ' | SeekRangeEnd: ' + seekRange.end + ' | CurrentTime: ' + this.video_.currentTime + ' | DisplayTime: ' + displayTime + ' | SeekSize: ' + seekRangeSize + ' | Time: ' + this.currentTime_.textContent);
} else {
this.currentTime_.textContent = '- ' + this.buildTimeString_(displayTime, _showHour);
}
this.currentTime_.style.cursor = 'pointer';
} else {
this.currentTime_.textContent = 'LIVE';
this.currentTime_.style.cursor = '';
}
if (!this.isSeeking_) {
this.dvrSeekBar_.value = seekRange.end - displayTime;
}
} else {
var showHour = duration >= 3600;
this.currentTime_.textContent = this.buildTimeString_(displayTime, showHour);
if (!this.isSeeking_) {
this.dvrSeekBar_.value = displayTime;
}
this.currentTime_.style.cursor = '';
}
if (bufferedLength == 0) ; else {
var clampedBufferStart = Math.max(bufferedStart, seekRange.start);
var clampedBufferEnd = Math.min(bufferedEnd, seekRange.end);
var bufferStartDistance = clampedBufferStart - seekRange.start;
var bufferEndDistance = clampedBufferEnd - seekRange.start;
var playheadDistance = displayTime - seekRange.start;
}
/* this.dvrSeekBar_.style.background =
'linear-gradient(' + gradient.join(',') + ')'; */
};
DVRSeekBar.prototype.getSeekRange = function getSeekRange() {
if (this.player_.seekRange) {
return this.player_.seekRange();
}
return {
start: this.player_.seekable().start(0),
end: this.player_.seekable().end(0)
};
};
return DVRSeekBar;
}();
var Plugin = videojs.getPlugin('plugin');
// Default options for the plugin.
var defaults$1 = {
startTime: 0,
externalSeekable: null
};
/**
* An advanced Video.js plugin. For more information on the API
*
* See: https://blog.videojs.com/feature-spotlight-advanced-plugins/
*/
var Dvrseekbar = function (_Plugin) {
inherits(Dvrseekbar, _Plugin);
/**
* Create a Dvrseekbar plugin instance.
*
* @param {Player} player
* A Video.js Player instance.
*
* @param {Object} [options]
* An optional options object.
*
* While not a core part of the Video.js plugin architecture, a
* second argument of options is a convenient way to accept inputs
* from your plugin's caller.
*/
function Dvrseekbar(player, options) {
classCallCheck(this, Dvrseekbar);
var _this = possibleConstructorReturn(this, _Plugin.call(this, player));
// the parent class will add player under this.player
_this.options = videojs.mergeOptions(defaults$1, options);
_this.player.ready(function () {
_this.player.addClass('vjs-dvrseekbar');
});
_this.player.on('loadeddata', function () {
// if (this.dash && this.dash.shakaPlayer) {
_this.ifShakaPlayer();
/* } else {
this.on('timeupdate', e => {
onTimeUpdate(this, e);
});
this.on('pause', e => {
let btnLiveEl = document.getElementById('liveButton');
btnLiveEl.className = 'vjs-live-label';
});
iDontKnowWhatThisDoes(this, videojs.mergeOptions(defaults, options));
} */
});
_this.one('playing', function (e) {
var sourceHandler = _this.tech_.sourceHandler_;
if (options.flowMode) {
var startTime = 0;
if (sourceHandler.constructor.name === 'ShakaHandler') {
startTime = sourceHandler.shakaPlayer.seekRange().start + 30;
}
_this.currentTime(startTime);
}
});
return _this;
}
Dvrseekbar.prototype.onTimeUpdate = function onTimeUpdate(player, e) {
var time = player.seekableFromShaka && player.seekableFromShaka() || player.seekable();
var btnLiveEl = document.getElementById('liveButton');
// When any tech is disposed videojs will trigger a 'timeupdate' event
// when calling stopTrackingCurrentTime(). If the tech does not have
// a seekable() method, time will be undefined
if (!time || !time.length) {
return;
}
if (time.end(0) - player.currentTime() < 30) {
btnLiveEl.className = 'label onair';
} else {
btnLiveEl.className = 'label';
}
player.duration(time.end(0));
};
Dvrseekbar.prototype.ifShakaPlayer = function ifShakaPlayer() {
var dvrCurrentTime = document.createElement('div');
dvrCurrentTime.setAttribute('id', 'dvr-current-time');
dvrCurrentTime.innerHTML = '0:00';
dvrCurrentTime.className = 'vjs-current-time-display';
this.player.controlBar.progressControl.seekBar.hide();
this.player.controlBar.progressControl.disable();
var currentSrc = this.player.tech_ && this.player.tech_.currentSource_ || {};
// TODO: delete this
currentSrc.hasCatchUp = true;
//////////////////////
if (currentSrc.hasCatchUp) {
this.player.controlBar.el_.insertBefore(dvrCurrentTime, this.player.controlBar.progressControl.el_.nextSibling);
var dvrSeekBar = new DVRSeekBar(this.player, this.options);
this.player.controlBar.progressControl.el_.appendChild(dvrSeekBar.getEl());
}
};
Dvrseekbar.prototype.iDontKnowWhatThisDoes = function iDontKnowWhatThisDoes(player, options) {
player.addClass('vjs-dvrseekbar');
player.controlBar.addClass('vjs-dvrseekbar-control-bar');
if (player.controlBar.progressControl) {
player.controlBar.progressControl.addClass('vjs-dvrseekbar-progress-control');
}
// ADD Live Button:
var btnLiveEl = document.createElement('div');
var newLink = document.createElement('a');
btnLiveEl.className = 'vjs-live-button vjs-control';
newLink.innerHTML = document.getElementsByClassName('vjs-live-display')[0].innerHTML;
newLink.id = 'liveButton';
if (!player.paused()) {
newLink.className = 'vjs-live-label onair';
}
var clickHandler = function clickHandler(e) {
var livePosition = player.seekableFromShaka && player.seekableFromShaka().end() || player.seekable().end(0);
player.currentTime(livePosition - 1);
player.play();
e.target.className += ' onair';
};
if (newLink.addEventListener) {
// DOM method
newLink.addEventListener('click', clickHandler, false);
} else if (newLink.attachEvent) {
// this is for IE, because it doesn't support addEventListener
newLink.attachEvent('onclick', function () {
return clickHandler.apply(newLink, [window.event]);
});
}
btnLiveEl.appendChild(newLink);
var controlBar = document.getElementsByClassName('vjs-control-bar')[0];
var insertBeforeNode = document.getElementsByClassName('vjs-progress-control')[0];
controlBar.insertBefore(btnLiveEl, insertBeforeNode);
videojs.log('dvrSeekbar Plugin ENABLED!', options);
};
return Dvrseekbar;
}(Plugin);
// Define default values for the plugin's `state` object here.
Dvrseekbar.defaultState = {};
// Include the version number.
Dvrseekbar.VERSION = version;
// Register the plugin with video.js.
videojs.registerPlugin('dvrseekbar', Dvrseekbar);
module.exports = Dvrseekbar;

View file

@ -0,0 +1 @@
/*! @name videojs-dvrseekbar @version 0.0.1 @license Apache-2.0 */.video-js{// This class is added to the video.js element by the plugin by default. &.vjs-dvrseekbar{display:block}}#dvr-current-time{line-height:3.5em;font-size:12px;font-weight:700;cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}#seekBar{display:flex;height:100%;margin:0;padding:0;-webkit-appearance:none;border:0 solid #666;border-radius:0;background-color:rgba(115,133,159,.5);outline:none}#seekBar::-moz-range-track{background-color:transparent;outline:none}#seekBar::-ms-fill-lower,#seekBar::-ms-fill-upper,#seekBar::-ms-track{background-color:transparent;outline:none}#seekBar{flex-grow:1;cursor:pointer}#seekBar::-webkit-slider-thumb{-webkit-appearance:none;background-color:#fff;outline:none}#seekBar::-moz-range-thumb{background-color:#fff;outline:none}#seekBar::-ms-thumb{background-color:#fff;outline:none}#seekBar::-webkit-slider-thumb{width:4px;height:100%}#seekBar::-moz-range-thumb{width:4px;height:100%}#seekBar::-ms-thumb{width:4px;height:100%}#seekBar::-ms-tooltip{display:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=range]{overflow:hidden;width:80px;-webkit-appearance:none;background-color:#fff}input[type=range]::-webkit-slider-runnable-track{height:10px;-webkit-appearance:none;color:#fff;margin-top:-1px}input[type=range]::-webkit-slider-thumb{width:10px;-webkit-appearance:none;height:10px;cursor:pointer;background:#434343;box-shadow:-9999px 0 0 9999px #fff}}input[type=range]::-moz-range-progress{background-color:#fff;height:100%}input[type=range]::-moz-range-track{background-color:#9a905d}input[type=range]::-ms-fill-lower{background-color:#fff}input[type=range]::-ms-fill-upper{background-color:#9a905d}

View file

@ -0,0 +1,492 @@
/*! @name videojs-dvrseekbar @version 0.0.1 @license Apache-2.0 */
import videojs from 'video.js';
var version = "0.0.1";
class DVRSeekBar {
constructor(player, options) {
if (!options) {
options = {};
}
this.vjsPlayer_ = player;
this.options_ = options;
if (this.vjsPlayer_.dash && this.vjsPlayer_.dash.shakaPlayer) {
this.player_ = this.vjsPlayer_.dash.shakaPlayer;
this.player_.addEventListener(
'buffering',
this.onBufferingStateChange_.bind(this)
);
// window.setInterval(this.updateTimeAndSeekRange_.bind(this), 125);
} else {
this.player_ = this.vjsPlayer_;
}
window.setInterval(this.updateTimeAndSeekRange_.bind(this), 125);
/** @private {HTMLMediaElement} */
this.video_ = this.vjsPlayer_.tech_.el_;
/** @private {boolean} */
this.enabled_ = true;
/** @private {?number} */
this.seekTimeoutId_ = null;
const seekBarEl = document.createElement('input');
seekBarEl.setAttribute('type', 'range');
seekBarEl.setAttribute('step', 'any');
seekBarEl.setAttribute('min', '0');
seekBarEl.setAttribute('max', '1');
seekBarEl.setAttribute('value', '0');
seekBarEl.setAttribute('id', 'seekBar');
seekBarEl.addEventListener('mousedown', this.onSeekStart_.bind(this));
seekBarEl.addEventListener('touchstart', this.onSeekStart_.bind(this), {
passive: true
});
seekBarEl.addEventListener('input', this.onSeekInput_.bind(this));
seekBarEl.addEventListener('touchend', this.onSeekEnd_.bind(this));
seekBarEl.addEventListener('mouseup', this.onSeekEnd_.bind(this));
this.dvrSeekBar_ = seekBarEl;
this.currentTime_ = document.getElementById('dvr-current-time');
this.currentTime_.addEventListener(
'click',
this.onCurrentTimeClick_.bind(this)
);
this.firstSeekRangeStart = null;
if (options.flowMode) ;
}
getEl() {
return this.dvrSeekBar_;
}
/** @private */
onSeekStart_() {
if (!this.enabled_) return;
this.isSeeking_ = true;
this.video_.pause();
}
/** @private */
onSeekInput_() {
if (!this.enabled_) return;
if (!this.video_.duration) {
// Can't seek yet. Ignore.
return;
}
// Update the UI right away.
this.updateTimeAndSeekRange_();
// Collect input events and seek when things have been stable for 125ms.
if (this.seekTimeoutId_ != null) {
window.clearTimeout(this.seekTimeoutId_);
}
this.seekTimeoutId_ = window.setTimeout(
this.onSeekInputTimeout_.bind(this),
125
);
}
/** @private */
onSeekInputTimeout_() {
let seekVal = parseFloat(this.dvrSeekBar_.value);
let lastStartPoint = this.getSeekRange().start;
this.dvrSeekBar_.min = lastStartPoint;
this.seekTimeoutId_ = null;
//TODO: Hack para evitar que se cuelgue al cambiarse el starter point mientras es en vivo:
this.video_.currentTime =
seekVal <= lastStartPoint ? lastStartPoint + 30 : seekVal;
}
/** @private */
onSeekEnd_() {
if (!this.enabled_) return;
if (this.seekTimeoutId_ != null) {
// They just let go of the seek bar, so end the timer early.
window.clearTimeout(this.seekTimeoutId_);
this.onSeekInputTimeout_();
}
this.isSeeking_ = false;
this.video_.play();
}
/** @private */
onCurrentTimeClick_() {
if (!this.enabled_) return;
// Jump to LIVE if the user clicks on the current time.
if (this.player_.isLive && this.player_.isLive()) {
this.video_.currentTime = this.dvrSeekBar_.max;
}
}
/**
* Iniciar desde el comienzo el contenido live
* con FlowMode activado.
*
* @memberof DVRSeekBar
*/
onFlowModePlaying_(e) {
if (this.player_.isLive()) {
this.video_.currentTime = this.getSeekRange().start + 30;
}
}
/**
* @param {Event} event
* @private
*/
onBufferingStateChange_(event) {
//this.bufferingSpinner_.style.display =
// event.buffering ? 'inherit' : 'none';
}
/**
* @return {boolean}
* @private
*/
isOpaque_() {
if (!this.enabled_) return false;
return this.vjsPlayer_.userActive();
}
/**
* @return {number}
* @private
*/
getMediaSeekRangeSize_() {
return this.getSeekRange().end - this.getSeekRange().start;
}
/**
* Builds a time string, e.g., 01:04:23, from |displayTime|.
*
* @param {number} displayTime
* @param {boolean} showHour
* @return {string}
* @private
*/
buildTimeString_(displayTime, showHour) {
var h = Math.floor(displayTime / 3600);
var m = Math.floor((displayTime / 60) % 60);
var s = Math.floor(displayTime % 60);
if (s < 10) s = '0' + s;
var text = m + ':' + s;
if (showHour) {
if (m < 10) text = '0' + text;
text = h + ':' + text;
}
return text;
}
/**
* Called when the seek range or current time need to be updated.
* @private
* @memberof DVRSeekBar
*/
updateTimeAndSeekRange_() {
// Suppress updates if the controls are hidden.
if (!this.isOpaque_()) {
return;
}
let seekRange = this.getSeekRange();
// Suppress updates if seekable range are not loaded.
if (seekRange.end === 0 && seekRange.start === seekRange.end) {
return;
}
this.dvrSeekBar_.min = seekRange.start;
this.dvrSeekBar_.max = seekRange.end;
let seekRangeSize = this.getMediaSeekRangeSize_();
let displayTime = this.isSeeking_
? this.dvrSeekBar_.value
: this.video_.currentTime;
let duration = this.video_.duration;
let bufferedLength = this.video_.buffered.length;
let bufferedStart = bufferedLength ? this.video_.buffered.start(0) : 0;
let bufferedEnd = bufferedLength
? this.video_.buffered.end(bufferedLength - 1)
: 0;
if (this.player_.isLive && this.player_.isLive()) {
// The amount of time we are behind the live edge.
let behindLive = Math.floor(seekRange.end - displayTime);
displayTime = Math.max(0, behindLive);
let showHour = seekRangeSize >= 3600;
// Consider "LIVE" when less than 1 second behind the live-edge. Always
// show the full time string when seeking, including the leading '-';
// otherwise, the time string "flickers" near the live-edge.
if (displayTime >= 15 || this.isSeeking_) {
// Si es con experiencia Flow:
if (this.options_.flowMode) {
if (!this.firstSeekRangeStart) ;
// Fill firstSeekRangeStart
if (this.isSeeking_ || !this.firstSeekRangeStart) {
this.firstSeekRangeStart = seekRange.start;
}
this.currentTime_.textContent = this.buildTimeString_(
this.video_.currentTime - this.firstSeekRangeStart,
showHour
);
console.log(
`SeekRangeStart: ${seekRange.start} | SeekRangeEnd: ${seekRange.end} | CurrentTime: ${this
.video_
.currentTime} | DisplayTime: ${displayTime} | SeekSize: ${seekRangeSize} | Time: ${this
.currentTime_.textContent}`
);
} else {
this.currentTime_.textContent =
'- ' + this.buildTimeString_(displayTime, showHour);
}
this.currentTime_.style.cursor = 'pointer';
} else {
this.currentTime_.textContent = 'LIVE';
this.currentTime_.style.cursor = '';
}
if (!this.isSeeking_) {
this.dvrSeekBar_.value = seekRange.end - displayTime;
}
} else {
var showHour = duration >= 3600;
this.currentTime_.textContent = this.buildTimeString_(
displayTime,
showHour
);
if (!this.isSeeking_) {
this.dvrSeekBar_.value = displayTime;
}
this.currentTime_.style.cursor = '';
}
if (bufferedLength == 0) ; else {
var clampedBufferStart = Math.max(bufferedStart, seekRange.start);
var clampedBufferEnd = Math.min(bufferedEnd, seekRange.end);
var bufferStartDistance = clampedBufferStart - seekRange.start;
var bufferEndDistance = clampedBufferEnd - seekRange.start;
var playheadDistance = displayTime - seekRange.start;
}
/* this.dvrSeekBar_.style.background =
'linear-gradient(' + gradient.join(',') + ')'; */
}
getSeekRange() {
if (this.player_.seekRange) {
return this.player_.seekRange();
}
return {
start: this.player_.seekable().start(0),
end: this.player_.seekable().end(0)
};
}
}
/////////////////////////
const Plugin = videojs.getPlugin('plugin');
// Default options for the plugin.
const defaults = {
startTime: 0,
externalSeekable: null
};
/**
* An advanced Video.js plugin. For more information on the API
*
* See: https://blog.videojs.com/feature-spotlight-advanced-plugins/
*/
class Dvrseekbar extends Plugin {
/**
* Create a Dvrseekbar plugin instance.
*
* @param {Player} player
* A Video.js Player instance.
*
* @param {Object} [options]
* An optional options object.
*
* While not a core part of the Video.js plugin architecture, a
* second argument of options is a convenient way to accept inputs
* from your plugin's caller.
*/
constructor(player, options) {
// the parent class will add player under this.player
super(player);
this.options = videojs.mergeOptions(defaults, options);
this.player.ready(() => {
this.player.addClass('vjs-dvrseekbar');
});
this.player.on('loadeddata', () => {
// if (this.dash && this.dash.shakaPlayer) {
this.ifShakaPlayer();
/* } else {
this.on('timeupdate', e => {
onTimeUpdate(this, e);
});
this.on('pause', e => {
let btnLiveEl = document.getElementById('liveButton');
btnLiveEl.className = 'vjs-live-label';
});
iDontKnowWhatThisDoes(this, videojs.mergeOptions(defaults, options));
} */
});
this.one('playing', e => {
const sourceHandler = this.tech_.sourceHandler_;
if (options.flowMode) {
let startTime = 0;
if (sourceHandler.constructor.name === 'ShakaHandler') {
startTime = sourceHandler.shakaPlayer.seekRange().start + 30;
}
this.currentTime(startTime);
}
});
}
onTimeUpdate(player, e) {
let time =
(player.seekableFromShaka && player.seekableFromShaka()) ||
player.seekable();
let btnLiveEl = document.getElementById('liveButton');
// When any tech is disposed videojs will trigger a 'timeupdate' event
// when calling stopTrackingCurrentTime(). If the tech does not have
// a seekable() method, time will be undefined
if (!time || !time.length) {
return;
}
if (time.end(0) - player.currentTime() < 30) {
btnLiveEl.className = 'label onair';
} else {
btnLiveEl.className = 'label';
}
player.duration(time.end(0));
}
ifShakaPlayer() {
const dvrCurrentTime = document.createElement('div');
dvrCurrentTime.setAttribute('id', 'dvr-current-time');
dvrCurrentTime.innerHTML = '0:00';
dvrCurrentTime.className = 'vjs-current-time-display';
this.player.controlBar.progressControl.seekBar.hide();
this.player.controlBar.progressControl.disable();
const currentSrc = this.player.tech_ && this.player.tech_.currentSource_ || {};
// TODO: delete this
currentSrc.hasCatchUp = true;
//////////////////////
if (currentSrc.hasCatchUp) {
this.player.controlBar.el_.insertBefore(
dvrCurrentTime,
this.player.controlBar.progressControl.el_.nextSibling
);
let dvrSeekBar = new DVRSeekBar(this.player, this.options);
this.player.controlBar.progressControl.el_.appendChild(dvrSeekBar.getEl());
}
}
iDontKnowWhatThisDoes(player, options) {
player.addClass('vjs-dvrseekbar');
player.controlBar.addClass('vjs-dvrseekbar-control-bar');
if (player.controlBar.progressControl) {
player.controlBar.progressControl.addClass(
'vjs-dvrseekbar-progress-control'
);
}
// ADD Live Button:
let btnLiveEl = document.createElement('div');
let newLink = document.createElement('a');
btnLiveEl.className = 'vjs-live-button vjs-control';
newLink.innerHTML = document.getElementsByClassName(
'vjs-live-display'
)[0].innerHTML;
newLink.id = 'liveButton';
if (!player.paused()) {
newLink.className = 'vjs-live-label onair';
}
let clickHandler = function(e) {
let livePosition =
(player.seekableFromShaka && player.seekableFromShaka().end()) ||
player.seekable().end(0);
player.currentTime(livePosition - 1);
player.play();
e.target.className += ' onair';
};
if (newLink.addEventListener) {
// DOM method
newLink.addEventListener('click', clickHandler, false);
} else if (newLink.attachEvent) {
// this is for IE, because it doesn't support addEventListener
newLink.attachEvent('onclick', function() {
return clickHandler.apply(newLink, [window.event]);
});
}
btnLiveEl.appendChild(newLink);
let controlBar = document.getElementsByClassName('vjs-control-bar')[0];
let insertBeforeNode = document.getElementsByClassName(
'vjs-progress-control'
)[0];
controlBar.insertBefore(btnLiveEl, insertBeforeNode);
videojs.log('dvrSeekbar Plugin ENABLED!', options);
}
}
// Define default values for the plugin's `state` object here.
Dvrseekbar.defaultState = {};
// Include the version number.
Dvrseekbar.VERSION = version;
// Register the plugin with video.js.
videojs.registerPlugin('dvrseekbar', Dvrseekbar);
export default Dvrseekbar;

View file

@ -0,0 +1,527 @@
/*! @name videojs-dvrseekbar @version 0.0.1 @license Apache-2.0 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
(global.videojsDvrseekbar = factory(global.videojs));
}(this, (function (videojs) { 'use strict';
videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
var version = "0.0.1";
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var DVRSeekBar = function () {
function DVRSeekBar(player, options) {
classCallCheck(this, DVRSeekBar);
if (!options) {
options = {};
}
this.vjsPlayer_ = player;
this.options_ = options;
if (this.vjsPlayer_.dash && this.vjsPlayer_.dash.shakaPlayer) {
this.player_ = this.vjsPlayer_.dash.shakaPlayer;
this.player_.addEventListener('buffering', this.onBufferingStateChange_.bind(this));
// window.setInterval(this.updateTimeAndSeekRange_.bind(this), 125);
} else {
this.player_ = this.vjsPlayer_;
}
window.setInterval(this.updateTimeAndSeekRange_.bind(this), 125);
/** @private {HTMLMediaElement} */
this.video_ = this.vjsPlayer_.tech_.el_;
/** @private {boolean} */
this.enabled_ = true;
/** @private {?number} */
this.seekTimeoutId_ = null;
var seekBarEl = document.createElement('input');
seekBarEl.setAttribute('type', 'range');
seekBarEl.setAttribute('step', 'any');
seekBarEl.setAttribute('min', '0');
seekBarEl.setAttribute('max', '1');
seekBarEl.setAttribute('value', '0');
seekBarEl.setAttribute('id', 'seekBar');
seekBarEl.addEventListener('mousedown', this.onSeekStart_.bind(this));
seekBarEl.addEventListener('touchstart', this.onSeekStart_.bind(this), {
passive: true
});
seekBarEl.addEventListener('input', this.onSeekInput_.bind(this));
seekBarEl.addEventListener('touchend', this.onSeekEnd_.bind(this));
seekBarEl.addEventListener('mouseup', this.onSeekEnd_.bind(this));
this.dvrSeekBar_ = seekBarEl;
this.currentTime_ = document.getElementById('dvr-current-time');
this.currentTime_.addEventListener('click', this.onCurrentTimeClick_.bind(this));
this.firstSeekRangeStart = null;
if (options.flowMode) ;
}
DVRSeekBar.prototype.getEl = function getEl() {
return this.dvrSeekBar_;
};
/** @private */
DVRSeekBar.prototype.onSeekStart_ = function onSeekStart_() {
if (!this.enabled_) return;
this.isSeeking_ = true;
this.video_.pause();
};
/** @private */
DVRSeekBar.prototype.onSeekInput_ = function onSeekInput_() {
if (!this.enabled_) return;
if (!this.video_.duration) {
// Can't seek yet. Ignore.
return;
}
// Update the UI right away.
this.updateTimeAndSeekRange_();
// Collect input events and seek when things have been stable for 125ms.
if (this.seekTimeoutId_ != null) {
window.clearTimeout(this.seekTimeoutId_);
}
this.seekTimeoutId_ = window.setTimeout(this.onSeekInputTimeout_.bind(this), 125);
};
/** @private */
DVRSeekBar.prototype.onSeekInputTimeout_ = function onSeekInputTimeout_() {
var seekVal = parseFloat(this.dvrSeekBar_.value);
var lastStartPoint = this.getSeekRange().start;
this.dvrSeekBar_.min = lastStartPoint;
this.seekTimeoutId_ = null;
//TODO: Hack para evitar que se cuelgue al cambiarse el starter point mientras es en vivo:
this.video_.currentTime = seekVal <= lastStartPoint ? lastStartPoint + 30 : seekVal;
};
/** @private */
DVRSeekBar.prototype.onSeekEnd_ = function onSeekEnd_() {
if (!this.enabled_) return;
if (this.seekTimeoutId_ != null) {
// They just let go of the seek bar, so end the timer early.
window.clearTimeout(this.seekTimeoutId_);
this.onSeekInputTimeout_();
}
this.isSeeking_ = false;
this.video_.play();
};
/** @private */
DVRSeekBar.prototype.onCurrentTimeClick_ = function onCurrentTimeClick_() {
if (!this.enabled_) return;
// Jump to LIVE if the user clicks on the current time.
if (this.player_.isLive && this.player_.isLive()) {
this.video_.currentTime = this.dvrSeekBar_.max;
}
};
/**
* Iniciar desde el comienzo el contenido live
* con FlowMode activado.
*
* @memberof DVRSeekBar
*/
DVRSeekBar.prototype.onFlowModePlaying_ = function onFlowModePlaying_(e) {
if (this.player_.isLive()) {
this.video_.currentTime = this.getSeekRange().start + 30;
}
};
/**
* @param {Event} event
* @private
*/
DVRSeekBar.prototype.onBufferingStateChange_ = function onBufferingStateChange_(event) {}
//this.bufferingSpinner_.style.display =
// event.buffering ? 'inherit' : 'none';
/**
* @return {boolean}
* @private
*/
;
DVRSeekBar.prototype.isOpaque_ = function isOpaque_() {
if (!this.enabled_) return false;
return this.vjsPlayer_.userActive();
};
/**
* @return {number}
* @private
*/
DVRSeekBar.prototype.getMediaSeekRangeSize_ = function getMediaSeekRangeSize_() {
return this.getSeekRange().end - this.getSeekRange().start;
};
/**
* Builds a time string, e.g., 01:04:23, from |displayTime|.
*
* @param {number} displayTime
* @param {boolean} showHour
* @return {string}
* @private
*/
DVRSeekBar.prototype.buildTimeString_ = function buildTimeString_(displayTime, showHour) {
var h = Math.floor(displayTime / 3600);
var m = Math.floor(displayTime / 60 % 60);
var s = Math.floor(displayTime % 60);
if (s < 10) s = '0' + s;
var text = m + ':' + s;
if (showHour) {
if (m < 10) text = '0' + text;
text = h + ':' + text;
}
return text;
};
/**
* Called when the seek range or current time need to be updated.
* @private
* @memberof DVRSeekBar
*/
DVRSeekBar.prototype.updateTimeAndSeekRange_ = function updateTimeAndSeekRange_() {
// Suppress updates if the controls are hidden.
if (!this.isOpaque_()) {
return;
}
var seekRange = this.getSeekRange();
// Suppress updates if seekable range are not loaded.
if (seekRange.end === 0 && seekRange.start === seekRange.end) {
return;
}
this.dvrSeekBar_.min = seekRange.start;
this.dvrSeekBar_.max = seekRange.end;
var seekRangeSize = this.getMediaSeekRangeSize_();
var displayTime = this.isSeeking_ ? this.dvrSeekBar_.value : this.video_.currentTime;
var duration = this.video_.duration;
var bufferedLength = this.video_.buffered.length;
var bufferedStart = bufferedLength ? this.video_.buffered.start(0) : 0;
var bufferedEnd = bufferedLength ? this.video_.buffered.end(bufferedLength - 1) : 0;
if (this.player_.isLive && this.player_.isLive()) {
// The amount of time we are behind the live edge.
var behindLive = Math.floor(seekRange.end - displayTime);
displayTime = Math.max(0, behindLive);
var _showHour = seekRangeSize >= 3600;
// Consider "LIVE" when less than 1 second behind the live-edge. Always
// show the full time string when seeking, including the leading '-';
// otherwise, the time string "flickers" near the live-edge.
if (displayTime >= 15 || this.isSeeking_) {
// Si es con experiencia Flow:
if (this.options_.flowMode) {
if (!this.firstSeekRangeStart) ;
//player.vjsPlayer.currentTime(seekRange.start);
// Fill firstSeekRangeStart
if (this.isSeeking_ || !this.firstSeekRangeStart) {
this.firstSeekRangeStart = seekRange.start;
}
this.currentTime_.textContent = this.buildTimeString_(this.video_.currentTime - this.firstSeekRangeStart, _showHour);
console.log('SeekRangeStart: ' + seekRange.start + ' | SeekRangeEnd: ' + seekRange.end + ' | CurrentTime: ' + this.video_.currentTime + ' | DisplayTime: ' + displayTime + ' | SeekSize: ' + seekRangeSize + ' | Time: ' + this.currentTime_.textContent);
} else {
this.currentTime_.textContent = '- ' + this.buildTimeString_(displayTime, _showHour);
}
this.currentTime_.style.cursor = 'pointer';
} else {
this.currentTime_.textContent = 'LIVE';
this.currentTime_.style.cursor = '';
}
if (!this.isSeeking_) {
this.dvrSeekBar_.value = seekRange.end - displayTime;
}
} else {
var showHour = duration >= 3600;
this.currentTime_.textContent = this.buildTimeString_(displayTime, showHour);
if (!this.isSeeking_) {
this.dvrSeekBar_.value = displayTime;
}
this.currentTime_.style.cursor = '';
}
if (bufferedLength == 0) ; else {
var clampedBufferStart = Math.max(bufferedStart, seekRange.start);
var clampedBufferEnd = Math.min(bufferedEnd, seekRange.end);
var bufferStartDistance = clampedBufferStart - seekRange.start;
var bufferEndDistance = clampedBufferEnd - seekRange.start;
var playheadDistance = displayTime - seekRange.start;
}
/* this.dvrSeekBar_.style.background =
'linear-gradient(' + gradient.join(',') + ')'; */
};
DVRSeekBar.prototype.getSeekRange = function getSeekRange() {
if (this.player_.seekRange) {
return this.player_.seekRange();
}
return {
start: this.player_.seekable().start(0),
end: this.player_.seekable().end(0)
};
};
return DVRSeekBar;
}();
var Plugin = videojs.getPlugin('plugin');
// Default options for the plugin.
var defaults$1 = {
startTime: 0,
externalSeekable: null
};
/**
* An advanced Video.js plugin. For more information on the API
*
* See: https://blog.videojs.com/feature-spotlight-advanced-plugins/
*/
var Dvrseekbar = function (_Plugin) {
inherits(Dvrseekbar, _Plugin);
/**
* Create a Dvrseekbar plugin instance.
*
* @param {Player} player
* A Video.js Player instance.
*
* @param {Object} [options]
* An optional options object.
*
* While not a core part of the Video.js plugin architecture, a
* second argument of options is a convenient way to accept inputs
* from your plugin's caller.
*/
function Dvrseekbar(player, options) {
classCallCheck(this, Dvrseekbar);
var _this = possibleConstructorReturn(this, _Plugin.call(this, player));
// the parent class will add player under this.player
_this.options = videojs.mergeOptions(defaults$1, options);
_this.player.ready(function () {
_this.player.addClass('vjs-dvrseekbar');
});
_this.player.on('loadeddata', function () {
// if (this.dash && this.dash.shakaPlayer) {
_this.ifShakaPlayer();
/* } else {
this.on('timeupdate', e => {
onTimeUpdate(this, e);
});
this.on('pause', e => {
let btnLiveEl = document.getElementById('liveButton');
btnLiveEl.className = 'vjs-live-label';
});
iDontKnowWhatThisDoes(this, videojs.mergeOptions(defaults, options));
} */
});
_this.one('playing', function (e) {
var sourceHandler = _this.tech_.sourceHandler_;
if (options.flowMode) {
var startTime = 0;
if (sourceHandler.constructor.name === 'ShakaHandler') {
startTime = sourceHandler.shakaPlayer.seekRange().start + 30;
}
_this.currentTime(startTime);
}
});
return _this;
}
Dvrseekbar.prototype.onTimeUpdate = function onTimeUpdate(player, e) {
var time = player.seekableFromShaka && player.seekableFromShaka() || player.seekable();
var btnLiveEl = document.getElementById('liveButton');
// When any tech is disposed videojs will trigger a 'timeupdate' event
// when calling stopTrackingCurrentTime(). If the tech does not have
// a seekable() method, time will be undefined
if (!time || !time.length) {
return;
}
if (time.end(0) - player.currentTime() < 30) {
btnLiveEl.className = 'label onair';
} else {
btnLiveEl.className = 'label';
}
player.duration(time.end(0));
};
Dvrseekbar.prototype.ifShakaPlayer = function ifShakaPlayer() {
var dvrCurrentTime = document.createElement('div');
dvrCurrentTime.setAttribute('id', 'dvr-current-time');
dvrCurrentTime.innerHTML = '0:00';
dvrCurrentTime.className = 'vjs-current-time-display';
this.player.controlBar.progressControl.seekBar.hide();
this.player.controlBar.progressControl.disable();
var currentSrc = this.player.tech_ && this.player.tech_.currentSource_ || {};
// TODO: delete this
currentSrc.hasCatchUp = true;
//////////////////////
if (currentSrc.hasCatchUp) {
this.player.controlBar.el_.insertBefore(dvrCurrentTime, this.player.controlBar.progressControl.el_.nextSibling);
var dvrSeekBar = new DVRSeekBar(this.player, this.options);
this.player.controlBar.progressControl.el_.appendChild(dvrSeekBar.getEl());
}
};
Dvrseekbar.prototype.iDontKnowWhatThisDoes = function iDontKnowWhatThisDoes(player, options) {
player.addClass('vjs-dvrseekbar');
player.controlBar.addClass('vjs-dvrseekbar-control-bar');
if (player.controlBar.progressControl) {
player.controlBar.progressControl.addClass('vjs-dvrseekbar-progress-control');
}
// ADD Live Button:
var btnLiveEl = document.createElement('div');
var newLink = document.createElement('a');
btnLiveEl.className = 'vjs-live-button vjs-control';
newLink.innerHTML = document.getElementsByClassName('vjs-live-display')[0].innerHTML;
newLink.id = 'liveButton';
if (!player.paused()) {
newLink.className = 'vjs-live-label onair';
}
var clickHandler = function clickHandler(e) {
var livePosition = player.seekableFromShaka && player.seekableFromShaka().end() || player.seekable().end(0);
player.currentTime(livePosition - 1);
player.play();
e.target.className += ' onair';
};
if (newLink.addEventListener) {
// DOM method
newLink.addEventListener('click', clickHandler, false);
} else if (newLink.attachEvent) {
// this is for IE, because it doesn't support addEventListener
newLink.attachEvent('onclick', function () {
return clickHandler.apply(newLink, [window.event]);
});
}
btnLiveEl.appendChild(newLink);
var controlBar = document.getElementsByClassName('vjs-control-bar')[0];
var insertBeforeNode = document.getElementsByClassName('vjs-progress-control')[0];
controlBar.insertBefore(btnLiveEl, insertBeforeNode);
videojs.log('dvrSeekbar Plugin ENABLED!', options);
};
return Dvrseekbar;
}(Plugin);
// Define default values for the plugin's `state` object here.
Dvrseekbar.defaultState = {};
// Include the version number.
Dvrseekbar.VERSION = version;
// Register the plugin with video.js.
videojs.registerPlugin('dvrseekbar', Dvrseekbar);
return Dvrseekbar;
})));

File diff suppressed because one or more lines are too long

0
plugin/Live/view/Offline.jpg Normal file → Executable file
View file

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Before After
Before After

0
plugin/Live/view/OnAir.jpg Normal file → Executable file
View file

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Before After
Before After

0
plugin/Live/view/RtmpPublisher.swf Normal file → Executable file
View file

0
plugin/Live/view/expressInstall.swf Normal file → Executable file
View file

View file

View file

View file

0
plugin/Live/view/http-streaming/videojs-http-streaming.min.js vendored Normal file → Executable file
View file

0
plugin/Live/view/live.css Normal file → Executable file
View file

96
plugin/Live/view/modeYoutubeLive.php Normal file → Executable file
View file

@ -5,9 +5,9 @@ require_once $global['systemRootPath'] . 'objects/subscribe.php';
require_once $global['systemRootPath'] . 'objects/functions.php';
require_once $global['systemRootPath'] . 'plugin/Live/Objects/LiveTransmition.php';
if(!empty($_GET['c'])){
if (!empty($_GET['c'])) {
$user = User::getChannelOwner($_GET['c']);
if(!empty($user)){
if (!empty($user)) {
$_GET['u'] = $user['user'];
}
}
@ -25,6 +25,8 @@ $video['creator'] = '<div class="pull-left"><img src="' . User::getPhoto($user_i
$img = "{$global['webSiteRootURL']}plugin/Live/getImage.php?u={$_GET['u']}&format=jpg";
$imgw = 640;
$imgh = 360;
$liveDO = YouPHPTubePlugin::getObjectData("Live");
?>
<!DOCTYPE html>
<html lang="<?php echo $_SESSION['language']; ?>">
@ -38,7 +40,7 @@ $imgh = 360;
<?php
include $global['systemRootPath'] . 'view/include/head.php';
?>
<meta property="fb:app_id" content="774958212660408" />
<meta property="og:url" content="<?php echo $global['webSiteRootURL']; ?>plugin/Live/?u=<?php echo $_GET['u']; ?>" />
<meta property="og:type" content="video.other" />
@ -53,64 +55,80 @@ $imgh = 360;
<?php
include $global['systemRootPath'] . 'view/include/navbar.php';
$lt = new LiveTransmition($t['id']);
if($lt->userCanSeeTransmition()){
?>
<div class="container-fluid principalContainer " itemscope itemtype="http://schema.org/VideoObject">
<div class="col-md-12">
<?php
require "{$global['systemRootPath']}plugin/Live/view/liveVideo.php";
?>
</div>
</div>
<div class="container-fluid ">
<div class="col-md-5 col-md-offset-2 list-group-item">
<h1 itemprop="name">
<i class="fas fa-video"></i> <?php echo $t['title']; ?>
</h1>
<p><?php echo nl2br(textToLink($t['description'])); ?></p>
<div class="col-xs-12 col-sm-12 col-lg-12"><?php echo $video['creator']; ?></div>
</div>
<div class="col-md-3">
if ($lt->userCanSeeTransmition()) {
?>
<div class="container-fluid principalContainer " itemscope itemtype="http://schema.org/VideoObject">
<div class="col-md-12">
<?php
require "{$global['systemRootPath']}plugin/Live/view/liveVideo.php";
?>
</div>
</div>
<div class="container-fluid ">
<div class="col-md-5 col-md-offset-2 list-group-item">
<h1 itemprop="name">
<i class="fas fa-video"></i> <?php echo $t['title']; ?>
</h1>
<p><?php echo nl2br(textToLink($t['description'])); ?></p>
<div class="col-xs-12 col-sm-12 col-lg-12"><?php echo $video['creator']; ?></div>
</div>
<div class="col-md-3">
<?php
echo $config->getAdsense();
?>
</div>
</div>
</div>
<?php
}else{
<?php
} else {
?>
<h1 class="alert alert-danger"><i class="fa fa-exclamation-triangle"></i> <?php echo __("You are not allowed see this streaming"); ?></h1>
<h1 class="alert alert-danger"><i class="fa fa-exclamation-triangle"></i> <?php echo __("You are not allowed see this streaming"); ?></h1>
<?php
}
?>
<script src="<?php echo $global['webSiteRootURL']; ?>js/jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
<script>
/*** Handle jQuery plugin naming conflict between jQuery UI and Bootstrap ***/
$.widget.bridge('uibutton', $.ui.button);
$.widget.bridge('uitooltip', $.ui.tooltip);
/*** Handle jQuery plugin naming conflict between jQuery UI and Bootstrap ***/
$.widget.bridge('uibutton', $.ui.button);
$.widget.bridge('uitooltip', $.ui.tooltip);
</script>
<script src="<?php echo $global['webSiteRootURL']; ?>js/video.js/video.js" type="text/javascript"></script>
<script src="<?php echo $global['webSiteRootURL']; ?>js/videojs-contrib-ads/videojs.ads.min.js" type="text/javascript"></script>
<script src="<?php echo $global['webSiteRootURL']; ?>plugin/Live/view/videojs-contrib-hls.min.js" type="text/javascript"></script>
<?php
<?php
include $global['systemRootPath'] . 'view/include/footer.php';
?>
<?php
if(!empty($p)){
$p->getChat($uuid);
}
?>
<?php
if (empty($liveDO->disableDVR)) {
?>
<script src="<?php echo $global['webSiteRootURL']; ?>plugin/Live/videojs-dvr/videojs-dvrseekbar.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
if (typeof player === 'undefined') {
player = videojs('mainVideo');
}
player.dvrseekbar();
});
</script>
<?php
}
?>
<?php
if (!empty($p)) {
$p->getChat($uuid);
}
?>
<script src="<?php echo $global['webSiteRootURL']; ?>js/videojs-persistvolume/videojs.persistvolume.js" type="text/javascript"></script>
<script src="<?php echo $global['webSiteRootURL']; ?>js/webui-popover/jquery.webui-popover.min.js" type="text/javascript"></script>
<script src="<?php echo $global['webSiteRootURL']; ?>js/bootstrap-list-filter/bootstrap-list-filter.min.js" type="text/javascript"></script>
</body>
</html>
<?php
include $global['systemRootPath'].'objects/include_end.php';
include $global['systemRootPath'] . 'objects/include_end.php';
?>

0
plugin/Live/view/onlineUsers.php Normal file → Executable file
View file

0
plugin/Live/view/swfobject.js Normal file → Executable file
View file

View file

@ -124,6 +124,22 @@ if ($config->getAutoplay()) {
require_once $global['systemRootPath'] . 'plugin/YouPHPTubePlugin.php';
echo YouPHPTubePlugin::getFooterCode();
?>
<?php
if (empty($liveDO->disableDVR)) {
?>
<script src="<?php echo $global['webSiteRootURL']; ?>plugin/Live/videojs-dvr/videojs-dvrseekbar.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
if (typeof player === 'undefined') {
player = videojs('mainVideo');
}
player.dvrseekbar();
});
</script>
<?php
}
?>
</body>
</html>

View file

@ -171,5 +171,21 @@ if ($config->getAutoplay()) {
require_once $global['systemRootPath'] . 'plugin/YouPHPTubePlugin.php';
echo YouPHPTubePlugin::getFooterCode();
?>
<?php
if (empty($liveDO->disableDVR)) {
?>
<script src="<?php echo $global['webSiteRootURL']; ?>plugin/Live/videojs-dvr/videojs-dvrseekbar.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
if (typeof player === 'undefined') {
player = videojs('mainVideo');
}
player.dvrseekbar();
});
</script>
<?php
}
?>
</body>
</html>

0
plugin/Live/view/videojs-contrib-hls.min.js vendored Normal file → Executable file
View file

0
plugin/Live/view/webcam.swf Normal file → Executable file
View file