Rectangle 27 73

You will have to make a call to the Youtube Data API's Video resource after you make the search call. You can put up to 50 video id's in search, so you wont have to call it for each element.

For example the following call:

https://www.googleapis.com/youtube/v3/videos?id=9bZkp7q19f0&part=contentDetails&key={YOUR_API_KEY}
{
 "kind": "youtube#videoListResponse",
 "etag": "\"XlbeM5oNbUofJuiuGi6IkumnZR8/ny1S4th-ku477VARrY_U4tIqcTw\"",
 "items": [
  {

   "id": "9bZkp7q19f0",
   "kind": "youtube#video",
   "etag": "\"XlbeM5oNbUofJuiuGi6IkumnZR8/HN8ILnw-DBXyCcTsc7JG0z51BGg\"",
   "contentDetails": {
    "duration": "PT4M13S",
    "dimension": "2d",
    "definition": "hd",
    "caption": "false",
    "licensedContent": true,
    "regionRestriction": {
     "blocked": [
      "DE"
     ]
    }
   }
  }
 ]
}

The time is formatted as an ISO 8601 string. PT stands for Time Duration, 4M is 4 minutes, and 13S is 13 seconds.

What is this time format ? Is it a standard which Objective C supports?

Late comment, but maybe you'd like to star and keep an eye on this ticket requesting durations be included in the search response: code.google.com/p/gdata-issues/issues/detail?id=4294

@Andrew - it is ISO 8601 formatted. I agree that it looks pretty atrocious, but at least it can be easily converted in any language - just look up ISO 8601 converter.

@Matt Koskela Doh. Sorry Matt. I have just found out that an API key & a client id are two very different things. The API key makes my life a lot easier. I am now going to research all the different queries I can make with this key. Thanks for pointing me in the right direction. This is a real bombshell moment. It looks like I have been trying to oAuth everything unneccessarily...

php - Youtube API v3 , how to get video durations? - Stack Overflow

php objective-c rest youtube-api youtube-api-v3
Rectangle 27 8

$dur = file_get_contents("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=$vId&key=dldfsd981asGhkxHxFf6JqyNrTqIeJ9sjMKFcX4");



 $duration =json_decode($dur, true);
  foreach ($duration['items'] as $vidTime) {
     $vTime= $vidTime['contentDetails']['duration'];

There it returns the time for Youtube API V3. [the key is made up by the way ;] I used $vId that I had gotten off of the returned list of the videos from the channel I am showing the videos from...

It works.. :) Google REALLY needs to include the duration in the snippet so you can get it all with one call instead of two... sigh....... it's on their 'wontfix' list.

Yes, and include the duration in human readable formats such as seconds.

What do you expect? Its Google, they dont do anything the correct way.

Did you find a way to get duration in seconds, it seems to be ahrd to convert from PT**** format to seconds.

php - Youtube API v3 , how to get video durations? - Stack Overflow

php objective-c rest youtube-api youtube-api-v3
Rectangle 27 5

I wrote the following class to get YouTube video duration using YouTube API v3. (It returns thumbnails as well)

class Youtube
{
    static $api_key = '<API_KEY>';
    static $api_base = 'https://www.googleapis.com/youtube/v3/videos';
    static $thumbnail_base = 'https://i.ytimg.com/vi/';

    // $vid - video id in youtube
    // returns - video info
    public static function getVideoInfo($vid)
    {
        $params = array(
            'part' => 'contentDetails',
            'id' => $vid,
            'key' => self::$api_key,
        );

        $api_url = Youtube::$api_base . '?' . http_build_query($params);
        $result = json_decode(@file_get_contents($api_url), true);

        if(empty($result['items'][0]['contentDetails']))
            return null;
        $vinfo = $result['items'][0]['contentDetails'];

        $interval = new DateInterval($vinfo['duration']);
        $vinfo['duration_sec'] = $interval->h * 3600 + $interval->i * 60 + $interval->s;

        $vinfo['thumbnail']['default']       = self::$thumbnail_base . $vid . '/default.jpg';
        $vinfo['thumbnail']['mqDefault']     = self::$thumbnail_base . $vid . '/mqdefault.jpg';
        $vinfo['thumbnail']['hqDefault']     = self::$thumbnail_base . $vid . '/hqdefault.jpg';

        $vinfo['thumbnail']['sdDefault']     = self::$thumbnail_base . $vid . '/sddefault.jpg';
        $vinfo['thumbnail']['maxresDefault'] = self::$thumbnail_base . $vid . '/maxresdefault.jpg';

        return $vinfo;
    }
}

Please note that you'll need API_KEY to use YouTube API:

php - Youtube API v3 , how to get video durations? - Stack Overflow

php objective-c rest youtube-api youtube-api-v3
Rectangle 27 15

Oh buddy.... welcome welcome to the world of parsing JSON files and putting up with BADLY documented APIs :)

