As promised, here is the new fixed version of my bookmarklet:
Netflix Autoplay Bookmarklet
Please note I can no longer tell when the episode is almost over, so I am now just timing the entire length of play. You will now see a countdown telling you when it will change to the next episode. This means a few things:
* If you pause the show, or it takes a long time to buffer, or is has to buffer in the middle, the timer will be off and it will switch early. There are some things you can do about this, first, you will see ‘||’ next to the timer, clicking it will pause the countdown, clicking again will unpause it, so if you walk away, be sure to click this. Also, you can click the countdown and type a new time into it, you can either give a number of seconds, or enter time in the mm:ss format.
Also, next to the pause button you will see a ‘-‘ most of you can ignore this, but if you have a lot of problems with buffering taking a really long time or something, you can also click the ‘-‘ and enter a number of seconds there. This will be added to what the bookmarklet thinks is the length of each episode to allow for buffering and such. By default 10 seconds is added to allow the episodes to load properly.
I have not done extensive testing on this, so there could very will be some bugs. If you find any, let me know.
(function(undefined){
//Takes our countdown timer and converts it to mm:ss and displays to user
function updateTime() {
var seconds = (countdownTimer % 60) + '';
if(seconds.length === 0)
seconds = '00';
else if(seconds.length === 1)
seconds = '0' + seconds;
timerNode.innerHTML = Math.floor(countdownTimer / 60) + ':' + seconds;
}
//Grabs the data for the episode matching the ID passed in
function getCurrentEpisodeData(episodeId) {
var episode, i = 0, j = 0;
if(episodeData && episodeData.video && episodeData.video.seasons) {
for(i=0; i<episodeData.video.seasons.length; i++) { for(j=0; j<episodeData.video.seasons[i].episodes.length; j++) { if(episodeData.video.seasons[i].episodes[j].id === episodeId) { episode = episodeData.video.seasons[i].episodes[j]; break; } } if(episode) break; } } return episode; } //Grabs the data for the episode following the one with the ID passed in function getNextEpisodeData(episodeId) { var episode, i = 0, j = 0, found = false; if(episodeData && episodeData.video && episodeData.video.seasons) { for(i=0; i<episodeData.video.seasons.length; i++) { for(j=0; j<episodeData.video.seasons[i].episodes.length; j++) { if(episodeData.video.seasons[i].episodes[j].id === episodeId) { found = true; } else if(found) { episode = episodeData.video.seasons[i].episodes[j]; break; } } if(episode) break; } } return episode; } //base64 decoder function decode64(input) { var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', output = '', chr1, chr2, chr3 = '', enc1, enc2, enc3, enc4 = '', i = 0, base64test = /[^A-Za-z0-9\+\/\=]/g; input = input.replace(base64test, ''); do { enc1 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++)); enc4 = keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); } if (enc4 != 64) { output = output + String.fromCharCode(chr3); } chr1 = chr2 = chr3 = ''; enc1 = enc2 = enc3 = enc4 = ''; } while (i<input.length); return unescape(output); } if(window.NetflixAutoplayLoaded) { alert('Autoplay already loaded.'); //return false; } else { window.NetflixAutoplayLoaded = true; } //resize the player so we can see the text we are about to insert under it document.getElementById('SLPlayer').style.height = (window.innerHeight - 35) + 'px'; document.getElementById('SLPlayerWrapper').style.height = (window.innerHeight - 35) + 'px'; document.getElementById('page-content').style.height = (window.innerHeight - 35) + 'px'; //create the text and other shizzy we want var autoplayElement = document.body.appendChild(document.createElement('div')); autoplayElement.id = 'NetflixAutoplayContainer'; autoplayElement.innerHTML = '
Time left until switch: 00:00 || -
';
var timerNode = document.getElementById('NetflixAutoplayTimer');
var autoplayText = document.getElementById('NetflixAutoplay');
var pauseButton = document.getElementById('NetflixAutoPauser');
var delay = document.getElementById('NetflixAutoDelay');
//the number of seconds to wait for the show to buffer on load
var timerDelay = 10;
//Pull the current episode information and the full series data for us
var episodeData = JSON.parse(decode64(netflix.Silverlight.MoviePlayer.getPlugin().settings.metadata));
var currentEppId = (/,EpisodeMovieId=\d*/.exec(netflix.Silverlight.MoviePlayer.getPlugin().settings.initParams)[0]).split('=')[1];
//gets data for current & next epps
var currentEpp = getCurrentEpisodeData(currentEppId);
var nextEpp = getNextEpisodeData(currentEpp.id);
var paused = false; //bool to see if paused
var done = false; //bool to see if finished autoplay
var editingTime = false; //bool to check if user is editing time
//Javascript to execute to change episode
var ini = document.getElementsByTagName('script');
ini = ini[ini.length-1].innerHTML;
//Set the countdown till next episode + the pause we need for buffer
function updateCountdown() {
countdownTimer = parseInt(currentEpp.runtime, 10) + timerDelay;
}
var countdownTimer = 0; //episode length timer
updateCountdown(); //Sets the count down timer for current episode
//Prompt user for number of episodes
var numToWatch = 3;
function getNumberOfEpisodesToWatch() {
var newNum;
do {
newNum = prompt('How many episodes would you like to play?', numToWatch);
} while (isNaN(newNum));
numToWatch = parseInt(newNum, 10);
//set the text
if(numToWatch > 0) {
autoplayText.innerHTML = 'Netflix autoplay on, Episodes left: ' + numToWatch;
if(done) { //if we have already finished, restart
done = false;
switchEpps();
}
} else {
autoplayText.innerHTML = 'Netflix autoplay off';
}
}
//ask the user for the number of episodes they want
getNumberOfEpisodesToWatch();
//handler for pause button
function pause() {
if(pauseButton.innerHTML === '||') {
paused = true;
pauseButton.innerHTML = '>';
} else {
paused = false;
pauseButton.innerHTML = '||';
}
}
//handles editing the buffer delay
function delayEdit(e) {
if((!e.keyCode || e.keyCode === 13) && !isNaN(delay.innerHTML)) {
timerDelay = parseInt(delay.innerHTML, 10);
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return false;
}
}
//handler for editing time left to play
function editTime(e) {
timerNode.contentEditable=true;
editingTime = true;
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return false;
}
//handles updating time left to play after user edit
function endEdit(e) {
if(timerNode.contentEditable.toString() === 'true' && (e.type === 'blur' || e.keyCode === 13)) {
timerNode.contentEditable = false;
editingTime = false;
var time = timerNode.innerHTML;
if(time.indexOf(':') >0) { //converts minutes:seconds into time
time = time.split(':');
countdownTimer = parseInt(time[0], 10)*60 + parseInt(time[1], 10);
} else { //converts just seconds into time
if(!isNaN(time)) {
countdownTimer = parseInt(time, 10);
}
}
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return false;
}
}
//Does everything to change to the next episode
function switchEpps() {
//setup the script for the next epp
ini = ini.replace(/,EpisodeMovieId=\d*/,',EpisodeMovieId=' + nextEpp.id);
//switch out data to the new epps
currentEpp = nextEpp;
nextEpp = getNextEpisodeData(currentEpp.id);
//Switch to next epp & update text
if(currentEpp) {
autoplayText.innerHTML = 'Netflix autoplay on, Episodes left: ' + numToWatch;
updateCountdown();
eval(ini);
nextEppTimer();
} else {
autoplayText.innerHTML = 'There does not seem to be a next episode.';
}
}
//Main loop, updates our timer and stuff, switches to next epp when necessary, yadayda
function nextEppTimer() {
setTimeout(function() {
if(isNaN(countdownTimer) || isNaN(numToWatch)) {
autoplayText.innerHTML = 'NUMBERS DO NOT WORK THAT WAY! GOOD NIGHT!';
nextEppTimer();
return;
}
if(countdownTimer <= 0) { if(numToWatch-- > 0) {
switchEpps();
} else {
done = true;
autoplayText.innerHTML = 'Netflix autoplay completed.';
numToWatch = 0;
}
} else {
if(!editingTime && !paused) {
countdownTimer--;
updateTime();
}
nextEppTimer();
}
}, 1000);
}
//attach the events we need
autoplayText.addEventListener('click', getNumberOfEpisodesToWatch, false);
pauseButton.addEventListener('click', pause, false);
timerNode.addEventListener('click', editTime, false);
timerNode.addEventListener('blur', endEdit, false);
timerNode.addEventListener('keypress', endEdit, false);
delay.addEventListener('blur', delayEdit, false);
delay.addEventListener('keyup', delayEdit, false);
//START EVERYTHING!
nextEppTimer();
})();
its still useful but it doesnt support full screen so i still have to get up and make it full screen.
Crap you are right, did not notice because I did all my testing with it not full screened, but when I went to use it it last night I found the same thing. I will have to do something about that.
You, sir, are a star. I know you didn’t plan on so many of us digging this bookmarklet, and I’m sure you are overwhelmed with people complaining about this new player crap…but we thank you from the bottom of our lazy hearts. You have made lots of people happy. That rocks.
Thank you so much!
Ty for updating the bookmarklet.
THANK YOU SOOOOOO MUCHHHHHH!!!!
Amazing, thanks!
Wonderful! Thank you for your work.
TY! You may do well to set up a Paypal donation/gift button, I know a couple of people that would not mind throwing a few bucks your way, provided it remains freeware for those who cannot.
A happy man, yes sir, that is what you have made me. You have created a solution to what I believe is the single biggest problem with Netflix, and which has prevented me from really even using my account with any enjoyment. I was even considering dropping Netflix for Hulu (which has allowed auto play all along), as I can not afford both services at this time. Now, because of you generously deciding to provide this solution freely with the rest of us, I can begin enjoying Netflix the way it always should have been. Thank you sir, for sharing this most precious jewel with us. We’re not worthy! Good karma = you. 8o)
I am trying this on Chrome and every time it goes to skip to the next episode it just refreshes the page and loads the same episode.
There are some issues with the new one. I have not seen that, but I should have a better version out soon, that I hope will fix all the problems. Stay tuned.
A friend and I are having an issue with your auto player. Instead of switching to the next episode it is either tracking back about 2 minutes or just reloading the same episode. =(
Man, you’re quick on the updates! Thanks for the continued vigilance, but I’m having an issue with this one. It only plays one episode, restarting it when it’s over. And if I may suggest something; having the timer restart upon skipping forward or back an episode would be rather handy!
Any chance of a fix on this yet?
autoFlix works great with the new layout.
Download
Autoflix no longer works at all…I appreciate the time he spent working on his program, but it’s too dodgy for paying a fee – and I paid twice. And no more updates it seems. I’ll stick with this awesome bookmarklet from Matt. It’s not perfect, but it’s free…so if it all goes pear-shape, it’s still ok. 🙂
Hey Daphne.
Email me at octalmage@gmail.com
I sent out an update a day after the change then a few more since then, but they often get marked as spam.
sorry about that.
$5? Yeah right.
Three words for you…. “Dude You Rock!”
Is this working for current iteration of Netflix? It seems to replay the current episode after its done watching it instead of moving to next epi.
Yes, but if you use the next button, or select a different episode in the player, it will throw it off and you will have that problem.
dudes. just buy autoflix. its like 5$, supports some guy with the same dilemma, and it justtt works.
That is an option.