Skip to content

YouTube API for CodeIgniter

World Wide Web Server edited this page Jul 4, 2012 · 17 revisions

Category:Libraries::YouTube API Category:Library::YouTube API

I have finished up work on the YouTube API library. This will let you make YouTube api calls without having to include all of the Zend Gdata libraries. This library has a single dependency which is on an OAuth signing helper I wrote which can be found at

[url]http://codeigniter.com/wiki/OAuth_Helper/[/url]

This library only works with OAuth authentication but a number of calls can be made without any authentication at all. You must pass in a few parameters while loading the library these are as follows:

Your YouTube API key this is given to you when you sign up as a developer with YouTube, and it is required. [code] $params['apikey'] = $this->config->item('youtube_api_key') [/code]

Also your oauth data if you are using authentication. You must provide your consumer key and secret, the signing algorithm you are using and if you already have an authenticated user you must pass in their OAuth access token data as an array containing the oauth_token and (if you are using HMAC signing) the oauth_token_secret. All values of the access_token array must be urlencoded.

I keep my static OAuth data in a config file
[code] $params['oauth']['key'] = $this->config->item('google_consumer_key'); $params['oauth']['secret'] = $this->config->item('google_consumer_secret'); $params['oauth']['algorithm'] = $this->config->item('google_signing_algo'); $params['oauth']['access_token'] = array('oauth_token'=>urlencode($token)); [/code]

After that we can load our library [code] $this->load->library('youtube', $params); [/code]

Now we have free reign to call any API method we choose. All methods will return a string of XML. It is your job to parse the XML and get out whatever you need. Some methods don't require an authenticated user but other do. Consult the library comments for more details. Here is a breakdown of all the methods that are available:

[code] getVideoEntry($videoId, $fullEntry = false) getRelatedVideoFeed($videoId) getVideoResponseFeed($videoId) getVideoCommentFeed($videoId) getTopRatedVideoFeed() getMostViewedVideoFeed() getRecentlyFeaturedVideoFeed() getWatchOnMobileVideoFeed() getPlaylistListFeed($user = 'default') getSubscriptionFeed($user = 'default') getContactFeed($user = 'default') getUserUploads($user = 'default') getUserFavorites($user = 'default') getUserProfile($user = 'default') getActivityForUser($user = 'default') getFriendActivityForCurrentUser() getInboxFeedForCurrentUser() getFormUploadToken($metadata) [/code]

Methods where you define the user (by the users name) only require authentication if the user is defined as 'default' which indicates the currently logged in user. If a method is named get***ForCurrentUser then it requires authentication. Finally the getFormUploadToken method also requires an authenticated user to work.

In addition to requiring an authenticated user getFormUploadToken also requires some XML meta data be passed in. You can find out more about what this should look like at:

[url]http://code.google.com/apis/youtube/2.0/developers_guide_protocol.html#Sending_a_Browser_Upload_API_Request[/url]

I wrote a library to get an OAuth access token from a google service it can be found at:

[url]http://codeigniter.com/wiki/OAuth_for_Google/[/url]

Here is the complete library. If you would rather download a copy you can do so at my blog:

[url]http://jimdoescode.blogspot.com/2010/10/codeigniter-and-youtube-api-this-is.html[/url]

[code]