Well I was looking into this a few months ago and I managed to get it working. Here are the things you have to do:

Will your app allow the user to login to YouTube so that they can comment/like/etc... videos? If so, then you will need to get the user to login to the YouTube API via your app first before they can do these kind of things. In order to do that, your app will need to use OAuth 2.0 to communicate with the YouTube API. Here is a superb library which you can use to authenticate with the YouTube API via OAuth 2.0: https://github.com/BHughes3388/BAHYouTubeOAuth

Step 2 - Keychain - Access Token storage

If you are new to OAuth authentication, then it can be daunting at first, but once you play around with it and familiarize yourself with it, you will realize that it is very easy to work with.

So overall, the way it works, is that your app contacts the API (in this case YouTube V3 API) and requests a webpage. The webpage allows the user to login to the APi and grant your app access. Once this has been done, the API will send your app an "access token". This token will need to be used in all (or most) of your API requests (it depends on the type of request).

Once you have obtained the "access token" you will then need to store it securely. Its basically a password, so you need to keep it safe. Do not do what some people do, which is to use NSUserDefaults, that is not secure at all. Instead you will need to use Keychain. This is Apple's secure encryption/storage library which can easily be used to save secure strings such as passwords.

In order to use Keychain to securely store and retrieve the "access token" when you need it, take a look at this SO post, its great: How to use Keychain for saving password like GenericKeychain sample code

Right so now, the harder bit. You need to read through the Google YouTube API V3 and go through the API reference documents to find the specific URLs which will return the data you are looking for. For example: if you want to get a list of videos from the home feed of a user or from a simple search, then take a look at this API reference page: https://developers.google.com/youtube/v3/docs/videos/list

Step 4 - Extract the video URL

Before I talk further about this step, I should mention that Google says you should present videos in a simple webview with YouTube HTML code which simply embeds the video view in your app. But in my opinion (and many other devs), this looks and works horribly....

So if you want to display YouTube video in your app via the native MPMovieplayerController, then you will need to extract the video URL first before you can do this.

When you make a request to the YouTube API for a set of video(s), you will get a JSON file back, this file contains a list of videos (videoIDs, titles, dates, etc....).

You will need to parse the JSON file for the video IDs. Once you or the app user has selected the video that they want, you will need to use then pass the video ID for that particular video to a "YouTube video link extractor" library. This library will then return a set of video file links for that video. These links can be used in conjunction with MPMovieplayerController to display the video natively.

This breaks YouTube's Terms of Service. The only way to play YouTube videos in an iOS application without breaking any TOS is through the YouTube's YTPlayerView: github.com/youtube/youtube-ios-player-helper

@BalzsVincze You are most welcome :)

I'm looking for something like a open source demo that runs out of the box and then copy-paste the relevant parts into my project, did you ever put together something like that.

objective c - How to use YouTube API for an iOS app? - Stack Overflow

ios objective-c google-api youtube-api integration
Rectangle 27 2

This code extracts the Youtube video duration using Youtube API v3 by passing Video ID, it worked for me.

<?php
function getDuration($videoID){
   $apikey = "YOUR-Youtube-API-KEY"; // Like this AIcvSyBsLA8znZn-i-aPLWFrsPOlWMkEyVaXAcv
   $dur = file_get_contents("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=$videoID&key=$apikey");
   $VidDuration =json_decode($dur, true);
   foreach ($VidDuration['items'] as $vidTime)
   {
       $VidDuration= $vidTime['contentDetails']['duration'];
   }
   preg_match_all('/(\d+)/',$VidDuration,$parts);
   return $parts[0][0].":".$parts[0][1].":".$parts[0][2]; // Return 1:11:46 (i.e) HH:MM:SS
}
echo getDuration("zyeubYQxHyY"); // Video ID
?>

You can get your Domain's own youtube API Key in https://console.developers.google.com and generate credentials for your own requirement.

php - Youtube API v3 , how to get video durations? - Stack Overflow

php objective-c rest youtube-api youtube-api-v3
Rectangle 27 2

Getting duration in hours, minutes and seconds using regex (tested in Python 3)

import re
def parse_ISO8601(dur):
    test1 = rex("PT(.+?)H", dur)
    if test1:
        return int(test1.group(1))*3600
    test2 = rex("PT(.+?)H(.+?)M",dur)
    if test2:
        h,m = [int(x) for x in test2.groups()]
        return 3600*h+60*m
    test3 = rex("PT(.+?)H(.+?)S",dur)
    if test3:
        h,s = [int(x) for x in test3.groups()]
        return 3600*h+s
    test4 = rex("PT(.+?)H(.+?)M(.+?)S",dur)
    if test4:
        h,m,s = [int(x) for x in test4.groups()]
        return 3600*h+60*h+s
    test5 = rex("PT(.+?)M", dur)
    if test5:
        return int(test5.group(1))*60
    test6 = rex("PT(.+?)M(.+?)S",dur)
    if test6:
        m,s = [int(x) for x in test6.groups()]
        return 60*m+s
    test7 = rex("PT(.+?)S",dur)
    if test7:
        return int(test7.group(1))
    print("CAN'T PARSE FUCKING GOOGLE FORMATTING:",dur)
    return False #I'm out ...

