2018-03-10 22:06:42 +01:00
|
|
|
/*
|
2018-07-24 03:11:56 +02:00
|
|
|
This file is part of FreeTube.
|
2018-03-10 22:06:42 +01:00
|
|
|
|
2018-07-24 03:11:56 +02:00
|
|
|
FreeTube is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2018-03-10 22:06:42 +01:00
|
|
|
|
2018-07-24 03:11:56 +02:00
|
|
|
FreeTube is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2018-03-10 22:06:42 +01:00
|
|
|
|
2018-07-24 03:11:56 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with FreeTube. If not, see <http://www.gnu.org/licenses/>.
|
2018-03-10 22:06:42 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2018-03-12 04:06:30 +01:00
|
|
|
* File for functions related to videos.
|
|
|
|
*/
|
2018-03-10 22:06:42 +01:00
|
|
|
|
2019-04-11 21:42:08 +02:00
|
|
|
let checkedSettings = false;
|
|
|
|
|
2018-03-10 22:06:42 +01:00
|
|
|
/**
|
2018-03-12 04:06:30 +01:00
|
|
|
* Display the video player and play a video
|
|
|
|
*
|
|
|
|
* @param {string} videoId - The video ID of the video to be played.
|
|
|
|
*
|
|
|
|
* @return {Void}
|
|
|
|
*/
|
2018-09-28 21:48:42 +02:00
|
|
|
function playVideo(videoId, playlistId = '') {
|
2018-09-19 17:01:21 +02:00
|
|
|
hideViews();
|
2018-04-01 00:14:07 +02:00
|
|
|
|
2019-03-19 18:45:25 +01:00
|
|
|
let youtubedlFinished = false;
|
|
|
|
let invidiousFinished = false;
|
2019-04-11 21:42:08 +02:00
|
|
|
checkedSettings = false;
|
2018-09-24 20:19:43 +02:00
|
|
|
playerView.firstLoad = true;
|
2018-09-19 17:01:21 +02:00
|
|
|
playerView.videoId = videoId;
|
2018-09-24 20:19:43 +02:00
|
|
|
playerView.videoAudio = undefined;
|
|
|
|
playerView.validAudio = true;
|
2019-04-16 19:09:29 +02:00
|
|
|
playerView.video360p = undefined;
|
|
|
|
playerView.valid360p = true;
|
2018-09-19 17:01:21 +02:00
|
|
|
playerView.video720p = undefined;
|
2018-09-21 21:56:59 +02:00
|
|
|
playerView.valid720p = true;
|
2019-02-27 19:46:25 +01:00
|
|
|
playerView.videoUrl = '';
|
2019-05-20 17:35:29 +02:00
|
|
|
playerView.currentTime = undefined;
|
2019-05-02 21:47:23 +02:00
|
|
|
playerView.subtitleHtml = '';
|
2019-04-25 21:53:38 +02:00
|
|
|
playerView.videoLive = undefined;
|
|
|
|
playerView.validLive = false;
|
2019-04-16 19:09:29 +02:00
|
|
|
playerView.validDash = true;
|
|
|
|
playerView.videoDash = invidiousInstance + '/api/manifest/dash/' + videoId + '.mpd';
|
2018-09-19 17:01:21 +02:00
|
|
|
playerView.embededHtml = "<iframe width='560' height='315' src='https://www.youtube-nocookie.com/embed/" + videoId + "?rel=0' frameborder='0' allow='autoplay; encrypted-media' allowfullscreen></iframe>";
|
|
|
|
|
|
|
|
let videoHtml = '';
|
2019-04-11 21:42:08 +02:00
|
|
|
let player;
|
2018-07-24 03:11:56 +02:00
|
|
|
|
2019-05-02 21:47:23 +02:00
|
|
|
switch (defaultPlayer) {
|
|
|
|
case 'dash':
|
|
|
|
playerView.playerSeen = true;
|
|
|
|
playerView.legacySeen = false;
|
|
|
|
break;
|
|
|
|
case 'legacy':
|
|
|
|
playerView.playerSeen = false;
|
|
|
|
playerView.legacySeen = true;
|
|
|
|
break;
|
|
|
|
case 'embed':
|
|
|
|
playerView.playerSeen = false;
|
|
|
|
playerView.legacySeen = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-07-24 03:11:56 +02:00
|
|
|
const checkSavedVideo = videoIsSaved(videoId);
|
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
// Change the save button icon and text depending on if the user has saved the video or not.
|
|
|
|
checkSavedVideo.then((results) => {
|
|
|
|
if (results === false) {
|
|
|
|
playerView.savedText = 'FAVORITE';
|
|
|
|
playerView.savedIconType = 'far unsaved';
|
|
|
|
} else {
|
|
|
|
playerView.savedText = 'FAVORITED';
|
|
|
|
playerView.savedIconType = 'fas saved';
|
|
|
|
}
|
2018-03-10 22:06:42 +01:00
|
|
|
});
|
2019-02-26 15:53:18 +01:00
|
|
|
|
2019-04-16 19:09:29 +02:00
|
|
|
if (getVideosLocally) {
|
|
|
|
youtubedlGetInfo(videoId, (data) => {
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log(data);
|
2019-04-16 19:09:29 +02:00
|
|
|
|
|
|
|
let videoUrls = data.formats;
|
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
if (data.player_response.videoDetails.isLiveContent !== false) {
|
|
|
|
playerView.validDash = false;
|
|
|
|
playerView.valid360p = false;
|
|
|
|
playerView.valid720p = false;
|
|
|
|
playerView.validAudio = false;
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-05-20 17:35:29 +02:00
|
|
|
playerView.playerSeen = true;
|
|
|
|
playerView.legacySeen = false;
|
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
playerView.validLive = true;
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
youtubedlFinished = true;
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
if (youtubedlFinished && invidiousFinished) {
|
|
|
|
loadingView.seen = false;
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
if (subscriptionView.seen === false && aboutView.seen === false && headerView.seen === false && searchView.seen === false && settingsView.seen === false && popularView.seen === false && savedView.seen === false && historyView.seen === false && channelView.seen === false && channelVideosView.seen === false) {
|
|
|
|
playerView.seen = true;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2019-04-16 19:09:29 +02:00
|
|
|
}
|
2019-04-25 21:53:38 +02:00
|
|
|
else {
|
|
|
|
playerView.validLive = false;
|
|
|
|
|
|
|
|
// Search through the returned object to get the 360p and 720p video URLs (If available)
|
|
|
|
Object.keys(videoUrls).forEach((key) => {
|
|
|
|
switch (videoUrls[key]['itag']) {
|
|
|
|
case '18':
|
|
|
|
playerView.video360p = decodeURIComponent(videoUrls[key]['url']);
|
2019-05-20 20:53:14 +02:00
|
|
|
// ft.log(playerView.video360p);
|
2019-04-25 21:53:38 +02:00
|
|
|
break;
|
|
|
|
case '22':
|
|
|
|
playerView.video720p = decodeURIComponent(videoUrls[key]['url']);
|
2019-05-20 20:53:14 +02:00
|
|
|
// ft.log(playerView.video720p);
|
2019-04-25 21:53:38 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-05-02 21:47:23 +02:00
|
|
|
if (videoUrls.length > 3) {
|
|
|
|
// Last adaptive format will be the best quality audio stream
|
|
|
|
playerView.videoAudio = decodeURIComponent(videoUrls[videoUrls.length - 1]['url']);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
playerView.playerSeen = false;
|
|
|
|
playerView.legacySeen = true;
|
|
|
|
}
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
if (typeof (playerView.videoAudio) === 'undefined') {
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log(playerView.videoAudio);
|
2019-04-25 21:53:38 +02:00
|
|
|
playerView.validAudio = false;
|
|
|
|
}
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
let useEmbedPlayer = false;
|
|
|
|
|
|
|
|
// Default to the embeded player if the URLs cannot be found.
|
|
|
|
if (typeof (playerView.video720p) === 'undefined' && typeof (playerView.video360p) === 'undefined') {
|
|
|
|
//useEmbedPlayer = true;
|
|
|
|
playerView.currentQuality = 'EMBED';
|
|
|
|
playerView.playerSeen = false;
|
|
|
|
playerView.valid720p = false;
|
|
|
|
playerView.valid360p = false;
|
|
|
|
playerView.video720p = '';
|
|
|
|
//useEmbedPlayer = true;
|
|
|
|
showToast('Unable to get video file. Reverting to embeded player.');
|
|
|
|
} else if (typeof (playerView.video720p) === 'undefined' && typeof (playerView.video360p) !== 'undefined') {
|
|
|
|
// Default to the 360p video if the 720p URL cannot be found.
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log('Found');
|
2019-04-25 21:53:38 +02:00
|
|
|
playerView.videoUrl = playerView.video360p;
|
|
|
|
playerView.currentQuality = '360p';
|
|
|
|
playerView.valid720p = false;
|
|
|
|
playerView.video720p = '';
|
|
|
|
} else {
|
|
|
|
// Default to the 720p video.
|
|
|
|
playerView.videoUrl = playerView.video720p;
|
|
|
|
playerView.currentQuality = '720p';
|
|
|
|
//playerView.videoUrl = playerView.liveManifest;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!useEmbedPlayer &&
|
|
|
|
typeof (data.player_response.captions) !== 'undefined' &&
|
|
|
|
typeof (data.player_response.captions.playerCaptionsTracklistRenderer) !== 'undefined' &&
|
|
|
|
typeof (data.player_response.captions.playerCaptionsTracklistRenderer.captionTracks) !== 'undefined') {
|
|
|
|
data.player_response.captions.playerCaptionsTracklistRenderer.captionTracks.forEach((caption) => {
|
|
|
|
let subtitleUrl = invidiousInstance + '/api/v1/captions/' + videoId + '?label=' + caption.name.simpleText;
|
|
|
|
|
|
|
|
videoHtml = videoHtml + '<track kind="subtitles" src="' + subtitleUrl + '" srclang="' + caption.languageCode + '" label="' + caption.name.simpleText + '">';
|
|
|
|
});
|
2019-04-16 19:09:29 +02:00
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
playerView.subtitleHtml = videoHtml;
|
|
|
|
}
|
|
|
|
}
|
2019-04-16 19:09:29 +02:00
|
|
|
youtubedlFinished = true;
|
|
|
|
|
|
|
|
if (youtubedlFinished && invidiousFinished) {
|
|
|
|
loadingView.seen = false;
|
|
|
|
|
|
|
|
if (subscriptionView.seen === false && aboutView.seen === false && headerView.seen === false && searchView.seen === false && settingsView.seen === false && popularView.seen === false && savedView.seen === false && historyView.seen === false && channelView.seen === false && channelVideosView.seen === false) {
|
|
|
|
playerView.seen = true;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
youtubedlFinished = true;
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log("Grabbing videos through Invidious");
|
2019-04-16 19:09:29 +02:00
|
|
|
}
|
2019-02-26 15:53:18 +01:00
|
|
|
|
|
|
|
invidiousAPI('videos', videoId, {}, (data) => {
|
2018-09-19 17:01:21 +02:00
|
|
|
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log(data);
|
2018-09-21 16:49:23 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
// Figure out the width for the like/dislike bar.
|
|
|
|
playerView.videoLikes = data.likeCount;
|
|
|
|
playerView.videoDislikes = data.dislikeCount;
|
|
|
|
let totalLikes = parseInt(playerView.videoLikes) + parseInt(playerView.videoDislikes);
|
|
|
|
playerView.likePercentage = parseInt((playerView.videoLikes / totalLikes) * 100);
|
|
|
|
playerView.videoTitle = data.title;
|
|
|
|
playerView.channelName = data.author;
|
|
|
|
playerView.channelId = data.authorId;
|
2018-10-15 21:00:14 +02:00
|
|
|
playerView.channelIcon = data.authorThumbnails[2].url;
|
2019-05-21 03:27:10 +02:00
|
|
|
playerView.lengthSeconds = data.lengthSeconds;
|
2018-09-19 17:01:21 +02:00
|
|
|
|
2019-05-02 21:47:23 +02:00
|
|
|
if (playerView.channelIcon.includes('https:') === false) {
|
|
|
|
playerView.channelIcon = 'https:' + playerView.channelIcon;
|
|
|
|
}
|
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
// Add commas to the video view count.
|
|
|
|
playerView.videoViews = data.viewCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
|
|
|
|
|
|
playerView.videoThumbnail = data.videoThumbnails[0].url;
|
|
|
|
|
|
|
|
// Format the date to a more readable format.
|
2018-09-21 21:56:59 +02:00
|
|
|
let dateString = new Date(data.published * 1000);
|
2018-09-19 17:01:21 +02:00
|
|
|
dateString.setDate(dateString.getDate() + 1);
|
|
|
|
playerView.publishedDate = dateFormat(dateString, "mmm dS, yyyy");
|
|
|
|
|
2018-10-16 16:20:46 +02:00
|
|
|
playerView.description = parseDescription(data.descriptionHtml);
|
2018-09-19 17:01:21 +02:00
|
|
|
|
|
|
|
const checkSubscription = isSubscribed(playerView.channelId);
|
|
|
|
|
|
|
|
checkSubscription.then((results) => {
|
|
|
|
if (results === false) {
|
2019-02-27 19:46:25 +01:00
|
|
|
playerView.subscribedText = 'SUBSCRIBE';
|
2018-09-19 17:01:21 +02:00
|
|
|
} else {
|
2019-02-27 19:46:25 +01:00
|
|
|
playerView.subscribedText = 'UNSUBSCRIBE';
|
2018-07-24 03:11:56 +02:00
|
|
|
}
|
2018-09-19 17:01:21 +02:00
|
|
|
});
|
2018-06-02 00:17:33 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
playerView.recommendedVideoList = [];
|
2018-06-02 00:17:33 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
data.recommendedVideos.forEach((video) => {
|
|
|
|
let data = {};
|
2018-06-02 00:17:33 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
let time = video.lengthSeconds;
|
|
|
|
let hours = 0;
|
2018-06-11 04:58:25 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
if (time >= 3600) {
|
|
|
|
hours = Math.floor(time / 3600);
|
|
|
|
time = time - hours * 3600;
|
|
|
|
}
|
2018-06-02 00:17:33 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
let minutes = Math.floor(time / 60);
|
|
|
|
let seconds = time - minutes * 60;
|
2018-03-12 04:06:30 +01:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
if (seconds < 10) {
|
|
|
|
seconds = '0' + seconds;
|
|
|
|
}
|
2018-07-24 03:11:56 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
if (hours > 0) {
|
|
|
|
data.duration = hours + ":" + minutes + ":" + seconds;
|
|
|
|
} else {
|
|
|
|
data.duration = minutes + ":" + seconds;
|
|
|
|
}
|
2018-06-25 22:04:11 +02:00
|
|
|
|
2018-09-24 20:19:43 +02:00
|
|
|
data.id = video.videoId;
|
2018-09-19 17:01:21 +02:00
|
|
|
data.title = video.title;
|
|
|
|
data.channelName = video.author;
|
2018-09-21 16:49:23 +02:00
|
|
|
data.thumbnail = video.videoThumbnails[4].url;
|
2018-09-19 17:01:21 +02:00
|
|
|
data.viewCount = video.viewCountText;
|
2018-03-12 04:06:30 +01:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
playerView.recommendedVideoList = playerView.recommendedVideoList.concat(data);
|
|
|
|
});
|
2018-05-14 16:39:02 +02:00
|
|
|
|
2019-04-16 19:09:29 +02:00
|
|
|
if (!getVideosLocally) {
|
|
|
|
let videoUrls = data.formatStreams;
|
|
|
|
let formatUrls = data.adaptiveFormats;
|
|
|
|
|
|
|
|
// Search through the returned object to get the 360p and 720p video URLs (If available)
|
|
|
|
Object.keys(videoUrls).forEach((key) => {
|
|
|
|
switch (videoUrls[key]['itag']) {
|
|
|
|
case '18':
|
|
|
|
playerView.video360p = decodeURIComponent(videoUrls[key]['url']);
|
2019-05-20 20:53:14 +02:00
|
|
|
// ft.log(playerView.video360p);
|
2019-04-16 19:09:29 +02:00
|
|
|
break;
|
|
|
|
case '22':
|
|
|
|
playerView.video720p = decodeURIComponent(videoUrls[key]['url']);
|
2019-05-20 20:53:14 +02:00
|
|
|
// ft.log(playerView.video720p);
|
2019-04-16 19:09:29 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (typeof(playerView.video360p) === 'undefined') {
|
|
|
|
playerView.video360p = '';
|
|
|
|
playerView.valid360p = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof(playerView.video720p) === 'undefined') {
|
|
|
|
playerView.video720p = '';
|
|
|
|
playerView.valid720p = false;
|
|
|
|
}
|
|
|
|
|
2019-05-20 17:35:29 +02:00
|
|
|
if ((parseInt(defaultQuality) >= 720 || defaultQuality === '4k') && playerView.video720p !== '') {
|
2019-05-01 21:59:42 +02:00
|
|
|
playerView.videoUrl = playerView.video720p;
|
|
|
|
playerView.currentQuality = '720p';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
playerView.videoUrl = playerView.video360p;
|
|
|
|
playerView.currentQuality = '360p';
|
|
|
|
}
|
|
|
|
|
2019-05-02 21:47:23 +02:00
|
|
|
if (formatUrls.length > 0) {
|
|
|
|
// Last adaptive format will be best the quality audio stream (migrate fully to adaptive formats later)
|
|
|
|
playerView.videoAudio = decodeURIComponent(formatUrls[formatUrls.length - 1]['url']);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
playerView.playerSeen = false;
|
|
|
|
playerView.legacySeen = true;
|
|
|
|
}
|
2019-04-16 19:09:29 +02:00
|
|
|
|
|
|
|
if (typeof (playerView.videoAudio) === 'undefined') {
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log(playerView.videoAudio);
|
2019-04-16 19:09:29 +02:00
|
|
|
playerView.videoAudio = '';
|
|
|
|
playerView.validAudio = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
let useEmbedPlayer = false;
|
|
|
|
|
|
|
|
if (!useEmbedPlayer &&
|
|
|
|
typeof (data.captions) !== 'undefined') {
|
|
|
|
data.captions.forEach((caption) => {
|
|
|
|
let subtitleUrl = invidiousInstance + caption.url;
|
|
|
|
|
|
|
|
videoHtml = videoHtml + '<track kind="subtitles" src="' + subtitleUrl + '" srclang="' + caption.languageCode + '" label="' + caption.label + '">';
|
|
|
|
});
|
|
|
|
|
|
|
|
playerView.subtitleHtml = videoHtml;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
if (data.liveNow !== false) {
|
|
|
|
playerView.validLive = true;
|
|
|
|
playerView.videoLive = data.hlsUrl;
|
2019-05-01 21:59:42 +02:00
|
|
|
playerView.validDash = false;
|
2019-05-20 17:35:29 +02:00
|
|
|
playerView.playerSeen = true;
|
|
|
|
playerView.legacySeen = false;
|
2019-04-25 21:53:38 +02:00
|
|
|
}
|
|
|
|
|
2018-09-28 21:48:42 +02:00
|
|
|
if (playlistId != '') {
|
2019-03-31 23:31:56 +02:00
|
|
|
playerView.playlistSeen = true;
|
|
|
|
playerView.playlistShowList = true;
|
|
|
|
playerView.playlistId = playlistId;
|
|
|
|
playerView.playlistVideoList = [];
|
|
|
|
|
|
|
|
invidiousAPI('playlists', playlistId, {}, (data) => {
|
|
|
|
playerView.playlistTitle = data.title;
|
|
|
|
playerView.playlistChannelName = data.author;
|
|
|
|
playerView.playlistChannelId = data.authorId;
|
|
|
|
playerView.playlistTotal = data.videoCount;
|
|
|
|
|
|
|
|
let amountOfPages = Math.ceil(data.videoCount / 100);
|
|
|
|
|
|
|
|
for (let i = 1; i <= amountOfPages; i++) {
|
|
|
|
invidiousAPI('playlists', playlistId, {
|
|
|
|
page: i
|
|
|
|
}, (data) => {
|
|
|
|
data.videos.forEach((video) => {
|
|
|
|
let data = {};
|
|
|
|
|
|
|
|
if (video.videoId == videoId) {
|
|
|
|
playerView.playlistIndex = video.index + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
data.title = video.title;
|
|
|
|
data.videoId = video.videoId;
|
|
|
|
data.channelName = video.author;
|
|
|
|
data.index = video.index + 1;
|
|
|
|
data.thumbnail = video.videoThumbnails[4].url;
|
|
|
|
|
|
|
|
playerView.playlistVideoList[video.index] = data;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
playerView.playlistSeen = false;
|
|
|
|
playerView.playlistShowList = false;
|
|
|
|
playerView.playlistId = '';
|
2018-09-28 21:48:42 +02:00
|
|
|
}
|
|
|
|
|
2019-03-19 18:45:25 +01:00
|
|
|
invidiousFinished = true;
|
|
|
|
|
|
|
|
if (youtubedlFinished && invidiousFinished) {
|
2019-03-31 23:31:56 +02:00
|
|
|
loadingView.seen = false;
|
2019-03-19 18:45:25 +01:00
|
|
|
|
2019-03-31 23:31:56 +02:00
|
|
|
if (subscriptionView.seen === false && aboutView.seen === false && headerView.seen === false && searchView.seen === false && settingsView.seen === false && popularView.seen === false && savedView.seen === false && historyView.seen === false && channelView.seen === false && channelVideosView.seen === false) {
|
|
|
|
playerView.seen = true;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
2019-03-19 18:45:25 +01:00
|
|
|
}
|
|
|
|
|
2019-03-31 23:31:56 +02:00
|
|
|
if (rememberHistory === true) {
|
|
|
|
let historyData = {
|
|
|
|
videoId: videoId,
|
|
|
|
published: data.published,
|
|
|
|
publishedText: playerView.publishedDate,
|
|
|
|
description: data.description,
|
|
|
|
viewCount: data.viewCount,
|
|
|
|
title: playerView.videoTitle,
|
|
|
|
lengthSeconds: data.lengthSeconds,
|
|
|
|
videoThumbnails: playerView.videoThumbnail,
|
|
|
|
author: playerView.channelName,
|
|
|
|
authorId: playerView.channelId,
|
|
|
|
liveNow: false,
|
|
|
|
paid: false,
|
|
|
|
type: 'video',
|
|
|
|
timeWatched: new Date().getTime(),
|
|
|
|
};
|
|
|
|
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log(historyData);
|
2019-03-31 23:31:56 +02:00
|
|
|
addToHistory(historyData);
|
2018-09-19 20:34:23 +02:00
|
|
|
}
|
2018-09-19 17:01:21 +02:00
|
|
|
});
|
2018-03-10 22:06:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-12 04:06:30 +01:00
|
|
|
* Open up the mini player to watch the video outside of the main application.
|
|
|
|
*
|
|
|
|
* @param {string} videoThumbnail - The URL of the video thumbnail. Used to prevent another API call.
|
|
|
|
*
|
|
|
|
* @return {Void}
|
|
|
|
*/
|
2018-09-19 17:01:21 +02:00
|
|
|
function openMiniPlayer() {
|
2019-03-31 23:31:56 +02:00
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
let lastTime;
|
2019-05-23 21:56:18 +02:00
|
|
|
let videoPlayer;
|
2018-09-19 17:01:21 +02:00
|
|
|
// Grabs whatever the HTML is for the current video player. Done this way to grab
|
|
|
|
// the HTML5 player (with varying qualities) as well as the YouTube embeded player.
|
2019-04-25 21:53:38 +02:00
|
|
|
if (typeof(player) !== 'undefined') {
|
2019-05-23 21:56:18 +02:00
|
|
|
videoPlayer = player;
|
2018-09-19 17:01:21 +02:00
|
|
|
} else {
|
2019-05-23 21:56:18 +02:00
|
|
|
videoPlayer = $('.videoPlayer').get(0);
|
2018-09-19 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
2019-05-23 21:56:18 +02:00
|
|
|
videoPlayer.pause();
|
|
|
|
lastTime = videoPlayer.currentTime;
|
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
// Create a new browser window.
|
|
|
|
const BrowserWindow = electron.remote.BrowserWindow;
|
|
|
|
|
|
|
|
let miniPlayer = new BrowserWindow({
|
|
|
|
width: 1200,
|
2018-10-16 16:23:16 +02:00
|
|
|
height: 710,
|
2019-04-25 21:53:38 +02:00
|
|
|
show: false,
|
|
|
|
title: 'FreeTube Mini-Player: ' + playerView.videoTitle,
|
2018-10-16 16:23:16 +02:00
|
|
|
autoHideMenuBar: true
|
2018-09-19 17:01:21 +02:00
|
|
|
});
|
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
miniPlayer.loadURL(url.format({
|
|
|
|
pathname: path.join(__dirname, '/templates/miniPlayer.html'),
|
|
|
|
protocol: 'file:',
|
|
|
|
slashes: true,
|
|
|
|
}));
|
|
|
|
|
|
|
|
miniPlayer.once('ready-to-show', () => {
|
|
|
|
miniPlayer.show();
|
|
|
|
|
|
|
|
let playerData = {
|
2019-05-23 21:56:18 +02:00
|
|
|
videoId: playerView.videoId,
|
2019-04-25 21:53:38 +02:00
|
|
|
video360p: playerView.video360p,
|
|
|
|
valid360p: playerView.valid360p,
|
|
|
|
video720p: playerView.video720p,
|
|
|
|
valid720p: playerView.valid720p,
|
|
|
|
videoAudio: playerView.videoAudio,
|
|
|
|
validAudio: playerView.validAudio,
|
|
|
|
videoDash: playerView.videoDash,
|
|
|
|
validDash: playerView.validDash,
|
|
|
|
videoLive: playerView.videoLive,
|
|
|
|
validLive: playerView.validLive,
|
|
|
|
subtitleHtml: playerView.subtitleHtml,
|
|
|
|
videoThumbnail: playerView.videoThumbnail,
|
|
|
|
defaultPlaybackRate: player.options.defaultSpeed,
|
2019-05-23 21:56:18 +02:00
|
|
|
quality: defaultQuality,
|
2019-04-25 21:53:38 +02:00
|
|
|
volume: player.volume,
|
|
|
|
currentTime: player.currentTime,
|
2019-05-23 21:56:18 +02:00
|
|
|
playerSeen: playerView.playerSeen,
|
|
|
|
legacySeen: playerView.legacySeen,
|
|
|
|
autoplay: autoplay,
|
|
|
|
enableSubtitles: settingsView.enableSubtitles,
|
2019-04-25 21:53:38 +02:00
|
|
|
};
|
|
|
|
miniPlayer.webContents.send('ping', playerData);
|
2019-05-23 21:56:18 +02:00
|
|
|
});
|
2019-04-25 21:53:38 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
2018-09-19 17:01:21 +02:00
|
|
|
// Use the miniPlayer.html template.
|
2019-04-25 21:53:38 +02:00
|
|
|
/*$.get('templates/miniPlayer.html', (template) => {
|
2018-09-19 17:01:21 +02:00
|
|
|
mustache.parse(template);
|
|
|
|
const rendered = mustache.render(template, {
|
2019-03-26 15:48:43 +01:00
|
|
|
videoUrl: playerView.videoUrl,
|
|
|
|
videoThumbnail: playerView.videoThumbnail,
|
2018-09-19 17:01:21 +02:00
|
|
|
startTime: lastTime,
|
|
|
|
});
|
|
|
|
// Render the template to the new browser window.
|
|
|
|
miniPlayer.loadURL("data:text/html;charset=utf-8," + encodeURI(rendered));
|
2019-04-25 21:53:38 +02:00
|
|
|
});*/
|
2018-09-19 17:01:21 +02:00
|
|
|
}
|
2018-03-10 22:06:42 +01:00
|
|
|
|
2019-03-31 23:31:56 +02:00
|
|
|
/**
|
|
|
|
* Opens the video directly in pop up player
|
|
|
|
*
|
|
|
|
* @param {string} videoId - The ID of the video.
|
|
|
|
*
|
|
|
|
* @return {Void}
|
|
|
|
*/
|
|
|
|
function clickMiniPlayer(videoId) {
|
|
|
|
|
2019-04-16 19:09:29 +02:00
|
|
|
let video360p, video720p, historyData;
|
2019-03-31 23:31:56 +02:00
|
|
|
|
|
|
|
showToast("Opening in mini player, Please wait.");
|
|
|
|
|
|
|
|
let playVideo = function (videoUrl, videoThumbnail) {
|
|
|
|
// Create a new browser window.
|
|
|
|
const BrowserWindow = electron.remote.BrowserWindow;
|
2018-09-21 16:49:23 +02:00
|
|
|
|
2019-03-31 23:31:56 +02:00
|
|
|
let miniPlayer = new BrowserWindow({
|
|
|
|
width: 1200,
|
|
|
|
height: 710,
|
|
|
|
autoHideMenuBar: true
|
|
|
|
});
|
2018-09-24 20:19:43 +02:00
|
|
|
|
2019-03-31 23:31:56 +02:00
|
|
|
// Use the miniPlayer.html template.
|
|
|
|
$.get('templates/miniPlayer.html', (template) => {
|
|
|
|
mustache.parse(template);
|
|
|
|
const rendered = mustache.render(template, {
|
|
|
|
videoUrl: videoUrl,
|
|
|
|
videoThumbnail: videoThumbnail,
|
|
|
|
startTime: 0,
|
|
|
|
});
|
|
|
|
// Render the template to the new browser window.
|
|
|
|
miniPlayer.loadURL("data:text/html;charset=utf-8," + encodeURI(rendered));
|
|
|
|
|
|
|
|
if (rememberHistory) {
|
|
|
|
addToHistory(historyData);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
2018-09-24 20:19:43 +02:00
|
|
|
|
2019-03-31 23:31:56 +02:00
|
|
|
youtubedlGetInfo(videoId, (data) => {
|
|
|
|
|
|
|
|
let videoUrls = data.formats;
|
|
|
|
let videoThumbnail = data.player_response.videoDetails.thumbnail.thumbnails[data.player_response.videoDetails.thumbnail.thumbnails.length - 1].url;1553990400000
|
|
|
|
|
|
|
|
let dateString = new Date(data.published);
|
|
|
|
dateString.setDate(dateString.getDate() + 1);
|
|
|
|
let publishedDate = dateFormat(dateString, "mmm dS, yyyy");
|
|
|
|
|
|
|
|
historyData = {
|
|
|
|
videoId: videoId,
|
|
|
|
published: data.published / 1000,
|
|
|
|
publishedText: publishedDate,
|
|
|
|
description: data.description,
|
|
|
|
viewCount: data.player_response.videoDetails.viewCount,
|
|
|
|
title: data.title,
|
|
|
|
lengthSeconds: data.player_response.videoDetails.lengthSeconds,
|
|
|
|
videoThumbnails: videoThumbnail,
|
|
|
|
author: data.author.name,
|
|
|
|
authorId: data.author.id,
|
|
|
|
liveNow: false,
|
|
|
|
paid: false,
|
|
|
|
type: 'video',
|
|
|
|
timeWatched: new Date().getTime(),
|
|
|
|
};
|
|
|
|
|
2019-04-16 19:09:29 +02:00
|
|
|
// Search through the returned object to get the 360p and 720p video URLs (If available)
|
2019-03-31 23:31:56 +02:00
|
|
|
Object.keys(videoUrls).forEach((key) => {
|
|
|
|
switch (videoUrls[key]['itag']) {
|
|
|
|
case '18':
|
2019-04-16 19:09:29 +02:00
|
|
|
video360p = videoUrls[key]['url'];
|
2019-03-31 23:31:56 +02:00
|
|
|
break;
|
|
|
|
case '22':
|
|
|
|
video720p = videoUrls[key]['url'];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (defaultQuality === "720") {
|
|
|
|
validateUrl(video720p, (results) => {
|
|
|
|
if (results) {
|
|
|
|
playVideo(decodeURIComponent(video720p), videoThumbnail);
|
|
|
|
} else {
|
2019-04-16 19:09:29 +02:00
|
|
|
validateUrl(video360p, (results) => {
|
2019-03-31 23:31:56 +02:00
|
|
|
if (results) {
|
2019-04-16 19:09:29 +02:00
|
|
|
playVideo(decodeURIComponent(video360p), videoThumbnail);
|
2019-03-31 23:31:56 +02:00
|
|
|
} else {
|
|
|
|
showToast("Unable to open video into mini player.");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2019-04-16 19:09:29 +02:00
|
|
|
} else if (defaultQuality === "360") {
|
|
|
|
validateUrl(video360p, (results) => {
|
2019-03-31 23:31:56 +02:00
|
|
|
if (results) {
|
2019-04-16 19:09:29 +02:00
|
|
|
playVideo(decodeURIComponent(video360p), videoThumbnail);
|
2019-03-31 23:31:56 +02:00
|
|
|
} else {
|
|
|
|
validateUrl(video720p, (results) => {
|
|
|
|
if (results) {
|
|
|
|
playVideo(decodeURIComponent(video720p), videoThumbnail);
|
|
|
|
} else {
|
|
|
|
showToast("Unable to open video into mini player.");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2018-09-28 21:48:42 +02:00
|
|
|
}
|
2019-03-31 23:31:56 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-05-01 21:59:42 +02:00
|
|
|
function checkDashSettings() {
|
2019-04-12 21:31:56 +02:00
|
|
|
// Mediaelement.js for some reason calls onLoadStart() multiple times
|
|
|
|
// This check is here to force checkVideoSettings to only run once.
|
2019-04-11 21:42:08 +02:00
|
|
|
if (checkedSettings) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
checkedSettings = true;
|
2019-04-16 19:09:29 +02:00
|
|
|
let checked720p = false;
|
|
|
|
let checked360p = false;
|
|
|
|
let checkedAudio = false;
|
|
|
|
let checkedDash = false;
|
2019-05-01 21:59:42 +02:00
|
|
|
let parseDash = true;
|
2019-05-20 17:35:29 +02:00
|
|
|
let quality = 'Auto';
|
2019-05-21 03:27:10 +02:00
|
|
|
let thumbnailInterval = 5;
|
|
|
|
|
2019-05-22 04:20:13 +02:00
|
|
|
if (playerView.lengthSeconds < 120) {
|
|
|
|
thumbnailInterval = 1;
|
|
|
|
}
|
|
|
|
else if (playerView.lengthSeconds < 300) {
|
|
|
|
thumbnailInterval = 2;
|
|
|
|
}
|
|
|
|
else if (playerView.lengthSeconds < 900) {
|
|
|
|
thumbnailInterval = 5;
|
|
|
|
}
|
|
|
|
else {
|
2019-05-21 03:27:10 +02:00
|
|
|
thumbnailInterval = 10;
|
|
|
|
}
|
2019-04-16 19:09:29 +02:00
|
|
|
|
|
|
|
let declarePlayer = function() {
|
2019-05-01 21:59:42 +02:00
|
|
|
if (!checkedDash) {
|
2019-04-16 19:09:29 +02:00
|
|
|
return;
|
|
|
|
}
|
2019-04-11 21:42:08 +02:00
|
|
|
|
2019-04-25 21:53:38 +02:00
|
|
|
if (playerView.validLive) {
|
|
|
|
quality = 'Live';
|
|
|
|
}
|
|
|
|
|
2019-05-01 21:59:42 +02:00
|
|
|
let player = new MediaElementPlayer('player', {
|
2019-05-20 17:35:29 +02:00
|
|
|
features: ['playpause', 'current', 'progress', 'duration', 'volume', 'stop', 'speed', 'quality', 'loop', 'tracks', 'fullscreen', 'timerailthumbnails'],
|
2019-05-01 21:59:42 +02:00
|
|
|
speeds: ['2', '1.75', '1.5', '1.25', '1', '0.75', '0.5', '0.25'],
|
|
|
|
renderers: ['native_dash', 'native_hls', 'html5'],
|
|
|
|
defaultSpeed: defaultPlaybackRate,
|
|
|
|
autoGenerate: true,
|
|
|
|
autoDash: true,
|
|
|
|
autoHLS: false,
|
|
|
|
qualityText: 'Quality',
|
|
|
|
defaultQuality: quality,
|
|
|
|
stretching: 'responsive',
|
|
|
|
startVolume: currentVolume,
|
2019-05-21 03:27:10 +02:00
|
|
|
timeRailThumbnailsSeconds: thumbnailInterval,
|
2019-05-01 21:59:42 +02:00
|
|
|
|
|
|
|
success: function(mediaElement, originalNode, instance) {
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log(mediaElement,originalNode,instance);
|
2019-05-01 21:59:42 +02:00
|
|
|
|
2019-05-21 21:47:49 +02:00
|
|
|
if (autoplay) {
|
|
|
|
instance.play();
|
|
|
|
};
|
|
|
|
|
2019-05-01 21:59:42 +02:00
|
|
|
window.setTimeout(() => {
|
2019-05-21 21:47:49 +02:00
|
|
|
if (enableSubtitles) {
|
|
|
|
instance.options.startLanguage = 'en';
|
|
|
|
};
|
|
|
|
}, 2000);
|
|
|
|
|
|
|
|
let initializeSettings = function() {
|
|
|
|
let qualityOptions = $('.mejs__qualities-selector-input').get();
|
|
|
|
|
|
|
|
if (qualityOptions.length < 2) {
|
|
|
|
// Other plugin hasn't finished making the qualities. Let's try again in a moment.
|
2019-05-02 21:47:23 +02:00
|
|
|
|
2019-05-21 21:47:49 +02:00
|
|
|
window.setTimeout(initializeSettings, 500);
|
|
|
|
return;
|
2019-05-01 21:59:42 +02:00
|
|
|
}
|
|
|
|
|
2019-05-21 21:47:49 +02:00
|
|
|
if (typeof(playerView.currentTime) !== 'undefined') {
|
|
|
|
instance.currentTime = playerView.currentTime;
|
|
|
|
playerView.currentTime = undefined;
|
2019-05-01 21:59:42 +02:00
|
|
|
}
|
2019-05-20 17:35:29 +02:00
|
|
|
|
|
|
|
let selectedOption = false;
|
|
|
|
qualityOptions.reverse().forEach((option, index) => {
|
|
|
|
if (option.value === defaultQuality || option.value === defaultQuality + 'p') {
|
|
|
|
option.click();
|
|
|
|
selectedOption = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (selectedOption === false) {
|
|
|
|
// Assume user selected a higher quality as their default. Select the highest option available.
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log('Quality not available.');
|
|
|
|
ft.log(qualityOptions.reverse()[0]);
|
2019-05-20 17:35:29 +02:00
|
|
|
|
|
|
|
qualityOptions.reverse()[0].click();
|
|
|
|
}
|
2019-05-21 21:47:49 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
initializeSettings();
|
2019-05-01 21:59:42 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
error: function(error, originalNode, instance) {
|
2019-05-20 20:53:14 +02:00
|
|
|
ft.log(error);
|
|
|
|
ft.log(originalNode);
|
|
|
|
ft.log(instance);
|
2019-05-01 21:59:42 +02:00
|
|
|
showToast('There was an error with playing DASH formats. Reverting to the legacy formats.');
|
2019-05-22 21:15:05 +02:00
|
|
|
checkedSettings = false;
|
2019-05-02 21:47:23 +02:00
|
|
|
playerView.currentTime = instance.currentTime;
|
2019-05-01 21:59:42 +02:00
|
|
|
playerView.legacyFormats();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
if (playerView.validDash !== false) {
|
|
|
|
validateUrl(playerView.videoDash, (valid) => {
|
|
|
|
playerView.validDash = valid;
|
|
|
|
checkedDash = true;
|
|
|
|
declarePlayer();
|
|
|
|
});
|
|
|
|
}
|
2019-05-20 17:35:29 +02:00
|
|
|
else if (playerView.validLive !== false) {
|
|
|
|
checkedDash = true;
|
|
|
|
declarePlayer();
|
|
|
|
}
|
2019-05-01 21:59:42 +02:00
|
|
|
else {
|
|
|
|
playerView.legacyFormats();
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkLegacySettings() {
|
2019-05-02 21:47:23 +02:00
|
|
|
let player = document.getElementById('legacyPlayer');
|
2019-05-01 21:59:42 +02:00
|
|
|
|
|
|
|
let checked720p = false;
|
|
|
|
let checked360p = false;
|
|
|
|
let checkedAudio = false;
|
|
|
|
|
|
|
|
let declarePlayer = function() {
|
2019-05-02 21:47:23 +02:00
|
|
|
if (!checked720p || !checked360p || !checkedAudio) {
|
2019-05-01 21:59:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-02 21:47:23 +02:00
|
|
|
if (typeof(playerView.currentTime) !== 'undefined') {
|
|
|
|
player.currentTime = playerView.currentTime;
|
|
|
|
playerView.currentTime = undefined;
|
|
|
|
}
|
2019-04-12 21:31:56 +02:00
|
|
|
|
2019-05-02 21:47:23 +02:00
|
|
|
if (autoplay) {
|
|
|
|
player.play();
|
|
|
|
}
|
2019-05-22 21:15:05 +02:00
|
|
|
|
|
|
|
changeVideoSpeed(defaultPlaybackRate);
|
2019-05-01 21:59:42 +02:00
|
|
|
};
|
2019-04-11 21:42:08 +02:00
|
|
|
|
2019-05-01 21:59:42 +02:00
|
|
|
if (playerView.valid360p !== false) {
|
|
|
|
validateUrl(playerView.video360p, (valid) => {
|
|
|
|
playerView.valid360p = valid;
|
2019-04-16 19:09:29 +02:00
|
|
|
checked360p = true;
|
2019-04-25 21:53:38 +02:00
|
|
|
declarePlayer();
|
2019-05-01 21:59:42 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
checked360p = true;
|
|
|
|
declarePlayer();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerView.valid720p !== false) {
|
|
|
|
validateUrl(playerView.video720p, (valid) => {
|
|
|
|
playerView.valid720p = valid;
|
2019-04-16 19:09:29 +02:00
|
|
|
checked720p = true;
|
2019-04-25 21:53:38 +02:00
|
|
|
declarePlayer();
|
2019-05-01 21:59:42 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
checked720p = true;
|
|
|
|
declarePlayer();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerView.validAudio !== false) {
|
|
|
|
validateUrl(playerView.videoAudio, (valid) => {
|
|
|
|
playerView.validAudio = valid;
|
2019-04-16 19:09:29 +02:00
|
|
|
checkedAudio = true;
|
2019-04-25 21:53:38 +02:00
|
|
|
declarePlayer();
|
2019-05-01 21:59:42 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
checkedAudio = true;
|
|
|
|
declarePlayer();
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2018-09-21 16:49:23 +02:00
|
|
|
}
|
|
|
|
|
2018-09-28 21:48:42 +02:00
|
|
|
function playNextVideo() {
|
2019-05-23 21:56:18 +02:00
|
|
|
let videoPlayer
|
|
|
|
|
|
|
|
if (playerView.legacySeen) {
|
|
|
|
videoPlayer = $('.videoPlayer').get(0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
videoPlayer = $('#player').get(0);
|
|
|
|
}
|
2019-03-31 23:31:56 +02:00
|
|
|
|
2019-05-23 21:56:18 +02:00
|
|
|
if (videoPlayer.loop !== false || playerView.playlistSeen === false) {
|
2019-03-31 23:31:56 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerView.playlistShuffle === true) {
|
|
|
|
let randomVideo = Math.floor(Math.random() * playerView.playlistTotal);
|
|
|
|
|
|
|
|
loadingView.seen = true;
|
|
|
|
playVideo(playerView.playlistVideoList[randomVideo].videoId, playerView.playlistId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerView.playlistLoop === true && playerView.playlistIndex == playerView.playlistTotal) {
|
|
|
|
loadingView.seen = true;
|
|
|
|
playVideo(playerView.playlistVideoList[0].videoId, playerView.playlistId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerView.playlistIndex != playerView.playlistTotal) {
|
|
|
|
loadingView.seen = true;
|
|
|
|
playVideo(playerView.playlistVideoList[playerView.playlistIndex].videoId, playerView.playlistId);
|
|
|
|
return;
|
|
|
|
}
|
2018-03-10 22:06:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-12 04:06:30 +01:00
|
|
|
* Change the playpack speed of the video.
|
|
|
|
*
|
|
|
|
* @param {double} speed - The playback speed of the video.
|
|
|
|
*
|
|
|
|
* @return {Void}
|
|
|
|
*/
|
|
|
|
function changeVideoSpeed(speed) {
|
2019-05-01 21:59:42 +02:00
|
|
|
if (playerView.legacySeen) {
|
|
|
|
$('#currentSpeed').html(speed);
|
|
|
|
$('.videoPlayer').get(0).playbackRate = speed;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let speedOptions = $('.mejs__speed-selector-input').get();
|
|
|
|
speedOptions.forEach((option, index) => {
|
|
|
|
if (option.value == speed) {
|
|
|
|
option.click();
|
|
|
|
player.playbackRate = speed;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2018-03-10 22:06:42 +01:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:13:01 +01:00
|
|
|
/**
|
2018-03-12 04:06:30 +01:00
|
|
|
* Change the volume of the video player
|
|
|
|
*
|
|
|
|
* @param {double} amount - The volume to increase or descrease the volume by. Will be any double between 0 and 1.
|
|
|
|
*
|
|
|
|
* @return {Void}
|
|
|
|
*/
|
|
|
|
function changeVolume(amount) {
|
2019-05-01 21:59:42 +02:00
|
|
|
let videoPlayer;
|
|
|
|
|
|
|
|
if (playerView.legacySeen) {
|
|
|
|
videoPlayer = $('.videoPlayer').get(0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
videoPlayer = $('#player').get(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
let volume = videoPlayer.volume;
|
2018-07-24 03:11:56 +02:00
|
|
|
volume = volume + amount;
|
|
|
|
if (volume > 1) {
|
2019-05-01 21:59:42 +02:00
|
|
|
videoPlayer.volume = 1;
|
2018-07-24 03:11:56 +02:00
|
|
|
} else if (volume < 0) {
|
2019-05-01 21:59:42 +02:00
|
|
|
videoPlayer.volume = 0;
|
2018-07-24 03:11:56 +02:00
|
|
|
} else {
|
2019-05-01 21:59:42 +02:00
|
|
|
videoPlayer.volume = volume;
|
2018-07-24 03:11:56 +02:00
|
|
|
}
|
2018-03-10 22:06:42 +01:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:13:01 +01:00
|
|
|
/**
|
2018-03-12 04:06:30 +01:00
|
|
|
* Change the duration of the current time of a video by a few seconds.
|
|
|
|
*
|
|
|
|
* @param {integer} seconds - The amount of seconds to change the video by. Integer may be positive or negative.
|
|
|
|
*
|
|
|
|
* @return {Void}
|
|
|
|
*/
|
|
|
|
function changeDurationBySeconds(seconds) {
|
2019-05-01 21:59:42 +02:00
|
|
|
if (playerView.legacySeen) {
|
|
|
|
$('#legacyPlayer').get(0).currentTime = $('#legacyPlayer').get(0).currentTime + seconds;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
player.currentTime = player.currentTime + seconds;
|
|
|
|
}
|
2018-03-10 22:06:42 +01:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:13:01 +01:00
|
|
|
/**
|
2018-03-12 04:06:30 +01:00
|
|
|
* Change the duration of a video by a percentage of the duration.
|
|
|
|
*
|
|
|
|
* @param {double} percentage - The percentage to hop to of the video. Will be any double between 0 and 1.
|
|
|
|
*
|
|
|
|
* @return {Void}
|
|
|
|
*/
|
|
|
|
function changeDurationByPercentage(percentage) {
|
2019-05-01 21:59:42 +02:00
|
|
|
if (playerView.legacySeen) {
|
|
|
|
$('#legacyPlayer').get(0).currentTime = $('#legacyPlayer').get(0).duration * percentage;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
player.currentTime = player.duration * percentage;
|
|
|
|
}
|
2018-08-03 04:18:08 +02:00
|
|
|
}
|
2018-09-21 16:49:23 +02:00
|
|
|
|
2018-10-16 16:20:46 +02:00
|
|
|
function changeDuration(seconds) {
|
2019-05-01 21:59:42 +02:00
|
|
|
if (playerView.legacySeen) {
|
|
|
|
$('#legacyPlayer').get(0).currentTime = seconds;
|
|
|
|
}
|
|
|
|
else {
|
2019-04-12 21:31:56 +02:00
|
|
|
player.currentTime = seconds;
|
2019-05-01 21:59:42 +02:00
|
|
|
}
|
2018-10-16 16:20:46 +02:00
|
|
|
}
|
|
|
|
|
2019-03-31 23:31:56 +02:00
|
|
|
function updateVolume() {
|
2019-05-01 21:59:42 +02:00
|
|
|
if (playerView.legacySeen) {
|
|
|
|
currentVolume = $('#legacyPlayer').get(0).volume
|
|
|
|
}
|
|
|
|
else {
|
2019-03-31 23:31:56 +02:00
|
|
|
currentVolume = player.volume
|
2019-05-01 21:59:42 +02:00
|
|
|
}
|
2018-09-21 16:49:23 +02:00
|
|
|
}
|
2018-10-16 16:20:46 +02:00
|
|
|
|
|
|
|
function parseDescription(descriptionText) {
|
2019-03-31 23:31:56 +02:00
|
|
|
descriptionText = descriptionText.replace(/target\=\"\_blank\"/g, '');
|
|
|
|
descriptionText = descriptionText.replace(/\/redirect.+?(?=q\=)/g, '');
|
|
|
|
descriptionText = descriptionText.replace(/q\=/g, '');
|
|
|
|
descriptionText = descriptionText.replace(/rel\=\"nofollow\snoopener\"/g, '');
|
|
|
|
descriptionText = descriptionText.replace(/class\=.+?(?=\")./g, '');
|
|
|
|
descriptionText = descriptionText.replace(/id\=.+?(?=\")./g, '');
|
|
|
|
descriptionText = descriptionText.replace(/data\-target\-new\-window\=.+?(?=\")./g, '');
|
|
|
|
descriptionText = descriptionText.replace(/data\-url\=.+?(?=\")./g, '');
|
|
|
|
descriptionText = descriptionText.replace(/data\-sessionlink\=.+?(?=\")./g, '');
|
|
|
|
descriptionText = descriptionText.replace(/\&\;/g, '&');
|
|
|
|
descriptionText = descriptionText.replace(/\%3A/g, ':');
|
|
|
|
descriptionText = descriptionText.replace(/\%2F/g, '/');
|
|
|
|
descriptionText = descriptionText.replace(/\&v.+?(?=\")/g, '');
|
|
|
|
descriptionText = descriptionText.replace(/\&redirect\-token.+?(?=\")/g, '');
|
|
|
|
descriptionText = descriptionText.replace(/\&redir\_token.+?(?=\")/g, '');
|
|
|
|
descriptionText = descriptionText.replace(/href\=\"http(s)?\:\/\/youtube\.com/g, 'href="freetube://https://youtube.com');
|
|
|
|
descriptionText = descriptionText.replace(/href\=\"\/watch/g, 'href="freetube://https://youtube.com');
|
|
|
|
descriptionText = descriptionText.replace(/href\=\"\/results\?search\_query\=/g, 'href="freetube://');
|
|
|
|
descriptionText = descriptionText.replace(/yt\.www\.watch\.player\.seekTo/g, 'changeDuration');
|
|
|
|
|
|
|
|
return descriptionText;
|
2018-10-16 16:20:46 +02:00
|
|
|
}
|