<?php class youtube { const HTTP_1 = '1.1'; const HOST = 'gdata.youtube.com'; const PORT = '80'; const SCHEME = 'http'; const METHOD = 'GET'; const LINE_END = "\r\n";

const URI_BASE = 'http://gdata.youtube.com/';

const DEBUG = false;

private $_uris = array(
    'STANDARD_TOP_RATED_URI'            => 'feeds/api/standardfeeds/top_rated',
    'STANDARD_MOST_VIEWED_URI'          => 'feeds/api/standardfeeds/most_viewed',
    'STANDARD_RECENTLY_FEATURED_URI'    => 'feeds/api/standardfeeds/recently_featured',
    'STANDARD_WATCH_ON_MOBILE_URI'      => 'feeds/api/standardfeeds/watch_on_mobile',
    'USER_URI'                          => 'feeds/api/users',
    'INBOX_FEED_URI'                    => 'feeds/api/users/default/inbox',
    'FRIEND_ACTIVITY_FEED_URI'          => 'feeds/api/users/default/friendsactivity',
    'ACTIVITY_FEED_URI'                 => 'feeds/api/events',
    'VIDEO_URI'                         => 'feeds/api/videos',
    'USER_UPLOADS_REL'                  => 'schemas/2007#user.uploads',
    'USER_PLAYLISTS_REL'                => 'schemas/2007#user.playlists',
    'USER_SUBSCRIPTIONS_REL'            => 'schemas/2007#user.subscriptions',
    'USER_CONTACTS_REL'                 => 'schemas/2007#user.contacts',
    'USER_FAVORITES_REL'                => 'schemas/2007#user.favorites',
    'VIDEO_RESPONSES_REL'               => 'schemas/2007#video.responses',
    'VIDEO_RATINGS_REL'                 => 'schemas/2007#video.ratings',
    'VIDEO_COMPLAINTS_REL'              => 'schemas/2007#video.complaints',
    'PLAYLIST_REL'                      => 'schemas/2007#playlist',
    'IN_REPLY_TO_SCHEME'                => 'schemas/2007#in-reply-to',
    'UPLOAD_TOKEN_REQUEST'              => 'action/GetUploadToken'
);

private $_header = array(
    'Host'=>self::HOST,
    'Connection'=>'close',
    'User-Agent'=>'CodeIgniter',
    'Accept-encoding'=>'identity'
);

private $_oauth = array();
private $_access = false;

/**
 * Create YouTube object
 *
 * @param string $clientId The clientId issued by the YouTube dashboard
 * @param string $developerKey The developerKey issued by the YouTube dashboard
 */
public function youtube($params)
{
    if(isset($params['apikey']))$this->_header['X-GData-Key'] = 'key='.$params['apikey'];
    $this->CI = get_instance();
    if(isset($params['oauth']))
    {
        $this->_oauth['key'] = $params['oauth']['key'];
        $this->_oauth['secret'] = $params['oauth']['secret'];
        $this->_oauth['algorithm'] = $params['oauth']['algorithm'];
        $this->_access = $params['oauth']['access_token'];
    }
}

private function _build_header($url = false, $prepend = false, $append = false, $method = self::METHOD)
{
    $str = $prepend === false ? '' : $prepend;
    foreach($this->_header AS $key=>$value)
        $str .= $key.": ".$value.self::LINE_END;
    if($this->_access !== false && $url !== false)
    {
        $this->CI->load->helper('oauth_helper');
        //TODO: Instead of static oauth values make these passed in by the access array.
        $str .= get_auth_header($url, $this->_oauth['key'], $this->_oauth['secret'], $this->_access, $method, $this->_oauth['algorithm']);
    }
    $str .= $append === false ? '' : $append;

    return $str;
}

private function _connect($host = self::HOST, $port = self::PORT, $ssl = false)
{
    $connect = $ssl === false ? 'tcp' : 'ssl';
    $opts = array(self::SCHEME=>array('method'=>self::METHOD, 'header'=>$this->_build_header()));
    $context = stream_context_create($opts);
    $handle = stream_socket_client($connect.'://'.$host.':'.$port, $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context);
    
    return $handle;
}

private function _read($handle)
{
    $gotStatus = false;
    $response = '';
    $resparray = array();
    while(($line = fgets($handle)) !== false && !$this->_timedout($handle))
    {
        $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
        if($gotStatus)
        {
            $response .= $line;
            array_push($resparray, $line);
            if(rtrim($line) === '')break;
        }
    }
    
    //Check the status if it's not 200 OK log the error and return false.
    $matches = explode(' ', $resparray[0]);
    
    if(!$gotStatus || $matches[1] != '200')
    {
        error_log('YouTube library received bad response: '.$response);
        if(!self::DEBUG)return false;
        else return $response;
    }
    //Get the chunk size
    $chunk = '';
    $line = fgets($handle);
    $chunksize = rtrim($line);
    if(ctype_xdigit($chunksize))$chunksize = hexdec($chunksize);
    else $chunksize = 0;

    while($chunksize > 0 && !$this->_timedout($handle))
    {
        $width = ftell($handle) + $chunksize;
        while(!feof($handle) && $line !== false && strlen(trim($line)) > 0 && !$this->_timedout($handle))
        {
            $chunk .= $line;
            $position = ftell($handle);
            if($position >= $width) break;
            $line = fread($handle, $width - $position);
        }
        $line = fgets($handle);
        $response .= $chunk.$line;

        $chunksize = rtrim($line);
        if(ctype_xdigit($chunksize))$chunksize = hexdec($chunksize);
        else $chunksize = 0;
    }
    preg_match('/\<\?xml.*\r\n/', $response, $matches);
    
    return $matches[0];
}

private function _write($handle, $request)
{
    if(self::DEBUG)error_log($request);
    fwrite($handle, $request);
    return $request;
}

private function _timedout($handle)
{
    if($handle)
    {
        $info = stream_get_meta_data($handle);
        return $info['timed_out'];
    }
    return false;
}

private function _execute_request($uri)
{
    $request = self::METHOD." {$uri} HTTP/".self::HTTP_1.self::LINE_END;

    $url = self::URI_BASE.substr($uri, 1);

    $fullrequest = $this->_build_header($url, $request, self::LINE_END);

    $handle = $this->_connect();
    $this->_write($handle, $fullrequest);
    $output = $this->_read($handle);

    fclose($handle);
    $handle = null;

    return $output;
}

/**
 * Retrieves a specific video entry.
 *
 * @param $videoId The ID of the video to retrieve.
 * @param $fullEntry (optional) Retrieve the full metadata for the entry.
 *         Only possible if entry belongs to currently authenticated user.
 * @return the xml response from youtube
 */
public function getVideoEntry($videoId, $fullEntry = false)
{
    if($fullEntry)return $this->_execute_request ("/{$this->_uris['USER_URI']}/default/uploads/{$videoId}");
    else return $this->_execute_request ("/{$this->_uris['VIDEO_URI']}/{$videoId}");
}

/**
 * Retrieves a feed of videos related to the specified video ID.
 *
 * @param string $videoId The videoId of interest
 * @return the xml response from youtube.
 */
public function getRelatedVideoFeed($videoId)
{
    return $this->_execute_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/related");
}

/**
 * Retrieves a feed of video responses related to the specified video ID.
 *
 * @param string $videoId The videoId of interest
 * @return the xml response from youtube.
 */
public function getVideoResponseFeed($videoId)
{
    return $this->_execute_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/responses");
}

/**
 * Retrieves a feed of video comments related to the specified video ID.
 *
 * @param string $videoId The videoId of interest
 * @return the xml response from youtube.
 */
public function getVideoCommentFeed($videoId)
{
    return $this->_execute_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/comments");
}

public function getTopRatedVideoFeed()
{
    return $this->_execute_request("/{$this->_uris['STANDARD_TOP_RATED_URI']}");
}

public function getMostViewedVideoFeed()
{
    return $this->_execute_request("/{$this->_uris['STANDARD_MOST_VIEWED_URI']}");
}

public function getRecentlyFeaturedVideoFeed()
{
    return $this->_execute_request("/{$this->_uris['STANDARD_RECENTLY_FEATURED_URI']}");
}

public function getWatchOnMobileVideoFeed()
{
    return $this->_execute_request("/{$this->_uris['STANDARD_WATCH_ON_MOBILE_URI']}");
}

public function getPlaylistListFeed($user = 'default')
{
    return $this->_execute_request("/{$this->_uris['USER_URI']}/{$user}/playlists");
}

public function getSubscriptionFeed($user = 'default')
{
    return $this->_execute_request("/{$this->_uris['USER_URI']}/{$user}/subscription");
}

public function getContactFeed($user = 'default')
{
    return $this->_execute_request("/{$this->_uris['USER_URI']}/{$user}/contacts");
}

public function getUserUploads($user = 'default')
{
    return $this->_execute_request("/{$this->_uris['USER_URI']}/{$user}/uploads");
}

public function getUserFavorites($user = 'default')
{
    return $this->_execute_request("/{$this->_uris['USER_URI']}/{$user}/favorites");
}

public function getUserProfile&#40;$user = 'default'&#41;
{
    return $this->_execute_request("/{$this->_uris['USER_URI']}/{$user}");
}

public function getActivityForUser($user = 'default')
{
    return $this->_execute_request("/{$this->_uris['ACTIVITY_FEED_URI']}?author={$user}");
}

public function getFriendActivityForCurrentUser()
{
    if($this->_access !== false)return $this->_execute_request("/{$this->_uris['FRIEND_ACTIVITY_FEED_URI']}");
    else return false;
}

public function getInboxFeedForCurrentUser()
{
    if($this->_access !== false)return $this->_execute_request ("/{$this->_uris['INBOX_FEED_URI']}");
    else return false;
}

public function getFormUploadToken($metadata)
{
    if($this->_access !== false)
    {
        $uri = "/{$this->_uris['UPLOAD_TOKEN_REQUEST']}";
        $header = "POST {$uri} HTTP/".self::HTTP_1.self::LINE_END;
        
        $url = self::URI_BASE.substr($uri, 1);
        $encoding = "UTF-8";
        $extra = "Content-Type: application/atom+xml; charset={$encoding}".self::LINE_END;
        $extra .= "GData-Version: 2.0".self::LINE_END;
        mb_internal_encoding($encoding);
        $extra .= "Content-Length: ".mb_strlen($metadata.self::LINE_END).self::LINE_END.self::LINE_END;//If we hit deadlock change to length - 1
        
        $fullrequest = $this->_build_header($url, $header, $extra, 'POST');
        $fullrequest .= $metadata.self::LINE_END;
        
        $handle = $this->_connect();
        $this->_write($handle, $fullrequest);
        $output = $this->_read($handle);
        
        fclose($handle);
        $handle = null;
        
        return $output;
    }
    else return false;
}

} // ./system/application/libraries ?>

[/code]

Clone this wiki locally