What library are you using to do rex? Is it re or rex. I tried your code with the python-rex library (assuming that was the one) and it said you had a regex error.

rex = lambda x,y: re.search(x,y).groups()

php - Youtube API v3 , how to get video durations? - Stack Overflow

php objective-c rest youtube-api youtube-api-v3
Rectangle 27 3

Note: YouTube <object> embeds were deprecated on January 27, 2015. Please migrate your applications to the <iframe> embeds, which can intelligently use whichever embedded player HTML (<video>) or Flash (<object>) the client supports.

The HTML5 player will load on all devices where supported. If the HTML5 player can't be loaded for whatever reason (see Are there still any remains of Flash on YouTube for Chrome?), the player will return an error to the client.

argh I'm writing the same thing :D ...and YouTube (on web) now is based on HTML 5. Bye bye Flash! (yes I hate Flash)

objective c - Why YouTube videos are allowed to be played while flash ...

ios objective-c youtube youtube-api
Rectangle 27 7

This sounds like the following open bug against the Youtube iframe player API:

Issue 5204: js iframe api playVideo() doesn't play video in iOS 7

Thanks, I'm not loosing my mind. I can up vote yet or I'd up vote this answer.

ios - UIWebView youtube iframe api autoplay/playsinline quit working i...

ios objective-c uiwebview youtube-api youtube-javascript-api
Rectangle 27 27

I'm sorry to say this is not possible in iOS. According to Apple's documentation,

"...embedded media cannot be played automatically in Safari on iOS - the user always initiates playback."

The restriction is consistent regardless of network connection as it is both a bandwidth decision as well as a user experience decision.

Update, October, 2016: It's worth noting, now that iOS 10 is out and gaining significant market share, that people can leverage changes in the way video playback works on iOS 10 to get autoplay behavior. If the video has no audio tracks or the tag is muted, autoplay can be possible. More information is available in this webkit blog. The YouTube API may handle this nicely soon.

Thanks Tegeril, I suspect you're right. I'll award you the bounty if no one else answers in a few days. I have another question similar to this, do you think you can answer that too? Many thanks stackoverflow.com/questions/9033080/

