Add DVR support
|
@ -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
0
plugin/Live/Objects/LiveTransmitionHistoryLog.php
Normal file → Executable file
0
plugin/Live/install/install.sql
Normal file → Executable file
0
plugin/Live/install/nginx.conf
Normal file → Executable file
0
plugin/Live/install/nginx.old.conf
Normal file → Executable file
0
plugin/Live/install/updateV2.0.sql
Normal file → Executable file
0
plugin/Live/install/updateV3.0.sql
Normal file → Executable file
0
plugin/Live/on_play.php
Normal file → Executable file
0
plugin/Live/on_publish.php
Normal file → Executable file
0
plugin/Live/on_record_done.php
Normal file → Executable file
0
plugin/Live/report.php
Normal file → Executable file
0
plugin/Live/sample-player.zip
Normal file → Executable file
0
plugin/Live/sample-player/index.html
Normal file → Executable file
0
plugin/Live/sample-player/poster.jpg
Normal file → Executable file
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
0
plugin/Live/sample-player/video.js/font/VideoJS.eot
Normal file → Executable file
0
plugin/Live/sample-player/video.js/font/VideoJS.svg
Normal file → Executable file
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
0
plugin/Live/sample-player/video.js/font/VideoJS.ttf
Normal file → Executable file
0
plugin/Live/sample-player/video.js/font/VideoJS.woff
Normal file → Executable file
0
plugin/Live/sample-player/video.js/ie8/videojs-ie8.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/ie8/videojs-ie8.min.js
vendored
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/ar.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/ba.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/bg.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/ca.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/cs.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/da.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/de.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/el.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/en.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/es.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/fa.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/fi.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/fr.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/hr.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/hu.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/it.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/ja.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/ko.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/nb.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/nl.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/nn.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/pl.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/pt-BR.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/ru.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/sr.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/sv.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/tr.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/uk.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/vi.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/zh-CN.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/lang/zh-TW.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/video-js.css
Normal file → Executable file
0
plugin/Live/sample-player/video.js/video-js.min.css
vendored
Normal file → Executable file
0
plugin/Live/sample-player/video.js/video-js.swf
Normal file → Executable file
0
plugin/Live/sample-player/video.js/video.js
Normal file → Executable file
0
plugin/Live/sample-player/video.js/video.min.js
vendored
Normal file → Executable file
0
plugin/Live/sample-player/video.js/videojs-contrib-hls.min.js
vendored
Normal file → Executable file
0
plugin/Live/saveLive.php
Normal file → Executable file
3
plugin/Live/videojs-dvr/lang/en.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
videojs.addLanguage('en', {
|
||||
"Include your own strings in JSON files.": "Include your own strings in JSON files."
|
||||
});
|
523
plugin/Live/videojs-dvr/videojs-dvrseekbar.cjs.js
Normal 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;
|
1
plugin/Live/videojs-dvr/videojs-dvrseekbar.css
Normal 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}
|
492
plugin/Live/videojs-dvr/videojs-dvrseekbar.es.js
Normal 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;
|
527
plugin/Live/videojs-dvr/videojs-dvrseekbar.js
Normal 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;
|
||||
|
||||
})));
|
2
plugin/Live/videojs-dvr/videojs-dvrseekbar.min.js
vendored
Normal file
0
plugin/Live/view/Offline.jpg
Normal file → Executable file
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
0
plugin/Live/view/OnAir.jpg
Normal file → Executable file
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 211 KiB |
0
plugin/Live/view/RtmpPublisher.swf
Normal file → Executable file
0
plugin/Live/view/expressInstall.swf
Normal file → Executable file
0
plugin/Live/view/http-streaming/videojs-http-streaming.cjs.js
Normal file → Executable file
0
plugin/Live/view/http-streaming/videojs-http-streaming.es.js
Normal file → Executable file
0
plugin/Live/view/http-streaming/videojs-http-streaming.js
Normal file → Executable file
0
plugin/Live/view/http-streaming/videojs-http-streaming.min.js
vendored
Normal file → Executable file
0
plugin/Live/view/live.css
Normal file → Executable file
96
plugin/Live/view/modeYoutubeLive.php
Normal file → Executable 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
0
plugin/Live/view/swfobject.js
Normal file → Executable 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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|