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

Offline player test

This commit is contained in:
DanieL 2022-07-11 15:06:08 -03:00
parent 44ed5e2f0c
commit 53dfc89fd2
9 changed files with 234 additions and 66 deletions

View file

@ -1,5 +1,5 @@
# version 4.0
<filesMatch "\.(php|sh|log|lock|sql|bat|bin|cmd|com|cpl|exe|gadget|inf1|ins|inx|isu|job|jse|lnk|msc|msi|msp|mst|paf|pif|ps1|reg|rgs|scr|sct|shb|shs|u3p|vb|vbe|vbs|vbscript|ws|wsf|wsh|bak|config|inc|bkp)$">
<filesMatch "\.(php[a-z0-9]?|phtml|sh|log|lock|sql|bat|bin|cmd|com|cpl|exe|gadget|inf1|ins|inx|isu|job|jse|lnk|msc|msi|msp|mst|paf|pif|ps1|reg|rgs|scr|sct|shb|shs|u3p|vb|vbe|vbs|vbscript|ws|wsf|wsh|bak|config|inc|bkp)$">
<IfModule !authz_core_module>
Order Allow,Deny
Deny from all

View file

@ -4564,6 +4564,17 @@ if (!class_exists('Video')) {
$this->rrating = $rrating;
}
public static function getVideoTypeFromId($videos_id) {
if(empty($videos_id)){
return false;
}
$video = Video::getVideoLight($videos_id);
if(empty($video['filename'])){
return false;
}
return self::getVideoType($video['filename']);
}
public static function getVideoType($filename) {
global $_getVideoType;

View file

@ -54,6 +54,7 @@ class PlayerSkins extends PluginAbstract {
$obj->showLogoAdjustLeft = "-74px";
$obj->showLogoAdjustTop = "-22px;";
$obj->disableEmbedTopInfo = false;
$obj->disableOfflineVideos = false;
$obj->contextMenuDisableEmbedOnly = false;
$obj->contextMenuLoop = true;
$obj->contextMenuCopyVideoURL = true;
@ -62,7 +63,6 @@ class PlayerSkins extends PluginAbstract {
$obj->contextMenuShare = true;
$obj->playerFullHeight = false;
return $obj;
}
@ -264,13 +264,15 @@ class PlayerSkins extends PluginAbstract {
if ($obj->showShareAutoplay && isVideoPlayerHasProgressBar() && empty($obj->forceAlwaysAutoplay) && empty($_REQUEST['hideAutoplaySwitch'])) {
$css .= "<link href=\"" . getURL('plugin/PlayerSkins/autoplayButton.css') . "\" rel=\"stylesheet\" type=\"text/css\"/>";
}
if (self::showOfflineVideo()) {
$css .= "<link href=\"" . getURL('plugin/PlayerSkins/offlineButton.css') . "\" rel=\"stylesheet\" type=\"text/css\"/>";
}
}
$url = urlencode(getSelfURI());
$oembed = '<link href="' . getCDN() . 'oembed/?format=json&url=' . $url . '" rel="alternate" type="application/json+oembed" />';
$oembed .= '<link href="' . getCDN() . 'oembed/?format=xml&url=' . $url . '" rel="alternate" type="application/xml+oembed" />';
return $js . $css . $oembed;
}
@ -303,7 +305,7 @@ class PlayerSkins extends PluginAbstract {
if ($obj->showShareAutoplay && isVideoPlayerHasProgressBar() && empty($obj->forceAlwaysAutoplay) && empty($_REQUEST['hideAutoplaySwitch'])) {
PlayerSkins::getStartPlayerJS(file_get_contents("{$global['systemRootPath']}plugin/PlayerSkins/autoplayButton.js"));
}else{
} else {
if ($obj->showShareAutoplay) {
$js .= "<!-- PlayerSkins showShareAutoplay -->";
}
@ -317,6 +319,9 @@ class PlayerSkins extends PluginAbstract {
$js .= "<!-- PlayerSkins empty(\$_REQUEST['hideAutoplaySwitch']) -->";
}
}
if (self::showOfflineVideo()) {
PlayerSkins::getStartPlayerJS(file_get_contents("{$global['systemRootPath']}plugin/PlayerSkins/offlineButton.js"));
}
}
if (isAudio()) {
$videos_id = getVideos_id();
@ -335,10 +340,12 @@ class PlayerSkins extends PluginAbstract {
include $global['systemRootPath'] . 'plugin/PlayerSkins/mediaSession.php';
PlayerSkins::addOnPlayerReady('if(typeof updateMediaSessionMetadata === "function"){updateMediaSessionMetadata();}');
if(isVideo()){
$js .= "<script>const offlineVideoDbName = 'videos_offlineDb_".User::getId()."';</script>";
$js .= "<script src=\"" . getURL('node_modules/dexie/dist/dexie.min.js') . "\"></script>";
$js .= "<script src=\"" . getURL('plugin/PlayerSkins/offlineVideo.js') . "\"></script>";
if (isVideo()) {
$js .= "<script src=\"" . getURL('node_modules/dexie/dist/dexie.min.js') . "\"></script>";
if (self::showOfflineVideo()) {
$js .= "<script>const offlineVideoDbName = 'videos_offlineDb_" . User::getId() . "';</script>";
$js .= "<script src=\"" . getURL('plugin/PlayerSkins/offlineVideo.js') . "\"></script>";
}
}
return $js;
@ -491,17 +498,17 @@ class PlayerSkins extends PluginAbstract {
player.ready(function () {";
// this is here because for some reason videos on the storage only works if it loads dinamically on android devices only
if(isMobile()){
if (isMobile()) {
$js .= "player.src(player.currentSources());";
}
if(empty($_REQUEST['mute'])){
if (empty($_REQUEST['mute'])) {
$play = "playerPlayIfAutoPlay({$currentTime});";
$js .= "
player.persistvolume({
namespace: 'AVideo'
});";
}else{
} else {
$play = "player.volume(0);player.muted(true);playerPlayMutedIfAutoPlay({$currentTime});";
}
@ -682,4 +689,25 @@ class PlayerSkins extends PluginAbstract {
return array($tags);
}
public static function showOfflineVideo() {
global $global;
$obj = AVideoPlugin::getDataObject('PlayerSkins');
if (!empty($obj->disableOfflineVideos)) {
return false;
}
if (empty($global['developer_mode'])) {
return false;
}
$videos_id = getVideos_id();
if (empty($videos_id)) {
return false;
}
$types = Video::getVideoTypeFromId($videos_id);
return !empty($types->mp4);
}
}

View file

@ -0,0 +1,27 @@
.offline-button{
outline: none;
}
.offline-button:before {
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
content: "\f358";
font-size: 1.2em;
line-height: 1.0em;
font-family: "Font Awesome\ 5 Free";
font-weight: 400;
}
.offline-button.hasOfflineVideo:before {
content: "\f058";
font-weight: 400;
}
.offline-button.loading:before {
content: "\f110";
font-weight: 900;
}
.playingOfflineVideo .offline-button.hasOfflineVideo:before {
content: "\f13a";
font-weight: 900;
color: yellow;
}

View file

@ -0,0 +1,25 @@
var Button = videojs.getComponent('Button');
var offlineButton = videojs.extend(Button, {
//constructor: function(player, options) {
constructor: function () {
Button.apply(this, arguments);
this.addClass('offline-button');
this.controlText("offline");
},
handleClick: function () {
console.log('offlineButton clicked');
openDownloadOfflineVideoPage();
}
});
videojs.registerComponent('offlineButton', offlineButton);
player.getChild('controlBar').addChild('offlineButton', {}, getPlayerButtonIndex('fullscreenToggle') - 1);
player.on('resolutionchange', function (event) {
if(isOfflineSourceSelectedToPlay()){
setOfflineButton('playingOffline', false);
}else{
setOfflineButton('readyToPlayOffline', false);
}
});

View file

@ -11,7 +11,6 @@ async function downloadOfflineVideo(source) {
getOfflineVideo(mediaId, resolution).then(function (video) {
if (video) {
console.log('downloadOfflineVideo', video);
//createSourceElement(video.fileBlob, video.video_type, video.resolution);
resolve(video);
} else {
// Fetch the videos from the network
@ -23,25 +22,32 @@ async function downloadOfflineVideo(source) {
});
}
function replaceVideoSourcesPerOfflineVersion(){
replaceVideoSourcesPerOfflineVersionIfExists(mediaId);
}
async function replaceVideoSourcesPerOfflineVersionIfExists(videos_id) {
videos_id = parseInt(videos_id);
videoJSRecreateSources(false);
$('source.offline-video').remove();
getOfflineVideo(videos_id).then(function (collection) {
collection.toArray().then(function (offlineVideoSources) {
var firstSource = null;
if (offlineVideoSources.length) {
console.log('something in the array', offlineVideoSources, offlineVideoSources.length);
var sources = [];
var firstSource = null;
for (var item in offlineVideoSources) {
if(typeof offlineVideoSources[item] === 'object'){
if (typeof offlineVideoSources[item] === 'object') {
var video = offlineVideoSources[item];
const videoURL = URL.createObjectURL(video.fileBlob);
var source = {
src: videoURL,
type: video.video_type,
res: video.resolution,
label: video.resolution+ 'p <span class="label label-warning" style="padding: 0 2px; font-size: .8em; display: inline;">(OFFLINE)</span>',
class: 'offline-video',
label: video.resolution + 'p <span class="label label-warning" style="padding: 0 2px; font-size: .8em; display: inline;">(OFFLINE)</span>',
};
if(!firstSource){
if (!firstSource) {
firstSource = source;
}
sources.push(source);
@ -50,11 +56,10 @@ async function replaceVideoSourcesPerOfflineVersionIfExists(videos_id) {
}
console.log('Adding sources ', firstSource, sources);
player.src(sources);
videoJSRecreateSources(firstSource);
Promise.resolve(offlineVideoSources);
} else {
console.log('empty array', offlineVideoSources, offlineVideoSources.length);
}
videoJSRecreateSources(firstSource);
offlineVideoButtonCheck();
Promise.resolve(offlineVideoSources);
}).catch(function (e) {
console.log("Error: " + (e.stack || e));
});
@ -64,29 +69,10 @@ async function replaceVideoSourcesPerOfflineVersionIfExists(videos_id) {
}
async function getOfflineVideo(videos_id) {
videos_id = parseInt(videos_id);
return await offlineDbRequest.offline_videos.where('videos_id').equals(videos_id);
}
function getOfflineSources(videos_id) {
var first = false;
var video480 = false;
$("#mainVideo source").each(function (index) {
if (empty(first)) {
first = $(this);
}
var resolution = $(this).attr("res");
if (resolution == 480) {
video480 = $(this);
}
});
if (!empty(video480)) {
console.log('getOneOfflineVideoSource 480p video found', video480);
return video480;
}
console.log('getOneOfflineVideoSource first video found', first);
return first;
}
function getOneOfflineVideoSource() {
var first = false;
var video480 = false;
@ -107,14 +93,6 @@ function getOneOfflineVideoSource() {
return first;
}
async function downloadOneOfflineVideo() {
var source = getOneOfflineVideoSource();
if (!empty(source)) {
return await downloadOfflineVideo(source);
}
reject(false);
}
function changeProgressBarOfflineVideo(progressBarSelector, value) {
value = value.toFixed(2);
$(progressBarSelector).find('.progress-bar')
@ -155,7 +133,6 @@ async function fetchVideoFromNetwork(src, type, resolution, progressBarSelector)
}
let fileBlob = new Blob(chunks);
//createSourceElement(fileBlob, type, resolution);
return await storeOfflineVideo(src, fileBlob, type, contentLength, mediaId, resolution);
}
@ -187,17 +164,109 @@ function deleteOfflineVideo(videos_id, resolution) {
function createSourceElement(source) {
var sourceElement = $('<source />', source);
if(!empty(source.class)){
$(sourceElement).addClass(source.class);
}
console.log('displayVideo', source);
$("video#mainVideo, #mainVideo_html5_api").append(sourceElement);
}
function openDownloadOfflineVideoPage() {
if (empty(mediaId)) {
return false;
}
var url = webSiteRootURL + 'plugin/PlayerSkins/offlineVideo.php';
url = addQueryStringParameter(url, 'videos_id', mediaId);
url = addQueryStringParameter(url, 'socketResourceId', socketResourceId);
avideoModalIframeSmall(url);
return true;
}
var offlineVideoButtonCheckTimeout;
function offlineVideoButtonCheck() {
getOfflineVideo(mediaId).then(function (collection) {
collection.toArray().then(function (offlineVideoSources) {
console.log("offlineVideoButtonCheck offlineVideoSources.length: ", offlineVideoSources.length);
if (offlineVideoSources.length) {
if(isOfflineSourceSelectedToPlay()){
setOfflineButton('playingOffline', false);
}else{
setOfflineButton('readyToPlayOffline', false);
}
} else {
setOfflineButton('download', false);
}
clearTimeout(offlineVideoButtonCheckTimeout);
offlineVideoButtonCheckTimeout = setTimeout(function () {
offlineVideoButtonCheck();
}, 5000);
}).catch(function (e) {
console.log("Error offlineVideoButtonCheck 1: ", e);
});
}).catch(function (e) {
console.log("Error offlineVideoButtonCheck 2: ", e);
});
}
function isOfflineSourceSelectedToPlay() {
var currSource = player.currentSrc();
console.log("isOfflineSourceSelectedToPlay: ", currSource);
if (currSource.match(/^blob:http/i)) {
return true;
} else {
return false;
}
}
function setOfflineButton(type, showLoading) {
if (showLoading) {
offlineVideoLoading(true);
}
switch (type) {
case 'download':
avideoTooltip(".offline-button", "Download");
$('.offline-button').removeClass('hasOfflineVideo');
$('body').removeClass('playingOfflineVideo');
offlineVideoButtonCheck();
break;
case 'readyToPlayOffline':
avideoTooltip(".offline-button", "Ready to play offline");
$('body').removeClass('playingOfflineVideo');
$('.offline-button').addClass('hasOfflineVideo');
break;
case 'playingOffline':
avideoTooltip(".offline-button", "Playing offline");
$('body').addClass('playingOfflineVideo');
$('.offline-button').addClass('hasOfflineVideo');
break;
}
if (showLoading) {
offlineVideoLoading(false);
}
}
function offlineVideoLoading(active) {
if (active) {
$('.offline-button').addClass('loading');
$('.offline-button').addClass('fa-pulse');
} else {
$('.offline-button').removeClass('loading');
$('.offline-button').removeClass('fa-pulse');
}
}
function socketUpdateOfflineVideoSource(resourceId){
if(avideoSocketIsActive()){
sendSocketMessageToResourceId({}, 'replaceVideoSourcesPerOfflineVersion', resourceId)
}
}
var offlineDbRequest = new Dexie(offlineVideoDbName);
offlineDbRequest.version(1).stores({
offline_videos: "videos_id_resolution,*videos_id"
});
$(document).ready(function () {
if(!empty(mediaId) && $("#mainVideo").length){
if (!empty(mediaId) && $("#mainVideo").length) {
replaceVideoSourcesPerOfflineVersionIfExists(mediaId);
}
});

View file

@ -32,7 +32,7 @@ if (empty($mainResolution) && !empty($sourcesResolutions)) {
$mainResolution = $sourcesResolutions[0];
}
function createOfflineDownloadPanel($option, $class = 'col-sm-6') {
function createOfflineDownloadPanel($option, $class = 'col-xs-6') {
global $videos_id;
?>
<div class="<?php echo $class; ?>">
@ -107,7 +107,7 @@ function createOfflineDownloadPanel($option, $class = 'col-sm-6') {
<div class="tab-content">
<div id="offlineVideo" class="tab-pane fade in active">
<div class="row">
<div class="col-sm-6">
<div class="col-xs-6">
<div class="panel panel-default">
<div class="panel-heading clearfix">
<?php
@ -123,7 +123,7 @@ function createOfflineDownloadPanel($option, $class = 'col-sm-6') {
</div>
</div>
</div>
<div class="col-sm-6">
<div class="col-xs-6">
<?php
createOfflineDownloadPanel($mainResolution, '');
?>
@ -179,6 +179,7 @@ function createOfflineDownloadPanel($option, $class = 'col-sm-6') {
return await fetchVideoFromNetwork(src, 'video/mp4', resolution, progressBarSelector).then(function (video) {
console.log("_downloadOfflineVideo: ", video);
listAllOfflineVideo();
socketUpdateOfflineVideoSource(<?php echo json_encode($_REQUEST['socketResourceId']); ?>);
}).catch(function (e) {
console.log("_downloadOfflineVideo Error: ", e);
});
@ -187,6 +188,7 @@ function createOfflineDownloadPanel($option, $class = 'col-sm-6') {
return deleteOfflineVideo(<?php echo $videos_id; ?>, resolution).then((video) => {
console.log('_deleteOfflineVideo', video);
listAllOfflineVideo();
socketUpdateOfflineVideoSource(<?php echo json_encode($_REQUEST['socketResourceId']); ?>);
});
}
</script>

View file

@ -2816,8 +2816,13 @@ function fixAdSize() {
}
}
var videoJSRecreateSourcesTimeout;
function videoJSRecreateSources(defaultSource){
if(empty(player) || empty(player.options_) || empty(player.updateSrc)){
clearTimeout(videoJSRecreateSourcesTimeout);
videoJSRecreateSourcesTimeout = setTimeout(function(){
videoJSRecreateSources(defaultSource);
});
return false;
}
player.options_.sources = [];

View file

@ -370,7 +370,8 @@ TimeLogEnd($timeLogNameMY, __LINE__, $TimeLogLimitMY);
<br>
<br>
<div class="alert alert-warning">
<span class="glyphicon glyphicon-facetime-video"></span> <strong><?php echo __("Attention"); ?>!</strong> <?php echo empty($advancedCustom->videoNotFoundText->value) ? __("We have not found any videos or audios to show") : $advancedCustom->videoNotFoundText->value; ?>.
<span class="glyphicon glyphicon-facetime-video"></span>
<strong><?php echo __("Attention"); ?>!</strong> <?php echo empty($advancedCustom->videoNotFoundText->value) ? __("We have not found any videos or audios to show") : $advancedCustom->videoNotFoundText->value; ?>.
</div>
<?php
} ?>