diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js index 3adcaf6..af7cc67 100644 --- a/src/app/channel/media/queue.js +++ b/src/app/channel/media/queue.js @@ -37,6 +37,9 @@ module.exports = class{ this.syncDelta = 1000; //Create variable to hold current timestamp within the video this.timestamp = 0; + //Delay between pre-switch function call and start of media + //This should be enough time to do things like pre-fetch updated raw links from youtube + this.preSwitchDelta = 10 * 1000; //Create variable to hold sync timer this.syncTimer = null; @@ -300,16 +303,13 @@ module.exports = class{ const now = new Date().getTime(); //Calculate the amount of time in ms that the next item will start in const startsIn = nextItem.startTime - now; - //Delay between pre-switch function call and start of media - //This should be enough time to do things like pre-fetch updated raw links from youtube - const preSwitchDelta = 10 * 1000; //Calculate when the pre-switch timer would be called - const preSwitchTime = nextItem.startTime - preSwitchDelta; + const preSwitchTime = nextItem.startTime - this.preSwitchDelta; //Calculate how long the pre-switch timer will be called in const preSwitchIn = preSwitchTime - now; //If we have enough time to call the pre-switch timer - if(preSwitchIn > preSwitchDelta){ + if(preSwitchIn > this.preSwitchDelta){ //Set the pre-switch timer this.preSwitchTimer = setTimeout(()=>{this.preSwitch(nextItem)}, preSwitchIn); } @@ -551,8 +551,10 @@ module.exports = class{ */ for(let mediaObj of media){ + const now = new Date().getTime(); + //If someone is trying to schedule something that starts and ends in the past - if((mediaObj.getEndTime() < new Date().getTime()) && !force){ + if((mediaObj.getEndTime() < now) && !force){ //If an originating socket was provided for this request if(socket != null){ //Yell at the user for being an asshole @@ -562,9 +564,9 @@ module.exports = class{ } //If the item has already started - if((mediaObj.startTime < new Date().getTime()) && !force){ + if((mediaObj.startTime < now) && !force){ //Set time stamp to existing timestamp plus the difference between the orginal start-date and now - const calculatedTimeStamp = mediaObj.startTimeStamp + ((new Date().getTime() - mediaObj.startTime) / 1000) + const calculatedTimeStamp = mediaObj.startTimeStamp + ((now - mediaObj.startTime) / 1000) //If the calculated time stamp is more than negligible, and therefore not simply caused by serverside processing time if(calculatedTimeStamp > 5){ @@ -572,7 +574,7 @@ module.exports = class{ mediaObj.startTimeStamp = calculatedTimeStamp; //Start the item now - mediaObj.startTime = new Date().getTime(); + mediaObj.startTime = now; } } @@ -587,6 +589,12 @@ module.exports = class{ return false; } + //If we start in less than 10 seconds + if((mediaObj.startTime - this.preSwitchDelta) < now){ + //Asyncrhounosly Check if we need to refresh the raw link + this.handleRawRefresh(mediaObj); + } + //Create an empty temp array to sparsley populate with our schedule const tempSchedule = []; //Create new map to replace our current schedule map @@ -674,6 +682,10 @@ module.exports = class{ } async preSwitch(mediaObj){ + this.handleRawRefresh(mediaObj); + } + + async handleRawRefresh(mediaObj){ //Check if media needs a new raw link and update if it does if(await yanker.refreshRawLink(mediaObj)){ //If the fetch took so god damned long we've already started the video (isn't 10 seconds enough?) @@ -681,6 +693,9 @@ module.exports = class{ //Tell the clients to update the raw file for the current item fore.st-style, as it probably got sent out with a stale link this.server.io.in(this.channel.name).emit("updateCurrentRawFile", {file: mediaObj.rawLink}); } + + //Return media obj to tell of success + return mediaObj; } } @@ -989,10 +1004,9 @@ module.exports = class{ throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while rehydrating queue!`, "queue"); } + //Get current time const now = new Date().getTime(); - //Next: Update this function to handle ended items - //If something was playing if(chanDB.media.nowPlaying != null){ //Rehydrate the currently playing item int oa queued media object diff --git a/src/utils/media/internetArchiveUtils.js b/src/utils/media/internetArchiveUtils.js index 8467935..71e2a7a 100644 --- a/src/utils/media/internetArchiveUtils.js +++ b/src/utils/media/internetArchiveUtils.js @@ -15,7 +15,6 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //Node Imports -const url = require("node:url"); const validator = require('validator'); //Local Imports diff --git a/src/utils/media/yanker.js b/src/utils/media/yanker.js index 2c3c166..d0913e3 100644 --- a/src/utils/media/yanker.js +++ b/src/utils/media/yanker.js @@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //NPM Imports +const url = require("node:url"); const validator = require('validator');//No express here, so regular validator it is! //local import @@ -41,6 +42,16 @@ module.exports.yankMedia = async function(url, title){ module.exports.refreshRawLink = async function(mediaObj){ switch(mediaObj.type){ case 'yt': + //Scrape expiration from query strings + //const expires = mediaObj.rawLink.match(/expire=([0-9]+)/); //Keeping this regex version I wrote at first in-case we need the speed + const expires = new URL(mediaObj.rawLink).searchParams.get("expire"); + + //If we have a valid raw file link that will be good by the end of the video + if(expires != null && (expires * 1000) > mediaObj.getEndTime()){ + //Return null to tell the calling function there is no refresh required for this video at this time + return null; + } + //Re-fetch media metadata metadata = await ytdlpUtil.fetchYoutubeVideoMetadata(mediaObj.id); //Refresh media rawlink from metadata