YouTube Player API: Refresh page if video error - javascript

Solved this myself and it made me feel silly. What I was looking to do is not properly referenced in the API article. Giving the solution for others looking to achieve this.
The solution is:-
I've found the solution myself and boy do I feel silly. It's not referenced correctly in the YouTube Player API.
After many hours of playing with it, here is the solution.
// Skip dead videos
function onPlayerError(event) {
window.location.reload(true);
}
This requires you have the following in the YouTube Player calls:-
'onError' : onPlayerError
I am loading an array of video id's into the player, sometimes thousands (randomly). I have been trying to figure out a way to reload the page if x video shoots out an error.
The YouTube Player API lists only a couple error codes:-
https://developers.google.com/youtube/iframe_api_reference#Events
However, this does not cover private/copyright videos.
As is when a video ends I reload the page to randomly load a new video with:-
function onPlayerStateChange(event) {
if(event.data === 0) {
window.location.reload(true);
}
}
I have tried the below to no avail:-
// skip copyright videos
function onPlayerError(errorCode) {
if(errorCode == auth) {
window.location.reload(true);
}
}
The error code here is what I pulled out of the debug info for a copyright video (its the same for private). However, this is not in the API, thus does not work.
I also tried the following:-
// skip by numeric code
function onPlayerError(errorCode) {
if(errorCode == 100) {
window.location.reload(true);
}
}
Which is a valid error code and should work, but doesn't seem to want to.
I've tried a few other methods as well thinking I could read the API info and force a function, seems not. Have also tried fiddling with PlayerState.
Before anyone asks. No, I cannot use playlist embeds.
If anyone could help out, I'd really appreciate it!
Thanks

Related

Javascript get updated link in real time

I'm new to javascript and I've created a kinda successful extension on chrome for dubtrack I've been trying to figure out for quite awhile how to make my injected script run in real time and grab the latest youtube music video url any help would be much appreciated my extension is very basic and it's not for profit I just made it to play around with javascript and jquery.
Here's the section of code that I'd like to have function in real time.
$('#grab').click(function() {
function getId(url) {
var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var match = url.match(regExp);
if (match && match[2].length == 11) {
return match[2];
} else {
return 'error';
}
}
src = $('iframe').attr('src');
setInterval(function() {
src = $('iframe').attr('src');
}, 10000);
window.open('http://youtubeinmp3.com/fetch/?video=http://www.youtube.com/watch?v=' + getId(src), '_blank');
});
Relevant links
GitHub
Chrome Extension
Thank you for taking the time to read my question.
You're bad at explaining (and might want to edit the question to reflect what you want), but basically the problem is this:
You have a YouTube embed in the page, with a particular video ID in src.
When the video changes, that happens without updating the src (by using YT embed API).
Therefore, if you try to grab just the src, it's not the latest video but the first you loaded.
As an extension, I see two ways of trying to solve it:
You could try to initialize the YT API yourself to get a player reference. I don't know if it will break the code of Dubtrack.
You could inject a script in the iframe as well that would somehow extract the video being played in a way other than relying on src.
It's an open problem how to solve it, and the fact that you're basically providing "just" a bookmarklet may be an obstacle.

Text to speech using javascript and translate_tts

I have been trying to get my webpage to play up what it says in a text box when the user click on a link, but so far I haven't manage. I have tried with
function listen(){
var sound = new Audio();
sound.src = "http://translate.google.com/translate_tts?ie=UTF-8&tl=sv&q=Testar";
sound.play();
alert(":D");
return false;
}
and
function listen(){
var sound = document.createElement("audio");
sound.setAttribute("src","http://translate.google.com/translate_tts?tl=sv&q=Testar");
sound.load();
sound.play();
alert(":D");
return false;
}
I have tried adding ie=UTF-8 to the link, and tried both with and without sound.play(); but nothing have worked. I get smiley face from the alert so I know the function runs. Can someone please help me get this to work.
EDIT: I did a work around by using and iframe which I hide by using display: none; and then simply using javascript to change the src, not the best solution but it works... for now.
This is an easy way to do it :
var sound = new Audio("http://translate.google.com/translate_tts?tl=sv&q=Testar");
sound.play();
Now it's a bit more complicated, but still possible:
you need set up an user-agent string like a common browser and, more difficult, you also must provide a token into the GET request.
Some people managed to extract the token algorithm from the js code of the page, but it's quite a long work and at any time the algorithm changes you need to start again the reverse engineering of the cryptic code.
So it's much easier access to a particular url from the same site that generates an XHR that shows the token you need.
A simple script with phantomjs and grep will do the job for you, details here:
https://stackoverflow.com/a/37221340/6332793