I found another reference a few minutes ago but then proceeded to crash my browser. There is a YouTube discussion out there somewhere ultimately confirming this to be the case :(

any html5 video api will only work upon user-initialization. this is how things are for now.

This is outdated information, you can either roll your own solution or use the official framework: github.com/youtube/youtube-ios-player-helper

@ABeanSits - this entire post is about autoplaying video in a web browser, not with the native SDK.

javascript - YouTube API not working with iPad / iPhone / non-Flash de...

javascript ios youtube-api
Rectangle 27 10

Some YouTube videos can be played back in a MPMoviePlayerController - some cannot. When you query a video through the YouTube Data API (link here) you'll get back all the content types available for a particular videos, including the Flash player, 3GPP, MP4 (if available), etc. You can use these URLs to load up a MPMoviePlayerController.

This is perfectly fine, but as I've said - not all videos are available to embed this way. Some videos (mainly ones that require adverts to be displayed) can't be put into native controllers.

objective c - Playing youtube videos on iOS - Stack Overflow

ios objective-c uiwebview youtube mpmovieplayercontroller
Rectangle 27 1

YouTube does not provide an API to upload videos from a URL. You would first have to download the video to your device. Once you have video, the actual file, you can upload the video to YouTube using their API.

You would have use NSURLConnection and or NSURLRequest to upload the video. Browser-based uploading

Ya.. but can you give any examples to upload video...

iphone - how to upload video to youtube from an URL - Stack Overflow

iphone objective-c youtube
Rectangle 27 2

//Button action

- (IBAction)importAudioClip:(id)sender
{
flag = 0;
customActionSheet = [[UIActionSheet alloc]initWithTitle:@"Select Audio/Video from:" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"YouTube",@"Vimeo", nil];
[customActionSheet showInView:self.view];

}


#pragma ActionSheet Delegate Methods
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
  NSLog(@"CLiekc button is %i",buttonIndex);

 if([actionSheet.title isEqualToString:@"Select Audio/Video from:"])
    {
        if (buttonIndex == 0)
        {
            videoStatus=0;

            webView.hidden = NO;

            [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.youtube.com"]]];
            NSLog(@"Taking from Youtube");

        }
        else if (buttonIndex == 1)
        {
            videoStatus=1;
            UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"Vimeo" message:@"Please enter Vimeo Username" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
            alertView.tag=123;
            alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
            [alertView show];

        }
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag==123)
    {
    if (buttonIndex==1)
    {
        templateText=[[UITextField alloc]init];
        templateText = [alertView textFieldAtIndex:0];
        templateText.autocapitalizationType=UITextAutocapitalizationTypeWords;
        templateText.delegate=self;
        if ([templateText.text length]!=0)
        {
            NSString *str=[templateText.text capitalizedString];
            NSLog(@"Str== %@",str);
            [self getVimeoDetails:str];

        }
    }
}
}


-(void)getVimeoDetails:(NSString*)userName
{
 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://vimeo.com/api/v2/%@/videos.json",userName]]];
[request setHTTPMethod:@"GET"];
NSError *err;
NSURLResponse *response;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSString *resSrt = [[NSString alloc]initWithData:responseData encoding:NSASCIIStringEncoding];
NSLog(@"The value is==%@",resSrt);
vimeoDetailsArray =(NSArray*) [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&err];
NSLog(@"jsonObject== %i",[vimeoDetailsArray count]);
NSString *theReply = [[NSString alloc] initWithBytes:[responseData bytes] length:[responseData length] encoding: NSASCIIStringEncoding];
NSLog(@"the reply == %@",theReply);
if(response)
{
    if (vimeoDetailsArray==NULL)
    {
        NSLog(@"its Null");
        NSLog(@"null response== %@",response);
        //                     UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Alert!!!" message:[NSString stringWithFormat:@"%@",theReply] delegate:self
        //                                                        cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        //                     [alert show];
        // [self performSelector:@selector(showAlertMessage:theReply withTitle:@"Alert!!!") withObject:nil afterDelay:5];
        vimeoVideoTable.hidden=YES;
        [self showAlertMessage:[NSString stringWithFormat:@"%@",theReply] withTitle:@"Alert!!!"];
    }
    else
    {
        [self createTableView];
        vimeoVideoTable.hidden=NO;
        [vimeoVideoTable reloadData];
        NSLog(@"got response== %@",response);
    }
}
else
{
    NSLog(@"faield to connect");
}


if ([responseData length] == 0 && err == nil)
{
    NSLog(@"Nothing was downloaded.");
}
else if (err != nil){

    if ([[err description] rangeOfString:@"The Internet connection appears to be offline"].location != NSNotFound)
    {
        NSLog(@"string does not contain ");
        UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Alert!!!" message:@"Please Check your Internet Connection" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
    }
    NSLog(@"Error = %@", err);
}

}

-(void)createTableView
{
if (vimeoVideoTable !=nil)
{
    [vimeoVideoTable removeFromSuperview];
    vimeoVideoTable=nil;
}
vimeoVideoTable=[[UITableView alloc]initWithFrame:CGRectMake(10, 20, 300, self.view.bounds.size.height-100)];
[vimeoVideoTable setDelegate:self];
[vimeoVideoTable setHidden:YES];
[vimeoVideoTable setDataSource:self];
[self.view addSubview:vimeoVideoTable];
//[vimeoVideoTable reloadData];

}

can you please show me full relevant code.

if you dont mine, i add the view controller.h and view controller.m full code for you

ios - How to play youtube/vimeo video within the application in iPhone...

ios objective-c youtube uiwebview vimeo
Rectangle 27 2

Your POST request is a form data request, which is usually used post the data of an HTML form. It uses a special encoding for data. That's not what the YouTube API expects. It expects a simple POST request with an XML document.

Instead of the ASIFormDataRequest class, you should use the ASIHTTPRequest class. Your code should more or less look like this:

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:strConnection]];
[request setRequestMethod:@"POST"];
[request setPostValue:@"2" forKey:@"GData-Version"];
[request setPostValue:@"application/atom+xml" forKey:@"Content-Type"];
[request setPostValue:YOUTUBE_DEVELOPER_KEY    forKey:@"X-GData-Key"];
[request setPostValue:[[delegate userInfo   ]accessTokenYoutube]  forKey:@"Authorization"];

NSString *body = [NSString stringWithFormat:@"<?xml version='1.0' encoding='UTF-8'?><entry xmlns='http://www.w3.org/2005/Atom'><id>%@</id></entry>",strVideoID];
[request appendPostData:[body dataUsingEncoding:NSUTF8StringEncoding]];

[request setDelegate:self];
[request setDidFinishSelector:@selector(didAddVideoToFavoriteFinish:)];
[request setDidFailSelector:@selector(didAddVideoToFavoriteFail:)];\
[request setDidReceiveDataSelector:@selector(didAddVideoToFavoriteSelect:)];
[request startAsynchronous];

[request release];

do we have a setPostValue method in ASIHTTPRequest? How this is worked for u? @Codo

ios - How to send a Http post request in objective c? - Stack Overflow

