mirror of
https://github.com/iv-org/invidious.git
synced 2024-12-23 05:53:37 +00:00
support playlist function
This commit is contained in:
parent
74bf3bc8b2
commit
ffb7b7446e
@ -111,6 +111,9 @@ function control_embed_iframe(message) {
|
|||||||
case 'seek':
|
case 'seek':
|
||||||
const duration = player.duration();
|
const duration = player.duration();
|
||||||
let newTime = helpers.clamp(message.data.value, 0, duration);
|
let newTime = helpers.clamp(message.data.value, 0, duration);
|
||||||
|
if (player.paused() && player.currentTime() === 0) {
|
||||||
|
player.play();
|
||||||
|
}
|
||||||
player.currentTime(newTime);
|
player.currentTime(newTime);
|
||||||
break;
|
break;
|
||||||
case 'setplaybackrate':
|
case 'setplaybackrate':
|
||||||
|
@ -6,6 +6,7 @@ class invidious_embed {
|
|||||||
static invidious_instance = '';
|
static invidious_instance = '';
|
||||||
static api_instance_list = [];
|
static api_instance_list = [];
|
||||||
static instance_status_list = {};
|
static instance_status_list = {};
|
||||||
|
static videodata_cahce = {};
|
||||||
|
|
||||||
addEventListener(eventname, func) {
|
addEventListener(eventname, func) {
|
||||||
if (eventname in invidious_embed.eventname_table) {
|
if (eventname in invidious_embed.eventname_table) {
|
||||||
@ -79,9 +80,21 @@ class invidious_embed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async videodata_api(videoid) {
|
||||||
|
const not_in_videodata_cahce = !(videoid in invidious_embed.videodata_cahce);
|
||||||
|
if (not_in_videodata_cahce) {
|
||||||
|
const video_api_response = await fetch(invidious_embed.invidious_instance + "/api/v1/videos/" + videoid + "?fields=title,videoId,paid,premium,isFamilyFriendly,isListed,liveNow");
|
||||||
|
if (video_api_response.ok) {
|
||||||
|
invidious_embed.videodata_cahce[videoid] = Object.assign({},{status:true},await video_api_response.json());
|
||||||
|
} else {
|
||||||
|
invidious_embed.videodata_cahce[videoid] = {status:false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return invidious_embed.videodata_cahce[videoid];
|
||||||
|
}
|
||||||
|
|
||||||
async videoid_accessable_check(videoid) {
|
async videoid_accessable_check(videoid) {
|
||||||
const video_api_response = await fetch(invidious_embed.invidious_instance + "/api/v1/videos/" + videoid);
|
return (await this.videodata_api(videoid)).status;
|
||||||
return video_api_response.ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPlaylistVideoids(playlistid) {
|
async getPlaylistVideoids(playlistid) {
|
||||||
@ -101,6 +114,8 @@ class invidious_embed {
|
|||||||
this.player_status = -1;
|
this.player_status = -1;
|
||||||
this.error_code = 0;
|
this.error_code = 0;
|
||||||
this.volume = 100;
|
this.volume = 100;
|
||||||
|
this.loop = false;
|
||||||
|
this.playlistVideoIds = [];
|
||||||
this.eventobject = { ready: [], ended: [], error: [], ratechange: [], volumechange: [], waiting: [], timeupdate: [], loadedmetadata: [], play: [], seeking: [], seeked: [], playerresize: [], pause: [], statechange: [] };
|
this.eventobject = { ready: [], ended: [], error: [], ratechange: [], volumechange: [], waiting: [], timeupdate: [], loadedmetadata: [], play: [], seeking: [], seeked: [], playerresize: [], pause: [], statechange: [] };
|
||||||
let replace_elemnt;
|
let replace_elemnt;
|
||||||
if (element === undefined || element === null) {
|
if (element === undefined || element === null) {
|
||||||
@ -142,6 +157,7 @@ class invidious_embed {
|
|||||||
invidious_embed.widgetid++;
|
invidious_embed.widgetid++;
|
||||||
search_params.append('origin', location.origin);
|
search_params.append('origin', location.origin);
|
||||||
search_params.append('enablejsapi', '1');
|
search_params.append('enablejsapi', '1');
|
||||||
|
let no_start_parameter = true;
|
||||||
if (typeof options.playerVars === 'object') {
|
if (typeof options.playerVars === 'object') {
|
||||||
this.option_playerVars = options.playerVars;
|
this.option_playerVars = options.playerVars;
|
||||||
for (let x in options.playerVars) {
|
for (let x in options.playerVars) {
|
||||||
@ -149,9 +165,17 @@ class invidious_embed {
|
|||||||
search_params.append(x, options.playerVars[x]);
|
search_params.append(x, options.playerVars[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (options.playerVars.start !== undefined) {
|
||||||
|
no_start_parameter = false;
|
||||||
|
}
|
||||||
if (options.playerVars.autoplay === undefined) {
|
if (options.playerVars.autoplay === undefined) {
|
||||||
search_params.append('autoplay', '0');
|
search_params.append('autoplay', '0');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
search_params.append('autoplay', '0');
|
||||||
|
}
|
||||||
|
if (no_start_parameter) {
|
||||||
|
search_params.append('start', '0');
|
||||||
}
|
}
|
||||||
iframe_src += "?" + search_params.toString();
|
iframe_src += "?" + search_params.toString();
|
||||||
if (typeof options.events === 'object') {
|
if (typeof options.events === 'object') {
|
||||||
@ -163,7 +187,6 @@ class invidious_embed {
|
|||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.addEventListener('loadedmetadata', () => { this.event_executor('ready'); this.loaded = true; });
|
this.addEventListener('loadedmetadata', () => { this.event_executor('ready'); this.loaded = true; });
|
||||||
this.addEventListener('loadedmetadata', () => { this.setVolume(this.volume); });
|
this.addEventListener('loadedmetadata', () => { this.setVolume(this.volume); });
|
||||||
this.addEventListener('loadedmetadata', async () => { const plid = await this.promise_send_event('getplaylistid'); (plid === null || plid === undefined) ? this.playlistVideoIds = [] : this.playlistVideoIds = await this.getPlaylistVideoids(plid); })
|
|
||||||
this.player_iframe.src = iframe_src;
|
this.player_iframe.src = iframe_src;
|
||||||
if (typeof options.width === 'number') {
|
if (typeof options.width === 'number') {
|
||||||
this.player_iframe.width = options.width;
|
this.player_iframe.width = options.width;
|
||||||
@ -192,7 +215,13 @@ class invidious_embed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
event_executor(eventname) {
|
event_executor(eventname) {
|
||||||
this.eventElement.dispatchEvent(new Event(eventname));
|
let event_parameter = {detail:undefined};
|
||||||
|
if (eventname === 'statechange') {
|
||||||
|
event_parameter.detail = this.getPlayerState();
|
||||||
|
} else if (eventname === 'error'){
|
||||||
|
event_parameter.detail = this.error_code;
|
||||||
|
}
|
||||||
|
this.eventElement.dispatchEvent(new Event(eventname,event_parameter));
|
||||||
}
|
}
|
||||||
|
|
||||||
receiveMessage(message) {
|
receiveMessage(message) {
|
||||||
@ -299,7 +328,7 @@ class invidious_embed {
|
|||||||
return this.promise_send_event('getmutestatus');
|
return this.promise_send_event('getmutestatus');
|
||||||
}
|
}
|
||||||
|
|
||||||
seekTo(seconds, allowSeekAhead) {//seconds must be a number and allowSeekAhead is ignore
|
async seekTo(seconds, allowSeekAhead) {//seconds must be a number and allowSeekAhead is ignore
|
||||||
if (typeof seconds === 'number') {
|
if (typeof seconds === 'number') {
|
||||||
if (seconds !== NaN && seconds !== undefined) {
|
if (seconds !== NaN && seconds !== undefined) {
|
||||||
this.postMessage({ eventname: 'seek', value: seconds });
|
this.postMessage({ eventname: 'seek', value: seconds });
|
||||||
@ -338,7 +367,7 @@ class invidious_embed {
|
|||||||
return this.promise_send_event('getavailableplaybackrates');
|
return this.promise_send_event('getavailableplaybackrates');
|
||||||
}
|
}
|
||||||
|
|
||||||
async playOtherVideoById(option, autoplay, startSeconds_arg) {//internal fuction
|
async playOtherVideoById(option, autoplay, startSeconds_arg, additional_argument) {//internal fuction
|
||||||
let videoId = '';
|
let videoId = '';
|
||||||
let startSeconds = 0;
|
let startSeconds = 0;
|
||||||
let endSeconds = -1;
|
let endSeconds = -1;
|
||||||
@ -401,15 +430,22 @@ class invidious_embed {
|
|||||||
invidious_embed.widgetid++;
|
invidious_embed.widgetid++;
|
||||||
search_params.append('autoplay', Number(autoplay));
|
search_params.append('autoplay', Number(autoplay));
|
||||||
if (this.option_playerVars !== undefined) {
|
if (this.option_playerVars !== undefined) {
|
||||||
|
const ignore_keys = ['autoplay', 'start', 'end', 'index', 'list'];
|
||||||
Object.keys(this.option_playerVars).forEach(key => {
|
Object.keys(this.option_playerVars).forEach(key => {
|
||||||
if (key !== 'autoplay' && key !== 'start' && key !== 'end') {
|
if (!ignore_keys.includes(key)) {
|
||||||
search_params.append(key, this.option_playerVars[key]);
|
search_params.append(key, this.option_playerVars[key]);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (startSeconds > 0) {
|
if (typeof additional_argument === 'object') {
|
||||||
search_params.append('start', startSeconds);
|
const ignore_keys = ['autoplay', 'start', 'end'];
|
||||||
|
Object.keys(additional_argument).forEach(key => {
|
||||||
|
if (!ignore_keys.includes(key)) {
|
||||||
|
search_params.append(key, additional_argument[key]);
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
search_params.append('start', startSeconds);
|
||||||
if (endSeconds !== -1 && endSeconds >= 0) {
|
if (endSeconds !== -1 && endSeconds >= 0) {
|
||||||
if (endSeconds > startSeconds) {
|
if (endSeconds > startSeconds) {
|
||||||
search_params.append('end', endSeconds);
|
search_params.append('end', endSeconds);
|
||||||
@ -426,19 +462,134 @@ class invidious_embed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadVideoById(option, startSeconds) {
|
loadVideoById(option, startSeconds) {
|
||||||
this.playOtherVideoById(option, true, startSeconds);
|
this.playOtherVideoById(option, true, startSeconds, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
cueVideoById(option, startSeconds) {
|
cueVideoById(option, startSeconds) {
|
||||||
this.playOtherVideoById(option, false, startSeconds);
|
this.playOtherVideoById(option, false, startSeconds, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
cueVideoByUrl(option, startSeconds) {
|
cueVideoByUrl(option, startSeconds) {
|
||||||
this.playOtherVideoById(option, false, startSeconds);
|
this.playOtherVideoById(option, false, startSeconds, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadVideoByUrl(option, startSeconds) {
|
loadVideoByUrl(option, startSeconds) {
|
||||||
this.playOtherVideoById(option, true, startSeconds);
|
this.playOtherVideoById(option, true, startSeconds, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async playPlaylist(playlistData,autoplay,index,startSeconds) {
|
||||||
|
let playlistId;
|
||||||
|
if (typeof playlistData === 'string') {
|
||||||
|
this.playlistVideoIds = await this.getPlaylistVideoids(playlistData);
|
||||||
|
playlistId = playlistData;
|
||||||
|
} else if (typeof playlistData === 'object') {
|
||||||
|
if (Array.isArray(playlistData)) {
|
||||||
|
this.playlistVideoIds = playlistData;
|
||||||
|
} else {
|
||||||
|
index = playlistData['index'];
|
||||||
|
let listType = 'playlist';
|
||||||
|
if (typeof playlistData['listType'] === 'string'){
|
||||||
|
listType = playlistData['listType'];
|
||||||
|
}
|
||||||
|
switch (listType) {
|
||||||
|
case 'playlist':
|
||||||
|
if (Array.isArray(playlistData['list'])) {
|
||||||
|
this.playlistVideoIds = playlistData['list'];
|
||||||
|
} else if(typeof playlistData['list'] === 'string') {
|
||||||
|
this.playlistVideoIds = await this.getPlaylistVideoids(playlistData['list']);
|
||||||
|
playlistId = playlistData['list'];
|
||||||
|
} else {
|
||||||
|
console.error('playlist data list must be string or array of strings');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'user_uploads':
|
||||||
|
console.warn('sorry user_uploads not support');
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
console.error('listType : ' + listType + ' is unknown');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('playlist function first argument must be string or array of string');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.playlistVideoIds.length === 0){
|
||||||
|
console.error('playlist length 0 is invalid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let parameter = {index:0};
|
||||||
|
if (typeof index === 'undefined') {
|
||||||
|
index = 0;
|
||||||
|
} else if (typeof index === 'number'){
|
||||||
|
parameter.index = index;
|
||||||
|
} else{
|
||||||
|
console.error('index must be number of undefined');
|
||||||
|
}
|
||||||
|
if (typeof playlistId === 'string') {
|
||||||
|
parameter['list'] = playlistId;
|
||||||
|
this.playlistId = playlistId;
|
||||||
|
}
|
||||||
|
this.playOtherVideoById(this.playlistVideoIds[index],autoplay,startSeconds,parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
cuePlaylist(data,index,startSeconds) {
|
||||||
|
this.playPlaylist(data,false,index,startSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPlaylist(data,index,startSeconds) {
|
||||||
|
this.playPlaylist(data,true,index,startSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
playVideoAt(index) {
|
||||||
|
if (typeof index === 'number') {
|
||||||
|
let parameter = {index:index};
|
||||||
|
if (this.playlistId !== undefined) {
|
||||||
|
parameter['list'] = this.playlistId;
|
||||||
|
}
|
||||||
|
this.playOtherVideoById(this.playlistVideoIds[index],true,0,parameter);
|
||||||
|
} else {
|
||||||
|
console.error('playVideoAt first argument must be number');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async nextVideo() {
|
||||||
|
let now_index = this.promise_send_event('getplaylistindex');
|
||||||
|
if (now_index === this.playlistVideoIds.length -1) {
|
||||||
|
if (this.loop) {
|
||||||
|
now_index = 0;
|
||||||
|
} else {
|
||||||
|
console.log('end of playlist');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
now_index++;
|
||||||
|
}
|
||||||
|
let parameter = {index:now_index};
|
||||||
|
if (this.playlistId !== undefined) {
|
||||||
|
parameter['list'] = this.playlistId;
|
||||||
|
}
|
||||||
|
this.playOtherVideoById(this.playlistVideoIds[now_index],true,0,parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
async previousVideo() {
|
||||||
|
let now_index = this.promise_send_event('getplaylistindex');
|
||||||
|
if (now_index === 0) {
|
||||||
|
if (this.loop) {
|
||||||
|
now_index = this.playlistVideoIds.length -1;
|
||||||
|
} else {
|
||||||
|
console.log('back to start of playlist');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
now_index--;
|
||||||
|
}
|
||||||
|
let parameter = {index:now_index};
|
||||||
|
if (this.playlistId !== undefined) {
|
||||||
|
parameter['list'] = this.playlistId;
|
||||||
|
}
|
||||||
|
this.playOtherVideoById(this.playlistVideoIds[now_index],true,0,parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDuration() {
|
getDuration() {
|
||||||
@ -459,7 +610,8 @@ class invidious_embed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getVideoData() {
|
async getVideoData() {
|
||||||
return { video_id: this.videoId, title: await this.promise_send_event('gettitle'), list: this.promise_send_event('getplaylistid') };
|
const videoData = await this.videodata_api(this.videoId);
|
||||||
|
return { video_id: this.videoId, title: await this.promise_send_event('gettitle'), list: await this.promise_send_event('getplaylistid'), isListed:videoData.isListed, isLive:videoData.liveNow, isPremiere:videoData.premium};
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlaylistIndex() {
|
getPlaylistIndex() {
|
||||||
@ -470,12 +622,21 @@ class invidious_embed {
|
|||||||
return this.playlistVideoIds !== undefined ? this.playlistVideoIds : [];
|
return this.playlistVideoIds !== undefined ? this.playlistVideoIds : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLoop(loopStatus) {
|
||||||
|
if (typeof loopStatus === 'boolean') {
|
||||||
|
this.loop = loopStatus;
|
||||||
|
} else {
|
||||||
|
console.error('setLoop first argument must be bool');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor(element, options) {
|
constructor(element, options) {
|
||||||
this.Player(element, options);
|
this.Player(element, options);
|
||||||
window.addEventListener('message', (ms) => { this.receiveMessage(ms) });
|
window.addEventListener('message', (ms) => { this.receiveMessage(ms) });
|
||||||
this.message_wait = { getvolume: [], getmutestatus: [], getduration: [], getcurrenttime: [], getplaybackrate: [], getavailableplaybackrates: [], gettitle: [] };
|
this.message_wait = { getvolume: [], getmutestatus: [], getduration: [], getcurrenttime: [], getplaybackrate: [], getavailableplaybackrates: [], gettitle: [] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invidious_ready(func) {
|
function invidious_ready(func) {
|
||||||
if (typeof func === 'function') {
|
if (typeof func === 'function') {
|
||||||
func();
|
func();
|
||||||
@ -484,6 +645,7 @@ function invidious_ready(func) {
|
|||||||
console.warn('invidious.ready first argument must be function');
|
console.warn('invidious.ready first argument must be function');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invidious_embed.invidious_instance = new URL(document.currentScript.src).origin;
|
invidious_embed.invidious_instance = new URL(document.currentScript.src).origin;
|
||||||
const invidious = { Player: invidious_embed, PlayerState: { ENDED: 0, PLAYING: 1, PAUSED: 2, BUFFERING: 3, CUED: 5 }, ready: invidious_ready };
|
const invidious = { Player: invidious_embed, PlayerState: { ENDED: 0, PLAYING: 1, PAUSED: 2, BUFFERING: 3, CUED: 5 }, ready: invidious_ready };
|
||||||
if (typeof onInvidiousIframeAPIReady === 'function') {
|
if (typeof onInvidiousIframeAPIReady === 'function') {
|
||||||
@ -493,5 +655,3 @@ if (typeof onInvidiousIframeAPIReady === 'function') {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const YT = invidious;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user