Youtube Player API Throws 404

This has been bugging me for a while now, I am using this generic script to create a player
var player = new YT.Player(videoArray[0], { videoId : videoArray[0], events : { 'onStateChange' : onPlayerStateChange } });
I have the callback function set up with just a simple console.log the problem is when I change the state of a player the console throws
https://www.youtube.com/get_video?noflv=1&video_id=ghUA.... GET 404 from the file html5player-en_US-vfloyxzv5.js:39 witch I asume is loaded by the YouTube Iframe API.
Any ideeas or posibile solutions will be greatly apreciated.
Sadly, this is one of the numerous little things you'll have to cope with using the Youtube Player API. I don't think there is any solution, and we can only wait for a Youtube fix.
A bug report has already been created, feel free to vote for it.
Youtube player is updated every tuesday. Hopefully, this will be fixed someday.
I found out what I was doing wrong, I am posting this maybe it will help someone along the way.
Since the videoArray was holding jQuery object, I used this piece of code to get it all working.
if(isYouTubeVideo) {
videoID = iframeSrc.substr(baseUrlLength);
}
videoArray[i] = {};
videoArray[i].id = videoID;
jQuery.ajax({
dataType: 'JSON',
url: 'https://gdata.youtube.com/feeds/api/videos/' + videoID + '?v=2&alt=json'
})
.done(function(data) {
videoArray[i].title = data.entry.title.$t;
});
jQuery(this).attr('id', videoID);
playerArray[i] = new YT.Player(videoArray[i].id, { event : //Events here})
I hope this helps someone :)
I get this for certain videos. In my experience, the get_video 404 doesn't matter - the video still loads correctly.
There is one random caveat though; if you're running this on an iPhone connected to Mac Safari Web Inspector, the 404 causes the video to stop loading. This caused me hours of fun!

Embedding a SoundCloud recording right away?

Basically I want the user to record a sound with the SoundCloud recorder and once they click save, the sound they just recorded will be embedded on to my webpage.
I use the SC.record() method to get the recording. This is my function for where I save the recordings... Right now nothing is embedded when I try to run it
$('#save a').click(function(e) {
var currentURL ="";
e.preventDefault();
SC.connect({
connected: function() {
$('.status').html('Uploading...');
SC.recordUpload({
track: {
title: 'whatever',
sharing: 'public'
}
}, function(track) {
currentURL = '"'+track.permalink_url+'"';
$('#SCtracks').append('<li id='+currentURL+'>'+currentURL+'</li>');
SC.oEmbed(currentURL, {color: "ff0066"}, document.getElementById(currentURL));
});
}
});
});
But if I go in and call SC.oEmbed with a URL to a recording I made earlier it works fine.
So I think I might be trying to embed the recording before it is fully uploaded, but I don't know where else I could put that statement.
Thanks
This answered my question. I guess you have to just keep checking the state until it is for sure done. If someone know a quicker way please answer

YouTube JS API Breaking Change? Will no longer initialize without the videoid parameter as of 2/27/2013

To demonstrate the breaking change I discovered today I took the basic JS API sample page which can be found with link below and simply commented out the videoId parameter:
YT Sample Code demonstrating initialization error: http://www.multitask123.com/fmgem/YT_Sample2.htm
With said removal of videoId parameter the player will now display/initialize with the following error message in the embedded player, "An error occurred. Please try later." This was not the case until this afternoon.
For the past three months I could call onYouTubePlayerAPIReady as follows and there would be no error message:
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
//videoId: 'JW5meKfy3fY', - COMMENTED OUT INTENTIONALLY! HARD REQUIREMENT!
events: {
'onReady': onPlayerReady,
'onError': onPlayerError,
'onStateChange': onPlayerStateChange
}
});
}
The error is caught by the onPlayerError event handler during initialization and the error comes in with the "evt" parameter's data attribute. So onPlayerError(evt) is called on initialization and evt.data = 2. This value is documented as, "The request contains an invalid parameter value" which is clearly the API expecting a videoId.
I do not want to go into too much detail but I spent countless hours getting the initialization of the player to work just right as there are numerous cross browser initialization issues. I need to hide the player until I actually need it to play something.
I forget which browser is the culprit but one of them actually forces me to show the player even though no video is playing.
I discovered I cannot lazy load/JIT the embedded player because it loads asynchronously so if I try to only load it when my users wish to actually view a video or there are other parameters of the URL involved that will load a playlist for example the player will balk because I cannot BOTH initialize the player and ask it to play a video.
So the bottom line is the player NEEDS to be initialized when the page is loading but NOT with a videoId parameter because quite simply I have no idea what is going to be played in 90% of the circumstances and even if I did that would be the result of a different asynchronous call to a different API. I say this because the solution to initialize it with a videoid is unacceptable.
The YouTube API is amazing and I love it so much so that I have spent 18 months developing http://www.fmgem.com and now this breaking change is ruining the first impression beta users will have of my app. So if the YT API team does indeed monitor this please change it back. Pretty please with sugar on top. :))
Something similar happened a few weeks ago with the same function's wmode attribute on load.
//wmode: 'opaque' //--- causes wicked bug in Chrome - And I was able to change opaque to transparent so no biggie there but this would require me to review my entire architecture and methodically handle apx 9 different asynchronous use-cases for load that again, have all had cross-browser quirks.
So I cannot afford to be reactive and I have been forced to put in a "sneezing baby panda" videoId into the live code at http://www.fmgem.com but that looks quite unprofessional and it is merely a band-aid until I can review the entire architecture unless YT Team actually acknowledges this as a breaking change and then puts it back to its prior behavior.
This was detected by some users sometime during the afternoon of 2/27/2013 and I have read on google groups that YouTube's developers monitor SO.
Any answers, solutions, guidance or confirmation would be greatly appreciated.
Thanks!!
You can initially load a blank 0 second movie. Or you can re-arrange your code a tad bit.
Do not call onYouTubePlayerAPIReady function yourself. Use flag variables instead:
var playerAPIReady;
var player;
Set the first variable when the API file calls onYouTubePlayerAPIReady function:
function onYouTubePlayerAPIReady() {
playerAPIReady = true;
}
Set the second variable when the user chooses to play first video:
function createPlayerAndPlayVideo(id) {
if(! playerAPIReady) {
// player API file not loaded
return;
}
if (! player) {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: id
events: {
'onReady': onPlayerReady,
'onError': onPlayerError,
'onStateChange': onPlayerStateChange
}
});
} else {
player.loadVideoById(id);
}
}
Re-use the same player for subsequent videos as shown in the else block.
While this is a breaking change beyond a doubt now that I got a good night's sleep I found a solution to my own issue to lazy load / JIT the player.
The solution I have a proof of concept of and am currently implementing is as simple as setting a global var to test if I have a videoid.
var cleared = false;
function onYouTubePlayerAPIReady(videoid) {
if (!cleared) return;
.....
Then when I actually want to play a video I just see if the variable is false and if so I call the onYouTubePlayerAPIReady function and pass it the videoid and initialize it. My mistake was to try to initialize and then call the play() function in the same call. The solution for me is to either call the initializer with an id or call the playbyid function if already initialized.
While I do love the YT public API and others that I use it does open the door to lots of breaking changes and that is always a test of one's architectural and mental fortitude.
I'm not ruling out that something may have changed on Feb. 27, but the intention has always been that videoId (or a list id) is required when initializing an iframe Player. It isn't spelled out explicitly in the documentation, but at the same time, it never suggests that the parameter is optional, and all examples given do include a value for videoId.
So I wouldn't count on this behavior changing back in the future.
The most common thing to do when you have a YouTube iframe Player that you want to be initialized and not visible is to use CSS to set its position outside of the viewable area in the browser (such as by using negative x and y coordinates). You can initialize the player with whatever placeholder video you want, then call loadVideoById() when you're ready to play back a real video, and when you detect onStateChange with YT.PlayerState.BUFFERING or YT.PlayerState.PLAYING, you can move the player to the appropriate visible position.
Alternatively, you can just delay loading the player until you need it.

Categories

Resources