objective-c ios youtube-api asihttprequest
Rectangle 27 3

Beginning in iOS 4, UIWebView has the mediaPlaybackRequiresUserAction property. I cant tell if youre implementing this on the Web or in a native app, but setting that to NO in a native app should allow auto play to work.

Hi Jeff, it's purely on the web, as shown on the JSFiddle I posted. Could you show me how I would implement this using the fiddle? Thanks

You cant if its on the web; this only applies to native apps.

so this basically says if you were embedding safari into your own app you could have media auto-play. so Chrome for iPad could set this to false if they'd wanted to - but it looks like they didnt

javascript - YouTube API not working with iPad / iPhone / non-Flash de...

javascript ios youtube-api
Rectangle 27 1

Using the YouTube Embed Method requires modern browsers with HTML5 postMessage support.

The version of Firefox you are using is version 4.0 but postMessage is available in Firefox starting from version 6.

Coincidentally, if you were using Firefox Version 6 and your embed markup was complete with Video ID, you will be subject to a catastrophic bug that's surfaced the last two days for the YouTube Embed API... Flash Fallback is broken! See this SO workaround solution if applicable to you:https://stackoverflow.com/a/10560802/1195891

javascript - youtube api , firefox 4.0 . iframe failing to load videos...

javascript api video youtube
Rectangle 27 1

Most of the JavaScript Player API functions have Objective-C equivalents, though some of the naming may differ slightly to more closely match Objective-C coding guidelines. Notable exceptions are methods controlling the volume of the video, since these are controlled by the phone hardware or with built in UIView instances designed for this purpose, such as MPVolumeView.

Volume Control in JavaScript

On the desktop, you can set and read the volume property of an or element. This allows you to set the elements audio volume relative to the computers current volume setting. A value of 1 plays sound at the normal level. A value of 0 silences the audio. Values between 0 and 1 attenuate the audio. This volume adjustment can be useful, because it allows the user to mute a game, for example, while still listening to music on the computer. On iOS devices, the audio level is always under the users physical control. The volume property is not settable in JavaScript. Reading the volume property always returns 1.

ios - How can i volume set in uiwebview with swift? - Stack Overflow

ios swift youtube uiwebview volume
Rectangle 27 279

Fiddle Links: Source code - Preview - Small version Update: This small function will only execute code in a single direction. If you want full support (eg event listeners / getters), have a look at Listening for Youtube Event in jQuery

As a result of a deep code analysis, I've created a function: function callPlayer requests a function call on any framed YouTube video. See the YouTube Api reference to get a full list of possible function calls. Read the comments at the source code for an explanation.

On 17 may 2012, the code size was doubled in order to take care of the player's ready state. If you need a compact function which does not deal with the player's ready state, see http://jsfiddle.net/8R5y6/.

/**
 * @author       Rob W <gwnRob@gmail.com>
 * @website      https://stackoverflow.com/a/7513356/938089
 * @version      20131010
 * @description  Executes function on a framed YouTube video (see website link)
 *               For a full list of possible functions, see:
 *               https://developers.google.com/youtube/js_api_reference
 * @param String frame_id The id of (the div containing) the frame
 * @param String func     Desired function to call, eg. "playVideo"
 *        (Function)      Function to call when the player is ready.
 * @param Array  args     (optional) List of arguments to pass to function func*/
