Implemented official yt iframe embed player support.

This commit is contained in:
rainbow napkin 2025-05-10 12:23:33 -04:00
parent 1b0caa5e02
commit 473b54356e
3 changed files with 181 additions and 21 deletions

View file

@ -39,7 +39,7 @@ class channel{
//Set defaults for any unset settings and run any required process steps for the current config
this.setDefaults(false, true);
//Freak out any weirdos who take a peek in the dev console for gaffs
//Freak out any weirdos who take a peek in the dev console for shits n gigs
console.log("👁️👄👁️ 𝓊𝓃𝒿𝓊𝓇.");
}
@ -152,6 +152,22 @@ class channel{
}
}
//If the player or mediaHandler isn't loaded
if(this.player == null || this.player.mediaHandler == null){
//We're fuggin done here
return;
}
//Get current video
const nowPlaying = this.player.mediaHandler.nowPlaying;
//If we're playing a youtube video
if(nowPlaying != null && nowPlaying.type == 'yt'){
//Restart the video
this.player.start({media: nowPlaying});
}
//Stop while we're ahead
return;
}

View file

@ -64,9 +64,15 @@ class mediaHandler{
}
start(){
this.setVideoTitle(this.nowPlaying.title);
}
sync(timestamp = this.lastTimestamp){
//Skip sync calls that won't seek so we don't pointlessly throw selfAct
if(timestamp != this.video.currentTime){
//Set self act flag
this.selfAct = true;
}
}
reload(){
@ -165,14 +171,6 @@ class rawFileBase extends mediaHandler{
super.destroyPlayer();
}
sync(timestamp = this.lastTimestamp){
//Skip sync calls that won't seek so we don't pointlessly throw selfAct
if(timestamp != this.video.currentTime){
//Set self act flag
this.selfAct = true;
}
}
reload(){
//Call derived method
super.reload();
@ -270,9 +268,6 @@ class rawFileHandler extends rawFileBase{
//Set video volume
this.video.volume = this.player.volume;
//Set video title
this.setVideoTitle(this.nowPlaying.title);
//Unlock player
this.setPlayerLock(false);
@ -309,6 +304,21 @@ class youtubeEmbedHandler extends mediaHandler{
constructor(client, player, media){
//Call derived constructor
super(client, player, media, 'ytEmbed');
//Set flag to notify functions when the player is actually ready
this.ready = false;
//Create property to hold video iframe for easy access
this.iframe = null;
}
//custom start media function since we want the youtube player to call the start function once it's ready
startMedia(media){
//If we properly ingested the media
if(this.ingestMedia(media)){
//Build the video player
this.buildPlayer();
}
}
buildPlayer(){
@ -318,10 +328,6 @@ class youtubeEmbedHandler extends mediaHandler{
return console.warn("youtubeEmbedHandler.buildPlayer() Called before YT Iframe API Loaded, waiting on refresh to rebuild...");
}
//Clear out the player title so that youtube's baked in title can do it's thing.
//This will be replaced once we complete the full player control and remove the defualt youtube UI
this.player.title.textContent = "";
//Create temp div for yt api to replace
const tempDiv = document.createElement('div');
//Name the div
@ -333,9 +339,9 @@ class youtubeEmbedHandler extends mediaHandler{
this.video = new YT.Player('youtube-embed-player', {
//Inject video id
videoId: this.nowPlaying.id,
//Set up event listeners (NGL kinda nice of google to do it this way...)
events: {
'onReady': this.initializePlayer.bind(this)
'onReady': this.start.bind(this),
'onStateChange': this.onStateChange.bind(this)
}
});
@ -343,8 +349,140 @@ class youtubeEmbedHandler extends mediaHandler{
super.buildPlayer();
}
initializePlayer(){
start(){
//Call derived start function
super.start();
//Set volume based on player volume
this.video.setVolume(this.player.volume * 100);
//Kick the video off
this.video.playVideo();
//Pull iframe
this.iframe = this.video.getIframe()
//Throw the ready flag
this.ready = true;
}
destroyPlayer(){
//If we've had enough time to create a player frame
if(this.ready){
//Pull volume from player before destroying since google didn't give us a volume change event like a bunch of dicks
this.player.volume = (this.video.getVolume() / 100);
//Use the embed api's built in destroy function
this.video.destroy();
}
//If we have any leftovers
if(this.iframe != null){
//Nukem like last nights chicken
iframe.remove();
}
//Call derived destroy function
super.destroyPlayer();
}
sync(timestamp = this.lastTimestamp){
//If we're not ready
if(!this.ready){
//Kick off a timer to wait it out and try again l8r
setTimeout(this.sync.bind(this), 100);
//If it failed, tell randy to fuck off
return;
}
//Seek to timestamp, allow buffering
this.video.seekTo(timestamp, true);
}
reload(){
//if we're ready
if(this.ready){
//re-load the video by id
this.video.loadVideoById(this.nowPlaying.id);
}
}
play(){
//If we're ready
if(this.ready){
//play the video
this.video.playVideo();
}
}
pause(){
//If we're ready
if(this.ready){
//pause the video
this.video.pauseVideo();
}
}
getRatio(){
//TODO: Implement a type-specific metadata property object in the media class to hold type-sepecifc meta-data
//Alternatively we could fill in resolution information from the raw link
//However keeping embedded functionality dependant on raw-links seems like bad practice
}
getTimestamp(){
//If we're ready
if(this.ready){
//Return the timestamp
return this.video.getCurrentTime();
}
//If we fall through, simply report that the video hasn't gone anywhere yet
return 0;
}
setVideoTitle(){
//Clear out the player title so that youtube's baked in title can do it's thing.
//This will be replaced once we complete the full player control and remove the defualt youtube UI
this.player.title.textContent = "";
}
//Generic handler for state changes since google is a dick
onStateChange(event){
switch(event.data){
//video unstarted
case -1:
return;
//video ended
case 0:
return;
//video playing
case 1:
return;
//video paused
case 2:
super.onPause(event);
return;
//video buffering
case 3:
//There is no good way to tell slow connections apart from user seeking
//This will be easier to implement once we get custom player controls up
//super.onSeek(event);
return;
//video queued
case 5:
return;
//bad status code
default:
return;
}
}
setPlayerLock(lock){
super.setPlayerLock(lock);
if(this.ready){
this.iframe.style.pointerEvents = (lock ? "none" : "");
}
}
}

View file

@ -149,6 +149,12 @@ class player{
}
updateCurrentRawFile(data){
//typecheck the media handler to see if we really need to do any of this shit, if not...
if(this.mediaHandler.type == 'ytEmbed'){
//Ignore it
return;
}
//Grab current item from media handler
const currentItem = this.mediaHandler.nowPlaying;