function callPlayer(frame_id, func, args) {
    if (window.jQuery && frame_id instanceof jQuery) frame_id = frame_id.get(0).id;
    var iframe = document.getElementById(frame_id);
    if (iframe && iframe.tagName.toUpperCase() != 'IFRAME') {
        iframe = iframe.getElementsByTagName('iframe')[0];
    }

    // When the player is not ready yet, add the event to a queue
    // Each frame_id is associated with an own queue.
    // Each queue has three possible states:
    //  undefined = uninitialised / array = queue / 0 = ready
    if (!callPlayer.queue) callPlayer.queue = {};
    var queue = callPlayer.queue[frame_id],
        domReady = document.readyState == 'complete';

    if (domReady && !iframe) {
        // DOM is ready and iframe does not exist. Log a message
        window.console && console.log('callPlayer: Frame not found; id=' + frame_id);
        if (queue) clearInterval(queue.poller);
    } else if (func === 'listening') {
        // Sending the "listener" message to the frame, to request status updates
        if (iframe && iframe.contentWindow) {
            func = '{"event":"listening","id":' + JSON.stringify(''+frame_id) + '}';
            iframe.contentWindow.postMessage(func, '*');
        }
    } else if (!domReady ||
               iframe && (!iframe.contentWindow || queue && !queue.ready) ||
               (!queue || !queue.ready) && typeof func === 'function') {
        if (!queue) queue = callPlayer.queue[frame_id] = [];
        queue.push([func, args]);
        if (!('poller' in queue)) {
            // keep polling until the document and frame is ready
            queue.poller = setInterval(function() {
                callPlayer(frame_id, 'listening');
            }, 250);
            // Add a global "message" event listener, to catch status updates:
            messageEvent(1, function runOnceReady(e) {
                if (!iframe) {
                    iframe = document.getElementById(frame_id);
                    if (!iframe) return;
                    if (iframe.tagName.toUpperCase() != 'IFRAME') {
                        iframe = iframe.getElementsByTagName('iframe')[0];
                        if (!iframe) return;
                    }
                }
                if (e.source === iframe.contentWindow) {
                    // Assume that the player is ready if we receive a
                    // message from the iframe
                    clearInterval(queue.poller);
                    queue.ready = true;
                    messageEvent(0, runOnceReady);
                    // .. and release the queue:
                    while (tmp = queue.shift()) {
                        callPlayer(frame_id, tmp[0], tmp[1]);
                    }
                }
            }, false);
        }
    } else if (iframe && iframe.contentWindow) {
        // When a function is supplied, just call it (like "onYouTubePlayerReady")
        if (func.call) return func();
        // Frame exists, send message
        iframe.contentWindow.postMessage(JSON.stringify({
            "event": "command",
            "func": func,
            "args": args || [],
            "id": frame_id
        }), "*");
    }
    /* IE8 does not support addEventListener... */
    function messageEvent(add, listener) {
        var w3 = add ? window.addEventListener : window.removeEventListener;
        w3 ?
            w3('message', listener, !1)
        :
            (add ? window.attachEvent : window.detachEvent)('onmessage', listener);
    }
}
callPlayer("whateverID", function() {
    // This function runs once the player is ready ("onYouTubePlayerReady")
    callPlayer("whateverID", "playVideo");
});
// When the player is not ready yet, the function will be queued.
// When the iframe cannot be found, a message is logged in the console.
callPlayer("whateverID", "playVideo");

Q: It doesn't work!A: "Doesn't work" is not a clear description. Do you get any error messages? Please show the relevant code.

<iframe src="http://www.youtube.com/embed/As2rZGPGKDY" />
?enablejsapi=1
/embed/vid_id?enablejsapi=1

Q: I get error message "An invalid or illegal string was specified". Why?A: The API doesn't function properly at a local host (file://). Host your (test) page online, or use JSFiddle. Examples: See the links at the top of this answer.

Q: How did you know this?A: I have spent some time to manually interpret the API's source. I concluded that I had to use the postMessage method. To know which arguments to pass, I created a Chrome extension which intercepts messages. The source code for the extension can be downloaded here.

Q: What browsers are supported?A: Every browser which supports JSON and postMessage.

  • Firefox 3.6+ (actually 3.5, but document.readyState was implemented in 3.6)
onYouTubePlayerReady
callPlayer('frame_id', function() { ... })
  • 24 july 2012 Updated and successully tested in the supported browsers (look ahead).
  • 10 october 2013 When a function is passed as an argument, callPlayer forces a check of readiness. This is needed, because when callPlayer is called right after the insertion of the iframe while the document is ready, it can't know for sure that the iframe is fully ready. In Internet Explorer and Firefox, this scenario resulted in a too early invocation of postMessage, which was ignored.
  • 12 Dec 2013, recommended to add &origin=* in the URL.
&origin=*

@RobW I tried that actually. Seems like the JSON in error is not the one in your script, but inside the iframe as a part of youtube's API.

@RobW thanks for this nice snippet. Have you found any ways to use the Message Event instead of using the youtube JS API in order to add an event listener?

@brillout.com The PostMessage method is based on the YT JS API (?enablejsapi=1). Without enabling the JS API, the postMessage method will not do anything, See the linked answer for an easy implementation of event listeners. I have also created, but not published, readable code to communicate with the frame. I decided to not publish it, because its effect is similar to the default YouTube Frame API.

@MatthewBaker That requires listening to the message event and parsing the status of the result. This is not as easy as simple calls like playVideo, so I recommend to use the official API for that. See developers.google.com/youtube/iframe_api_reference#Events.

@ffyeahh I don't see any obvious error. Please ask a new question with a self-contained steps-to-reproduce instead of adding questions in comments to this answer.

javascript - YouTube iframe API: how do I control a iframe player that...

javascript youtube-api youtube-javascript-api
Rectangle 27 278

Fiddle Links: Source code - Preview - Small version Update: This small function will only execute code in a single direction. If you want full support (eg event listeners / getters), have a look at Listening for Youtube Event in jQuery

As a result of a deep code analysis, I've created a function: function callPlayer requests a function call on any framed YouTube video. See the YouTube Api reference to get a full list of possible function calls. Read the comments at the source code for an explanation.

On 17 may 2012, the code size was doubled in order to take care of the player's ready state. If you need a compact function which does not deal with the player's ready state, see http://jsfiddle.net/8R5y6/.

/**
 * @author       Rob W <gwnRob@gmail.com>
 * @website      https://stackoverflow.com/a/7513356/938089
 * @version      20131010
 * @description  Executes function on a framed YouTube video (see website link)
 *               For a full list of possible functions, see:
 *               https://developers.google.com/youtube/js_api_reference
 * @param String frame_id The id of (the div containing) the frame
 * @param String func     Desired function to call, eg. "playVideo"
 *        (Function)      Function to call when the player is ready.
 * @param Array  args     (optional) List of arguments to pass to function func*/
function callPlayer(frame_id, func, args) {
    if (window.jQuery && frame_id instanceof jQuery) frame_id = frame_id.get(0).id;
    var iframe = document.getElementById(frame_id);
    if (iframe && iframe.tagName.toUpperCase() != 'IFRAME') {
        iframe = iframe.getElementsByTagName('iframe')[0];
    }

    // When the player is not ready yet, add the event to a queue
    // Each frame_id is associated with an own queue.
    // Each queue has three possible states:
    //  undefined = uninitialised / array = queue / 0 = ready
    if (!callPlayer.queue) callPlayer.queue = {};
    var queue = callPlayer.queue[frame_id],
        domReady = document.readyState == 'complete';

    if (domReady && !iframe) {
        // DOM is ready and iframe does not exist. Log a message
        window.console && console.log('callPlayer: Frame not found; id=' + frame_id);
        if (queue) clearInterval(queue.poller);
    } else if (func === 'listening') {
        // Sending the "listener" message to the frame, to request status updates
        if (iframe && iframe.contentWindow) {
            func = '{"event":"listening","id":' + JSON.stringify(''+frame_id) + '}';
            iframe.contentWindow.postMessage(func, '*');
        }
    } else if (!domReady ||
               iframe && (!iframe.contentWindow || queue && !queue.ready) ||
               (!queue || !queue.ready) && typeof func === 'function') {
        if (!queue) queue = callPlayer.queue[frame_id] = [];
        queue.push([func, args]);
        if (!('poller' in queue)) {
            // keep polling until the document and frame is ready
            queue.poller = setInterval(function() {
                callPlayer(frame_id, 'listening');
            }, 250);
            // Add a global "message" event listener, to catch status updates:
            messageEvent(1, function runOnceReady(e) {
                if (!iframe) {
                    iframe = document.getElementById(frame_id);
                    if (!iframe) return;
                    if (iframe.tagName.toUpperCase() != 'IFRAME') {
                        iframe = iframe.getElementsByTagName('iframe')[0];
                        if (!iframe) return;
                    }
                }
                if (e.source === iframe.contentWindow) {
                    // Assume that the player is ready if we receive a
                    // message from the iframe
                    clearInterval(queue.poller);
                    queue.ready = true;
                    messageEvent(0, runOnceReady);
                    // .. and release the queue:
                    while (tmp = queue.shift()) {
                        callPlayer(frame_id, tmp[0], tmp[1]);
                    }
                }
            }, false);
        }
    } else if (iframe && iframe.contentWindow) {
        // When a function is supplied, just call it (like "onYouTubePlayerReady")
        if (func.call) return func();
        // Frame exists, send message
        iframe.contentWindow.postMessage(JSON.stringify({
            "event": "command",
            "func": func,
            "args": args || [],
            "id": frame_id
        }), "*");
    }
    /* IE8 does not support addEventListener... */
    function messageEvent(add, listener) {
        var w3 = add ? window.addEventListener : window.removeEventListener;
        w3 ?
            w3('message', listener, !1)
        :
            (add ? window.attachEvent : window.detachEvent)('onmessage', listener);
    }
}
callPlayer("whateverID", function() {
    // This function runs once the player is ready ("onYouTubePlayerReady")
    callPlayer("whateverID", "playVideo");
});
// When the player is not ready yet, the function will be queued.
// When the iframe cannot be found, a message is logged in the console.
callPlayer("whateverID", "playVideo");

Q: It doesn't work!A: "Doesn't work" is not a clear description. Do you get any error messages? Please show the relevant code.

<iframe src="http://www.youtube.com/embed/As2rZGPGKDY" />
?enablejsapi=1
/embed/vid_id?enablejsapi=1

Q: I get error message "An invalid or illegal string was specified". Why?A: The API doesn't function properly at a local host (file://). Host your (test) page online, or use JSFiddle. Examples: See the links at the top of this answer.

Q: How did you know this?A: I have spent some time to manually interpret the API's source. I concluded that I had to use the postMessage method. To know which arguments to pass, I created a Chrome extension which intercepts messages. The source code for the extension can be downloaded here.

Q: What browsers are supported?A: Every browser which supports JSON and postMessage.

  • Firefox 3.6+ (actually 3.5, but document.readyState was implemented in 3.6)
onYouTubePlayerReady
callPlayer('frame_id', function() { ... })
  • 24 july 2012 Updated and successully tested in the supported browsers (look ahead).
  • 10 october 2013 When a function is passed as an argument, callPlayer forces a check of readiness. This is needed, because when callPlayer is called right after the insertion of the iframe while the document is ready, it can't know for sure that the iframe is fully ready. In Internet Explorer and Firefox, this scenario resulted in a too early invocation of postMessage, which was ignored.
  • 12 Dec 2013, recommended to add &origin=* in the URL.
&origin=*

@RobW I tried that actually. Seems like the JSON in error is not the one in your script, but inside the iframe as a part of youtube's API.

@RobW thanks for this nice snippet. Have you found any ways to use the Message Event instead of using the youtube JS API in order to add an event listener?

@brillout.com The PostMessage method is based on the YT JS API (?enablejsapi=1). Without enabling the JS API, the postMessage method will not do anything, See the linked answer for an easy implementation of event listeners. I have also created, but not published, readable code to communicate with the frame. I decided to not publish it, because its effect is similar to the default YouTube Frame API.

@MatthewBaker That requires listening to the message event and parsing the status of the result. This is not as easy as simple calls like playVideo, so I recommend to use the official API for that. See developers.google.com/youtube/iframe_api_reference#Events.

@ffyeahh I don't see any obvious error. Please ask a new question with a self-contained steps-to-reproduce instead of adding questions in comments to this answer.

javascript - YouTube iframe API: how do I control a iframe player that...

javascript youtube-api youtube-javascript-api
Rectangle 27 18

There was a temporary issue with the iFrame Player API (which was fixed in June 2013) that you can read about here: https://code.google.com/p/gdata-issues/issues/detail?id=4706

As a temporary fix, you just need to add the event listener within the onReady event:

function onReady() {
    player.addEventListener('onStateChange', function(e) {
        console.log('State is:', e.data);
    });
}

Make sure to remove the onStateChange event from the YT.PLAYER constructor (see the jsfiddle).

Also, as someone mentioned on the Google Code Issue Thread, you set an interval and poll the player for its current state instead of listening for the onStateChange event. Here is an example code snippet for doing that:

setInterval( function() {
  var state = player.getPlayerState();
  if ( playerState !== state ) {
    onPlayerStateChange( {
      data: state
    });
  }
}, 10);

Other people have mentioned that Firefox will not instantiate the YouTube Player if it is placed in a container with the css property display: none. Internet Explorer will also not work with visibility: hidden. If you're finding this to be the issue, try positioning the container off the page with something like left: -150%.

The issue seems now that I write not to be fixed (PT time 00.44) yet.

May not be working if you're using an iframe rather than a div that gets replaced once the api loads

In my case, this was not the solution (and this bug should be resolved by now?). I had display:none on the container of the video and the API didn't fire. More here: stackoverflow.com/a/22199021/406171

Thanks! I needed the polling workaround to get this working... Two updates to the polling function (for completeness' sake): - Add var playerState as a first line, to initialize the variable - Add the line playerState = state, to keep track of the new state once the event has fired.

javascript - YouTube iframe player API - OnStateChange not firing - St...

javascript youtube-api
Rectangle 27 18

There was a temporary issue with the iFrame Player API (which was fixed in June 2013) that you can read about here: https://code.google.com/p/gdata-issues/issues/detail?id=4706

As a temporary fix, you just need to add the event listener within the onReady event:

function onReady() {
    player.addEventListener('onStateChange', function(e) {
        console.log('State is:', e.data);
    });
}

Make sure to remove the onStateChange event from the YT.PLAYER constructor (see the jsfiddle).

Also, as someone mentioned on the Google Code Issue Thread, you set an interval and poll the player for its current state instead of listening for the onStateChange event. Here is an example code snippet for doing that:

setInterval( function() {
  var state = player.getPlayerState();
  if ( playerState !== state ) {
    onPlayerStateChange( {
      data: state
    });
  }
}, 10);

Other people have mentioned that Firefox will not instantiate the YouTube Player if it is placed in a container with the css property display: none. Internet Explorer will also not work with visibility: hidden. If you're finding this to be the issue, try positioning the container off the page with something like left: -150%.

The issue seems now that I write not to be fixed (PT time 00.44) yet.

May not be working if you're using an iframe rather than a div that gets replaced once the api loads

In my case, this was not the solution (and this bug should be resolved by now?). I had display:none on the container of the video and the API didn't fire. More here: stackoverflow.com/a/22199021/406171

Thanks! I needed the polling workaround to get this working... Two updates to the polling function (for completeness' sake): - Add var playerState as a first line, to initialize the variable - Add the line playerState = state, to keep track of the new state once the event has fired.

javascript - YouTube iframe player API - OnStateChange not firing - St...

javascript youtube-api