{# Vars for auth docs %}

PHP Code Samples

The following code samples, which use the Google APIs Client Library for PHP, are available for the YouTube Data API. You can download these code samples from the php folder of the YouTube APIs code sample repository on GitHub.

Add a channel section

This sample calls the API's channelSections.insert method to create channel sections. The code accepts a number of command line arguments that let you specify the section's type, display style, title, position, and content.

This sample also updates the channel's brandingSettings.channel.showBrowseView property so that the channel displays content in a browse view (rather than a feed view). A channel's sections are only visible if the channel displays content in a browse view.

More information on channel sections is available in the YouTube Help Center.

<?php

/**
 * This sample creates a channel section by :
 *
 * 1. Getting the active user's channel branding settings via "channels.list" method.
 * 2. Updating the active user's channel to show "browse view" via "channel.update" method.
 * 3. Creating a channel section in the active user's channel via "channelSections->insert" method.
 *
 * @author Ibrahim Ulukaya
*/

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists($file = __DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

// Valid section types.
$SECTION_TYPES = array("allPlaylists", "completedEvents", "likedPlaylists",
  "likes", "liveEvents", "multipleChannels", "multiplePlaylists",
  "popularUploads", "recentActivity", "recentPosts", "recentUploads",
  "singlePlaylist", "upcomingEvents");

// Valid section styles.
$SECTION_STYLES = array("horizontalRow", "verticalList");

// Replace with section title of your choice.
$SECTION_TITLE = 'YOUR_SECTION_TITLE';

// The section's position on the channel page. This property uses a 0-based index.
// If you do not specify a value for this property when inserting a channel section,
// the default behavior is to display the new section last.
$SECTION_POSITION = 0;

// A list of playlist IDs that will be featured in a channel section.
$PLAYLISTS = '';

// A list of channel IDs that will be  featured in a channel section.
$CHANNELS = '';

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  try {

    /*
     * Before channel shelves will appear on your channel's web page, browse
     * view needs to be enabled. If you know that your channel already has
     * it enabled, or if you want to add a number of sections before enabling it,
     * you can skip the call to enable_browse_view().
     */

    // Call the YouTube Data API's channels.list method to retrieve your channel.
    $listResponse = $youtube->channels->listChannels('brandingSettings', array('mine' => true));
    $channel = $listResponse['items'][0];
    $channel['brandingSettings']['channel']['showBrowseView'] = true;

    // Call the YouTube Data API's channels.update method to update your channel.
    $updateResponse = $youtube->channels->update('brandingSettings', $channel);

    // Create a channel section snippet object with type, style, title and position.
    $channelSectionSnippet = new Google_Service_YouTube_ChannelSectionSnippet();
    $channelSectionSnippet->setType($SECTION_TYPES[0]);
    $channelSectionSnippet->setStyle($SECTION_STYLES[0]);
    $channelSectionSnippet->setTitle($SECTION_TITLE);
    $channelSectionSnippet->setPosition($SECTION_POSITION);

    // Create a channel section contentDetails object with channels and playlists.
    $channelSectionContentDetails = new Google_Service_YouTube_ChannelSectionContentDetails();
    $channelSectionContentDetails->setChannels($CHANNELS);
    $channelSectionContentDetails->setPlaylists($PLAYLISTS);

    // Create a channel section with snippet and contentDetails.
    $channelSection = new Google_Service_YouTube_ChannelSection();
    $channelSection->setSnippet($channelSectionSnippet);
    $channelSection->setContentDetails($channelSectionContentDetails);

    // Call the YouTube Data API's channelSections.insert method to create a channel section.
    $insertResponse = $youtube->channelSections->insert('snippet,contentDetails', $channelSection);

    $htmlBody = "<h2>Section Created</h2><ul>";
    $htmlBody .= sprintf('<li>%s "%s"</li>',
        $insertResponse['id'], $insertResponse['snippet']['title']);
    $htmlBody .= '</ul>';

    $htmlBody .= "<h3>with channels</h3><ul>";
    foreach ($insertResponse['contentDetails']['channels'] as $channel) {
      $channels .= sprintf('<li>%s</li>', $channel);
    }
    $htmlBody .= '</ul>';

    $htmlBody .= "<h3>with playlists</h3><ul>";
    foreach ($insertResponse['contentDetails']['playlists'] as $playlist) {
      $channels .= sprintf('<li>%s</li>', $playlist);
    }
    $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody = sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody = sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
 }
    ?>

    <!doctype html>
    <html>
    <head>
    <title>Section Created</title>
    </head>
    <body>
      <?=$htmlBody?>
    </body>
    </html>

Add a channel subscription

This sample calls the API's subscriptions.insert method to add a subscription to a specified channel.

<?php

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  try {
    // This code subscribes the authenticated user to the specified channel.

    // Identify the resource being subscribed to by specifying its channel ID
    // and kind.
    $resourceId = new Google_Service_YouTube_ResourceId();
    $resourceId->setChannelId('UCtVd0c0tGXuTSbU5d8cSBUg');
    $resourceId->setKind('youtube#channel');

    // Create a snippet object and set its resource ID.
    $subscriptionSnippet = new Google_Service_YouTube_SubscriptionSnippet();
    $subscriptionSnippet->setResourceId($resourceId);

    // Create a subscription request that contains the snippet object.
    $subscription = new Google_Service_YouTube_Subscription();
    $subscription->setSnippet($subscriptionSnippet);

    // Execute the request and return an object containing information
    // about the new subscription.
    $subscriptionResponse = $youtube->subscriptions->insert('id,snippet',
        $subscription, array());

    $htmlBody .= "<h3>Subscription</h3><ul>";
    $htmlBody .= sprintf('<li>%s (%s)</li>',
        $subscriptionResponse['snippet']['title'],
        $subscriptionResponse['id']);
    $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user has not authorized the application, start the OAuth 2.0 flow.
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>Returned Subscription</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Create a playlist

This sample calls the API's playlists.insert method to create a private playlist owned by the channel authorizing the request.

<?php

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  try {
    // This code creates a new, private playlist in the authorized user's
    // channel and adds a video to the playlist.

    // 1. Create the snippet for the playlist. Set its title and description.
    $playlistSnippet = new Google_Service_YouTube_PlaylistSnippet();
    $playlistSnippet->setTitle('Test Playlist  ' . date("Y-m-d H:i:s"));
    $playlistSnippet->setDescription('A private playlist created with the YouTube API v3');

    // 2. Define the playlist's status.
    $playlistStatus = new Google_Service_YouTube_PlaylistStatus();
    $playlistStatus->setPrivacyStatus('private');

    // 3. Define a playlist resource and associate the snippet and status
    // defined above with that resource.
    $youTubePlaylist = new Google_Service_YouTube_Playlist();
    $youTubePlaylist->setSnippet($playlistSnippet);
    $youTubePlaylist->setStatus($playlistStatus);

    // 4. Call the playlists.insert method to create the playlist. The API
    // response will contain information about the new playlist.
    $playlistResponse = $youtube->playlists->insert('snippet,status',
        $youTubePlaylist, array());
    $playlistId = $playlistResponse['id'];

    // 5. Add a video to the playlist. First, define the resource being added
    // to the playlist by setting its video ID and kind.
    $resourceId = new Google_Service_YouTube_ResourceId();
    $resourceId->setVideoId('SZj6rAYkYOg');
    $resourceId->setKind('youtube#video');

    // Then define a snippet for the playlist item. Set the playlist item's
    // title if you want to display a different value than the title of the
    // video being added. Add the resource ID and the playlist ID retrieved
    // in step 4 to the snippet as well.
    $playlistItemSnippet = new Google_Service_YouTube_PlaylistItemSnippet();
    $playlistItemSnippet->setTitle('First video in the test playlist');
    $playlistItemSnippet->setPlaylistId($playlistId);
    $playlistItemSnippet->setResourceId($resourceId);

    // Finally, create a playlistItem resource and add the snippet to the
    // resource, then call the playlistItems.insert method to add the playlist
    // item.
    $playlistItem = new Google_Service_YouTube_PlaylistItem();
    $playlistItem->setSnippet($playlistItemSnippet);
    $playlistItemResponse = $youtube->playlistItems->insert(
        'snippet,contentDetails', $playlistItem, array());

    $htmlBody .= "<h3>New Playlist</h3><ul>";
    $htmlBody .= sprintf('<li>%s (%s)</li>',
        $playlistResponse['snippet']['title'],
        $playlistResponse['id']);
    $htmlBody .= '</ul>';

    $htmlBody .= "<h3>New PlaylistItem</h3><ul>";
    $htmlBody .= sprintf('<li>%s (%s)</li>',
        $playlistItemResponse['snippet']['title'],
        $playlistItemResponse['id']);
    $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody = sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody = sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>New Playlist</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Create and manage YouTube video caption tracks

This sample demonstrates how to use the following API methods to create and manage YouTube video caption tracks:

  • It calls the captions.insert method with the isDraft parameter set to true to upload a caption track in draft status.
  • It calls the captions.list method with the videoId parameter to retrieve video caption tracks.
  • It calls the captions.update method with the caption in the request body to update a caption track.
  • It calls the captions.download method to download the caption track.
  • It calls the captions.delete method to delete the caption track, using the id parameter to identify the caption track.

<?php

/**
 * This sample creates and manages caption tracks by:
 *
 * 1. Uploading a caption track for a video via "captions.insert" method.
 * 2. Getting the caption tracks for a video via "captions.list" method.
 * 3. Updating an existing caption track via "captions.update" method.
 * 4. Download a caption track via "captions.download" method.
 * 5. Deleting an existing caption track via "captions.delete" method.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

$htmlBody = <<<END
<form method="POST" enctype="multipart/form-data">
  <div>
    Action:
    <select id="action" name="action">
      <option value="upload">Upload - Fill in: video ID, caption track name, language and file</option>
      <option value="list">List - Fill in: video ID</option>
      <option value="update">Update - Fill in: caption track ID, (optional - caption track file)</option>
      <option value="download">Download - Fill in: caption track ID</option>
      <option value="delete">Delete - Fill in: caption track ID</option>
      <option value="all">All - Fill in: video ID, caption track name, language and file</option>
    </select>
  </div>
  <br>
  <div>
    Video ID: <input type="text" id="videoId" name="videoId" placeholder="Enter Video ID">
  </div>
  <br>
  <div>
    Caption Track Name: <input type="text" id="captionName" name="captionName" placeholder="Enter Caption Track Name">
  </div>
  <br>
  <div>
    Caption Track Language: <input type="text" id="captionLanguage" name="captionLanguage" placeholder="Enter Caption Track Language">
  </div>
  <br>
  <div>
    File: <input type="file" id ="captionFile" name="captionFile" accept="*/*">
  </div>
  <br>
  <div>
    Caption Track Id: <input type="text" id="captionId" name="captionId" placeholder="Enter Caption Track ID">
  </div>
  <br>
  <input type="submit" value="GO!">
</form>
END;

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account and requires requests to use an SSL connection.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube.force-ssl');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  // This code executes if the user enters an action in the form
  // and submits the form. Otherwise, the page displays the form above.
  if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $videoId = isset($_POST['videoId']) ? $_POST['videoId'] : null;
    $captionFile = isset($_FILES['captionFile']) ? $_FILES['captionFile']['tmp_name'] : null;
    $captionName = isset($_POST['captionName']) ? $_POST['captionName'] : null;
    $captionLanguage = isset($_POST['captionLanguage']) ? $_POST['captionLanguage'] : null;
    $captionId = isset($_POST['captionId']) ? $_POST['captionId'] : null;
    try {
      switch ($_POST['action']) {
        case 'upload':
          uploadCaption($youtube, $client, $videoId, $captionFile,
              $captionName, $captionLanguage, $htmlBody);
          break;
        case 'list':
          $captions = listCaptions($youtube, $videoId, $htmlBody);
          break;
        case 'update':
          updateCaption($youtube, $client, $captionId, $htmlBody, $captionFile);
          break;
        case 'download':
          downloadCaption($youtube, $captionId, $htmlBody);
          break;
        case 'delete':
          deleteCaption($youtube, $captionId, $htmlBody);
          break;
        default:
          # All the available methods are used in sequence just for the sake of an example.
          uploadCaption($youtube, $client, $videoId, $captionFile,
              $captionName, $captionLanguage, $htmlBody);

          $captions = listCaptions($youtube, $videoId, $htmlBody);

          if (empty($captions)) {
            $htmlBody .= "<h3>Can't get video caption tracks.</h3>";
          } else {
            $firstCaptionId = $captions[0]['id'];
            updateCaption($youtube, $client, $firstCaptionId, $htmlBody, null);
            downloadCaption($youtube, $firstCaptionId, $htmlBody);
            deleteCaption($youtube, $firstCaptionId, $htmlBody);
        }
      }
    } catch (Google_Service_Exception $e) {
      $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    } catch (Google_Exception $e) {
      $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    }
  }
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}

/**
 * Uploads a caption track in draft status that matches the API request parameters.
 * (captions.insert)
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param Google_Client $client Google client.
 * @param $videoId the YouTube video ID of the video for which the API should
 *  return caption tracks.
 * @param $captionLanguage language of the caption track.
 * @param $captionName name of the caption track.
 * @param $captionFile caption track binary file.
 * @param $htmlBody html body.
 */
function uploadCaption(Google_Service_YouTube $youtube, Google_Client $client, $videoId,
    $captionFile, $captionName, $captionLanguage, &$htmlBody) {
    # Insert a video caption.
    # Create a caption snippet with video id, language, name and draft status.
    $captionSnippet = new Google_Service_YouTube_CaptionSnippet();
    $captionSnippet->setVideoId($videoId);
    $captionSnippet->setLanguage($captionLanguage);
    $captionSnippet->setName($captionName);

    # Create a caption with snippet.
    $caption = new Google_Service_YouTube_Caption();
    $caption->setSnippet($captionSnippet);

    // Specify the size of each chunk of data, in bytes. Set a higher value for
    // reliable connection as fewer chunks lead to faster uploads. Set a lower
    // value for better recovery on less reliable connections.
    $chunkSizeBytes = 1 * 1024 * 1024;

    // Setting the defer flag to true tells the client to return a request which can be called
    // with ->execute(); instead of making the API call immediately.
    $client->setDefer(true);

    // Create a request for the API's captions.insert method to create and upload a caption.
    $insertRequest = $youtube->captions->insert("snippet", $caption);

    // Create a MediaFileUpload object for resumable uploads.
    $media = new Google_Http_MediaFileUpload(
        $client,
        $insertRequest,
        '*/*',
        null,
        true,
        $chunkSizeBytes
    );
    $media->setFileSize(filesize($captionFile));


    // Read the caption file and upload it chunk by chunk.
    $status = false;
    $handle = fopen($captionFile, "rb");
    while (!$status && !feof($handle)) {
      $chunk = fread($handle, $chunkSizeBytes);
      $status = $media->nextChunk($chunk);
    }

    fclose($handle);

    // If you want to make other calls after the file upload, set setDefer back to false
    $client->setDefer(false);

    $htmlBody .= "<h2>Inserted video caption track for</h2><ul>";
    $captionSnippet = $status['snippet'];
    $htmlBody .= sprintf('<li>%s(%s) in %s language, %s status.</li>',
        $captionSnippet['name'], $status['id'], $captionSnippet['language'],
        $captionSnippet['status']);
    $htmlBody .= '</ul>';
}

/**
 * Returns a list of caption tracks. (captions.listCaptions)
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $videoId The videoId parameter instructs the API to return the
 * caption tracks for the video specified by the video id.
 * @param $htmlBody - html body.
 */
function listCaptions(Google_Service_YouTube $youtube, $videoId, &$htmlBody) {
  // Call the YouTube Data API's captions.list method to retrieve video caption tracks.
  $captions = $youtube->captions->listCaptions("snippet", $videoId);

  $htmlBody .= "<h3>Video Caption Tracks</h3><ul>";
  foreach ($captions as $caption) {
    $htmlBody .= sprintf('<li>%s(%s) in %s language</li>', $caption['snippet']['name'],
        $caption['id'],  $caption['snippet']['language']);
  }
  $htmlBody .= '</ul>';

  return $captions;
}

/**
 * Updates a caption track's draft status to publish it.
 * Updates the track with a new binary file as well if it is present.  (captions.update)
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param Google_Client $client Google client.
 * @param string $captionId The id parameter specifies the caption ID for the resource
 * that is being updated. In a caption resource, the id property specifies the
 * caption track's ID.
 * @param $htmlBody - html body.
 * @param $captionFile caption track binary file.
 */
function updateCaption(Google_Service_YouTube $youtube, Google_Client $client,
    $captionId, &$htmlBody, $captionFile) {
    // Modify caption's isDraft property to unpublish a caption track.
    $updateCaptionSnippet = new Google_Service_YouTube_CaptionSnippet();
    $updateCaptionSnippet->setIsDraft(true);

    # Create a caption with snippet.
    $updateCaption = new Google_Service_YouTube_Caption();
    $updateCaption->setSnippet($updateCaptionSnippet);
    $updateCaption->setId($captionId);

    if ($captionFile == '')
    {
      // Call the YouTube Data API's captions.update method to update an existing caption track.
      $captionUpdateResponse = $youtube->captions->update("snippet", $updateCaption);

      $htmlBody .= "<h2>Updated caption track</h2><ul>";
      $htmlBody .= sprintf('<li>%s(%s) draft status: %s</li>',
          $captionUpdateResponse['snippet']['name'],
      $captionUpdateResponse['id'],  $captionUpdateResponse['snippet']['isDraft']);
      $htmlBody .= '</ul>';
    } else {
      // Specify the size of each chunk of data, in bytes. Set a higher value for
      // reliable connection as fewer chunks lead to faster uploads. Set a lower
      // value for better recovery on less reliable connections.
      $chunkSizeBytes = 1 * 1024 * 1024;

      // Setting the defer flag to true tells the client to return a request which can be called
      // with ->execute(); instead of making the API call immediately.
      $client->setDefer(true);

      // Create a request for the YouTube Data API's captions.update method to update
      // an existing caption track.
      $captionUpdateRequest = $youtube->captions->update("snippet", $updateCaption);

      // Create a MediaFileUpload object for resumable uploads.
      $media = new Google_Http_MediaFileUpload(
          $client,
          $captionUpdateRequest,
          '*/*',
          null,
          true,
          $chunkSizeBytes
      );
      $media->setFileSize(filesize($captionFile));

      // Read the caption file and upload it chunk by chunk.
      $status = false;
      $handle = fopen($captionFile, "rb");
      while (!$status && !feof($handle)) {
        $chunk = fread($handle, $chunkSizeBytes);
        $status = $media->nextChunk($chunk);
      }

      fclose($handle);

      // If you want to make other calls after the file upload, set setDefer back to false
      $client->setDefer(false);

      $htmlBody .= "<h2>Updated caption track</h2><ul>";
      $htmlBody .= sprintf('<li>%s(%s) draft status: %s and updated the track with
          the new uploaded file.</li>',
          $status['snippet']['name'], $status['id'],  $status['snippet']['isDraft']);
      $htmlBody .= '</ul>';
    }
}

/**
 * Downloads a caption track for a YouTube video. (captions.download)
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $captionId The id parameter specifies the caption ID for the resource
 * that is being downloaded. In a caption resource, the id property specifies the
 * caption track's ID.
 * @param $htmlBody - html body.
 */
function downloadCaption(Google_Service_YouTube $youtube, $captionId, &$htmlBody) {
    // Call the YouTube Data API's captions.download method to download an existing caption.
    $captionResouce = $youtube->captions->download($captionId, array(
        'tfmt' => "srt",
        'alt' => "media"
    ));

    $htmlBody .= "<h2>Downloaded caption track</h2><ul>";
    $htmlBody .= sprintf('<li>%s</li>',
      $captionResouce);
    $htmlBody .= '</ul>';
}

/**
 * Deletes a caption track for a YouTube video. (captions.delete)
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $captionId The id parameter specifies the caption ID for the resource
 * that is being deleted. In a caption resource, the id property specifies the
 * caption track's ID.
 * @param $htmlBody - html body.
 */
function deleteCaption(Google_Service_YouTube $youtube, $captionId, &$htmlBody) {
    // Call the YouTube Data API's captions.delete method to delete a caption.
    $youtube->captions->delete($captionId);

    $htmlBody .= "<h2>Deleted caption track</h2><ul>";
    $htmlBody .= sprintf('<li>%s</li>',$captionId);
    $htmlBody .= '</ul>';
}
?>

<!doctype html>
<html>
<head>
<title>Create and manage video caption tracks</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Create and manage comment threads

This sample demonstrates how to use the following API methods to create and manage top-level comments:

  • It calls the commentThreads.insert method once with the channelId parameter to create a channel comment and once with the videoId parameter to create a video comment.
  • It calls the commentThreads.list method once with the channelId parameter to retrieve channel comments and once with the videoId parameter to retrieve video comments.
  • It calls the commentThreads.update method once to update a video comment and then again to update a channel comment. In each case, the request body contains the comment resource being updated.

<?php

/**
 * This sample creates and manages top-level comments by:
 *
 * 1. Creating a top-level comments for a video and a channel via "commentThreads.insert" method.
 * 2. Getting the top-level comments for a video and a channel via "commentThreads.list" method.
 * 3. Updating an existing comments via "commentThreads.update" method.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();


/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

/* You can replace $VIDEO_ID with one of your videos' id, channel id with your channel's id,
 * and text with the comment you want to be added.
 */
$VIDEO_ID = 'REPLACE_ME';
$CHANNEL_ID = 'REPLACE_ME';
$TEXT = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account and requires requests to use an SSL connection.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube.force-ssl');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  try {
    # All the available methods are used in sequence just for the sake of an example.

    # Insert channel comment by omitting videoId.
    # Create a comment snippet with text.
    $commentSnippet = new Google_Service_YouTube_CommentSnippet();
    $commentSnippet->setTextOriginal($TEXT);

    # Create a top-level comment with snippet.
    $topLevelComment = new Google_Service_YouTube_Comment();
    $topLevelComment->setSnippet($commentSnippet);

    # Create a comment thread snippet with channelId and top-level comment.
    $commentThreadSnippet = new Google_Service_YouTube_CommentThreadSnippet();
    $commentThreadSnippet->setChannelId($CHANNEL_ID);
    $commentThreadSnippet->setTopLevelComment($topLevelComment);

    # Create a comment thread with snippet.
    $commentThread = new Google_Service_YouTube_CommentThread();
    $commentThread->setSnippet($commentThreadSnippet);

    // Call the YouTube Data API's commentThreads.insert method to create a comment.
    $channelCommentInsertResponse = $youtube->commentThreads->insert('snippet', $commentThread);


    # Insert video comment
    $commentThreadSnippet->setVideoId($VIDEO_ID);
    // Call the YouTube Data API's commentThreads.insert method to create a comment.
    $videoCommentInsertResponse = $youtube->commentThreads->insert('snippet', $commentThread);

    // Call the YouTube Data API's commentThreads.list method to retrieve video comment threads.
    $videoComments = $youtube->commentThreads->listCommentThreads('snippet', array(
        'videoId' => $VIDEO_ID,
        'textFormat' => 'plainText',
    ));

    if (empty($videoComments)) {
      $htmlBody .= "<h3>Can\'t get video comments.</h3>";
    } else {
      $videoComments[0]['snippet']['topLevelComment']['snippet']['textOriginal'] = 'updated';
      $videoCommentUpdateResponse = $youtube->commentThreads->update('snippet', $videoComments[0]);
    }

    // Call the YouTube Data API's commentThreads.list method to retrieve channel comment threads.
    $channelComments = $youtube->commentThreads->listCommentThreads('snippet', array(
        'channelId' => $CHANNEL_ID,
        'textFormat' => 'plainText',
    ));

    if (empty($channelComments)) {
      $htmlBody .= "<h3>Can\'t get channel comments.</h3>";
    } else {
      $channelComments[0]['snippet']['topLevelComment']['snippet']['textOriginal'] = 'updated';
      $channelCommentUpdateResponse = $youtube->commentThreads->update('snippet', $channelComments[0]);
    }

    $htmlBody .= "<h2>Inserted channel comment for</h2><ul>";
    $comment = $channelCommentInsertResponse['snippet']['topLevelComment'];
    $htmlBody .= sprintf('<li>%s: "%s"</li>',
        $comment['snippet']['authorDisplayName'], $comment['snippet']['textDisplay']);
    $htmlBody .= '</ul>';

    $htmlBody .= "<h2>Inserted video comment for</h2><ul>";
    $comment = $videoCommentInsertResponse['snippet']['topLevelComment'];
    $htmlBody .= sprintf('<li>%s: "%s"</li>',
        $comment['snippet']['authorDisplayName'], $comment['snippet']['textDisplay']);
    $htmlBody .= '</ul>';

    $htmlBody .= "<h3>Video Comments</h3><ul>";
    foreach ($videoComments as $comment) {
      $htmlBody .= sprintf('<li>%s</li>', $comment['snippet']['topLevelComment']['snippet']['textOriginal']);
    }
    $htmlBody .= '</ul>';

    $htmlBody .= "<h3>Channel Comments</h3><ul>";
    foreach ($channelComments as $comment) {
      $htmlBody .= sprintf('<li>%s</li>', $comment['snippet']['topLevelComment']['snippet']['textOriginal']);
    }
    $htmlBody .= '</ul>';

    $htmlBody .= "<h2>Updated channel comment for</h2><ul>";
    $comment = $videoCommentUpdateResponse['snippet']['topLevelComment'];
    $htmlBody .= sprintf('<li>%s: "%s"</li>',
        $comment['snippet']['authorDisplayName'], $comment['snippet']['textDisplay']);
    $htmlBody .= '</ul>';

    $htmlBody .= "<h2>Updated video comment for</h2><ul>";
    $comment = $channelCommentUpdateResponse['snippet']['topLevelComment'];
    $htmlBody .= sprintf('<li>%s: "%s"</li>',
        $comment['snippet']['authorDisplayName'], $comment['snippet']['textDisplay']);
    $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>Insert, list and update top-level comments</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Create and manage comments

The following code sample demonstrates how to use the following API methods to create and manage comments:

  • It calls the commentThreads.list method with the videoId parameter set to retrieve comments for a video.
  • It calls the comments.insert method with the parentId parameter set to reply to an existing comment.
  • It calls the comments.list method with the parentId parameter to retrieve the comments in the thread.
  • It calls the comments.update method with comment in the request body to update a comment.
  • It calls the comments.setModerationStatus method to set the moderation status of the comment, the comments.markAsSpam method to mark the comment as spam, and the comments.delete method to delete the comment, using the id parameter to identify the comment.

<?php

/**
 * This sample creates and manages comments by:
 *
 * 1. Getting the top-level comments for a video via "commentThreads.list" method.
 * 2. Replying to a comment thread via "comments.insert" method.
 * 3. Getting comment replies via "comments.list" method.
 * 4. Updating an existing comment via "comments.update" method.
 * 5. Sets moderation status of an existing comment via "comments.setModerationStatus" method.
 * 6. Marking a comment as spam via "comments.markAsSpam" method.
 * 7. Deleting an existing comment via "comments.delete" method.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();


/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

/* You can replace $VIDEO_ID with one of your videos' id, and text with the
 *  comment you want to be added.
 */
$VIDEO_ID = 'REPLACE_ME';
$TEXT = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account and requires requests to use an SSL connection.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube.force-ssl');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  try {
    # All the available methods are used in sequence just for the sake of an example.

    // Call the YouTube Data API's commentThreads.list method to retrieve video comment threads.
    $videoCommentThreads = $youtube->commentThreads->listCommentThreads('snippet', array(
    'videoId' => $VIDEO_ID,
    'textFormat' => 'plainText',
    ));

    $parentId = $videoCommentThreads[0]['id'];

    # Create a comment snippet with text.
    $commentSnippet = new Google_Service_YouTube_CommentSnippet();
    $commentSnippet->setTextOriginal($TEXT);
    $commentSnippet->setParentId($parentId);

    # Create a comment with snippet.
    $comment = new Google_Service_YouTube_Comment();
    $comment->setSnippet($commentSnippet);

    # Call the YouTube Data API's comments.insert method to reply to a comment.
    # (If the intention is to create a new top-level comment, commentThreads.insert
    # method should be used instead.)
    $commentInsertResponse = $youtube->comments->insert('snippet', $comment);


    // Call the YouTube Data API's comments.list method to retrieve existing comment replies.
    $videoComments = $youtube->comments->listComments('snippet', array(
        'parentId' => $parentId,
        'textFormat' => 'plainText',
    ));

    if (empty($videoComments)) {
      $htmlBody .= "<h3>Can\'t get video comments.</h3>";
    } else {
      $videoComments[0]['snippet']['textOriginal'] = 'updated';

      // Call the YouTube Data API's comments.update method to update an existing comment.
      $videoCommentUpdateResponse = $youtube->comments->update('snippet', $videoComments[0]);

      // Call the YouTube Data API's comments.setModerationStatus method to set moderation
      // status of an existing comment.
      $youtube->comments->setModerationStatus($videoComments[0]['id'], 'published');

      // Call the YouTube Data API's comments.markAsSpam method to mark an existing comment as spam.
      $youtube->comments->markAsSpam($videoComments[0]['id']);

      // Call the YouTube Data API's comments.delete method to delete an existing comment.
      $youtube->comments->delete($videoComments[0]['id']);
    }

    $htmlBody .= "<h3>Video Comment Replies</h3><ul>";
    foreach ($videoComments as $comment) {
      $htmlBody .= sprintf('<li>%s: "%s"</li>', $comment['snippet']['authorDisplayName'],
          $comment['snippet']['textOriginal']);
    }
    $htmlBody .= '</ul>';

    $htmlBody .= "<h2>Replied to a comment for</h2><ul>";
    $htmlBody .= sprintf('<li>%s: "%s"</li>',
        $commentInsertResponse['snippet']['authorDisplayName'],
        $commentInsertResponse['snippet']['textDisplay']);
    $htmlBody .= '</ul>';

    $htmlBody .= "<h2>Updated comment for</h2><ul>";
    $htmlBody .= sprintf('<li>%s: "%s"</li>',
        $videoCommentUpdateResponse['snippet']['authorDisplayName'],
        $videoCommentUpdateResponse['snippet']['textDisplay']);
    $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
    <h3>Authorization Required</h3>
    <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>Insert, list, update, moderate, mark and delete comments.</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Retrieve my uploads

This sample calls the API's playlistItems.list method to retrieve a list of videos uploaded to the channel associated with the request. The code also calls the channels.list method with the mine parameter set to true to retrieve the playlist ID that identifies the channel's uploaded videos.

<?php

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
  FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  try {
    // Call the channels.list method to retrieve information about the
    // currently authenticated user's channel.
    $channelsResponse = $youtube->channels->listChannels('contentDetails', array(
      'mine' => 'true',
    ));

    $htmlBody = '';
    foreach ($channelsResponse['items'] as $channel) {
      // Extract the unique playlist ID that identifies the list of videos
      // uploaded to the channel, and then call the playlistItems.list method
      // to retrieve that list.
      $uploadsListId = $channel['contentDetails']['relatedPlaylists']['uploads'];

      $playlistItemsResponse = $youtube->playlistItems->listPlaylistItems('snippet', array(
        'playlistId' => $uploadsListId,
        'maxResults' => 50
      ));

      $htmlBody .= "<h3>Videos in list $uploadsListId</h3><ul>";
      foreach ($playlistItemsResponse['items'] as $playlistItem) {
        $htmlBody .= sprintf('<li>%s (%s)</li>', $playlistItem['snippet']['title'],
          $playlistItem['snippet']['resourceId']['videoId']);
      }
      $htmlBody .= '</ul>';
    }
  } catch (Google_Service_Exception $e) {
    $htmlBody = sprintf('<p>A service error occurred: <code>%s</code></p>',
      htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody = sprintf('<p>An client error occurred: <code>%s</code></p>',
      htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
  <head>
    <title>My Uploads</title>
  </head>
  <body>
    <?=$htmlBody?>
  </body>
</html>

Search by keyword

This sample calls the API's search.list method to retrieve search results associated with a particular keyword.

<?php

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';

$htmlBody = <<<END
<form method="GET">
  <div>
    Search Term: <input type="search" id="q" name="q" placeholder="Enter Search Term">
  </div>
  <div>
    Max Results: <input type="number" id="maxResults" name="maxResults" min="1" max="50" step="1" value="25">
  </div>
  <input type="submit" value="Search">
</form>
END;

// This code will execute if the user entered a search query in the form
// and submitted the form. Otherwise, the page displays the form above.
if (isset($_GET['q']) && isset($_GET['maxResults'])) {
  /*
   * Set $DEVELOPER_KEY to the "API key" value from the "Access" tab of the
   * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
   * Please ensure that you have enabled the YouTube Data API for your project.
   */
  $DEVELOPER_KEY = 'REPLACE_ME';

  $client = new Google_Client();
  $client->setDeveloperKey($DEVELOPER_KEY);

  // Define an object that will be used to make all API requests.
  $youtube = new Google_Service_YouTube($client);

  $htmlBody = '';
  try {

    // Call the search.list method to retrieve results matching the specified
    // query term.
    $searchResponse = $youtube->search->listSearch('id,snippet', array(
      'q' => $_GET['q'],
      'maxResults' => $_GET['maxResults'],
    ));

    $videos = '';
    $channels = '';
    $playlists = '';

    // Add each result to the appropriate list, and then display the lists of
    // matching videos, channels, and playlists.
    foreach ($searchResponse['items'] as $searchResult) {
      switch ($searchResult['id']['kind']) {
        case 'youtube#video':
          $videos .= sprintf('<li>%s (%s)</li>',
              $searchResult['snippet']['title'], $searchResult['id']['videoId']);
          break;
        case 'youtube#channel':
          $channels .= sprintf('<li>%s (%s)</li>',
              $searchResult['snippet']['title'], $searchResult['id']['channelId']);
          break;
        case 'youtube#playlist':
          $playlists .= sprintf('<li>%s (%s)</li>',
              $searchResult['snippet']['title'], $searchResult['id']['playlistId']);
          break;
      }
    }

    $htmlBody .= <<<END
    <h3>Videos</h3>
    <ul>$videos</ul>
    <h3>Channels</h3>
    <ul>$channels</ul>
    <h3>Playlists</h3>
    <ul>$playlists</ul>
END;
  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
      htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
      htmlspecialchars($e->getMessage()));
  }
}
?>

<!doctype html>
<html>
  <head>
    <title>YouTube Search</title>
  </head>
  <body>
    <?=$htmlBody?>
  </body>
</html>

Search by location

This sample calls the API's search.list method with the type, q, location and locationRadius parameters to retrieve search results matching the provided keyword within the radius centered at a particular location. Using the video IDs from the search result, the sample calls the API's videos.list method to retrieve location details of each video.

<?php

/**
 * This sample lists videos that are associated with a particular keyword and are in the radius of
 *   particular geographic coordinates by:
 *
 * 1. Searching videos with "youtube.search.list" method and setting "type", "q", "location" and
 *   "locationRadius" parameters.
 * 2. Retrieving location details for each video with "youtube.videos.list" method and setting
 *   "id" parameter to comma separated list of video IDs in search result.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';

$htmlBody = <<<END
<form method="GET">
  <div>
    Search Term: <input type="search" id="q" name="q" placeholder="Enter Search Term">
  </div>
  <div>
    Location: <input type="text" id="location" name="location" placeholder="37.42307,-122.08427">
  </div>
  <div>
    Location Radius: <input type="text" id="locationRadius" name="locationRadius" placeholder="5km">
  </div>
  <div>
    Max Results: <input type="number" id="maxResults" name="maxResults" min="1" max="50" step="1" value="25">
  </div>
  <input type="submit" value="Search">
</form>
END;

// This code executes if the user enters a search query in the form
// and submits the form. Otherwise, the page displays the form above.
if (isset($_GET['q']) && isset($_GET['maxResults'])) {
  /*
   * Set $DEVELOPER_KEY to the "API key" value from the "Access" tab of the
  * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
  * Please ensure that you have enabled the YouTube Data API for your project.
  */
  $DEVELOPER_KEY = 'REPLACE_ME';

  $client = new Google_Client();
  $client->setDeveloperKey($DEVELOPER_KEY);

  // Define an object that will be used to make all API requests.
  $youtube = new Google_Service_YouTube($client);

  try {
    // Call the search.list method to retrieve results matching the specified
    // query term.
    $searchResponse = $youtube->search->listSearch('id,snippet', array(
        'type' => 'video',
        'q' => $_GET['q'],
        'location' =>  $_GET['location'],
        'locationRadius' =>  $_GET['locationRadius'],
        'maxResults' => $_GET['maxResults'],
    ));

    $videoResults = array();
    # Merge video ids
    foreach ($searchResponse['items'] as $searchResult) {
      array_push($videoResults, $searchResult['id']['videoId']);
    }
    $videoIds = join(',', $videoResults);

    # Call the videos.list method to retrieve location details for each video.
    $videosResponse = $youtube->videos->listVideos('snippet, recordingDetails', array(
    'id' => $videoIds,
    ));

    $videos = '';

    // Display the list of matching videos.
    foreach ($videosResponse['items'] as $videoResult) {
      $videos .= sprintf('<li>%s (%s,%s)</li>',
          $videoResult['snippet']['title'],
          $videoResult['recordingDetails']['location']['latitude'],
          $videoResult['recordingDetails']['location']['longitude']);
    }

    $htmlBody .= <<<END
    <h3>Videos</h3>
    <ul>$videos</ul>
END;
  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }
}
?>

<!doctype html>
<html>
<head>
<title>YouTube Geolocation Search</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Set and retrieve localized channel metadata

This sample demonstrates how to use the following API methods to set and retrieve localized metadata for a channel:

  • It calls the channels.update method to update the default language of a channel's metadata and to add a localized version of this metadata in a selected language. Note that to set the default language for a channel resource, you actually need to update the brandingSettings.channel.defaultLanguage property.
  • It calls the channels.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the channels.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that channel.

<?php

/**
 * This sample sets and retrieves localized metadata for a channel by:
 *
 * 1. Updating language of the default metadata and setting localized metadata
 *   for a channel via "channels.update" method.
 * 2. Getting the localized metadata for a channel in a selected language using the
 *   "channels.list" method and setting the "hl" parameter.
 * 3. Listing the localized metadata for a channel using "channels.list" method and
 *   including "localizations" in the "part" parameter.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

$htmlBody = <<<END
<form method="GET">
  <div>
    Action:
    <select id="action" name="action">
      <option value="set">Set Localization - Fill in: channel ID, default language, language, description</option>
      <option value="get">Get Localization- Fill in: channel ID, language</option>
      <option value="list">List Localizations - Fill in: channel ID, language</option>
    </select>
  </div>
  <br>
  <div>
    Channel ID: <input type="text" id="channelId" name="channelId" placeholder="Enter Channel ID">
  </div>
  <br>
  <div>
    Default Language: <input type="text" id="defaultLanguage" name="defaultLanguage" placeholder="Enter Default Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Language: <input type="text" id="language" name="language" placeholder="Enter Local Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Description: <input type="text" id="description" name="description" placeholder="Enter Description">
  </div>
  <br>
  <input type="submit" value="GO!">
</form>
END;

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  // This code executes if the user enters an action in the form
  // and submits the form. Otherwise, the page displays the form above.
  if (isset($_GET['action'])) {
    $htmlBody = '';
    $resource = $_GET['resource'];
    $channelId = $_GET['channelId'];
    $language = $_GET['language'];
    $defaultLanguage = $_GET['defaultLanguage'];
    $description = $_GET['description'];
    try {
      switch ($_GET['action']) {
        case 'set':
          setChannelLocalization($youtube, $channelId, $defaultLanguage,
              $language, $description, $htmlBody);
          break;
        case 'get':
          getChannelLocalization($youtube, $channelId, $language, $htmlBody);
          break;
        case 'list':
          listChannelLocalizations($youtube, $channelId, $htmlBody);
          break;
      }
    } catch (Google_Service_Exception $e) {
      $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    } catch (Google_Exception $e) {
      $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    }
  }
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}


/**
 * Updates a channel's default language and sets its localized metadata.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $channelId The id parameter specifies the channel ID for the resource
 * that is being updated.
 * @param string $defaultLanguage The language of the channel's default metadata
 * @param string $language The language of the localized metadata
 * @param string $description The localized description to be set
 * @param $htmlBody - html body.
 */
function setChannelLocalization(Google_Service_YouTube $youtube, $channelId, $defaultLanguage,
    $language, $description, &$htmlBody) {
  // Call the YouTube Data API's channels.list method to retrieve channels.
  $channels = $youtube->channels->listChannels("brandingSettings,localizations", array(
      'id' => $channelId
  ));

  // If $channels is empty, the specified channel was not found.
  if (empty($channels)) {
    $htmlBody .= sprintf('<h3>Can\'t find a channel with channel id: %s</h3>', $channelId);
  } else {
    // Since the request specified a channel ID, the response only
    // contains one channel resource.
    $updateChannel = $channels[0];

    // Modify channel's default language and localizations properties.
    // Ensure that a value is set for the resource's snippet.defaultLanguage property.
    // To set the snippet.defaultLanguage property for a channel resource,
    // you actually need to update the brandingSettings.channel.defaultLanguage property.
    $updateChannel['brandingSettings']['channel']['defaultLanguage'] = $defaultLanguage;
    $localizations = $updateChannel['localizations'];

    if (is_null($localizations)) {
      $localizations = array();
    }
    $localizations[$language] = array('description' => $description);
    $updateChannel['localizations'] = $localizations;

    // Call the YouTube Data API's channels.update method to update an existing channel.
    $channelUpdateResponse = $youtube->channels->update("brandingSettings,localizations",
        $updateChannel);

    $htmlBody .= "<h2>Updated channel</h2><ul>";
    $htmlBody .= sprintf('<li>(%s) default language: %s</li>', $channelId,
        $channelUpdateResponse['brandingSettings']['channel']['defaultLanguage']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language,
        $channelUpdateResponse['localizations'][$language]['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns localized metadata for a channel in a selected language.
 * If the localized text is not available in the requested language,
 * this method will return text in the default language.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $channelId The channelId parameter instructs the API to return the
 * localized metadata for the channel specified by the channel id.
 * @param string language The language of the localized metadata.
 * @param $htmlBody - html body.
 */
function getChannelLocalization(Google_Service_YouTube $youtube, $channelId,
    $language, &$htmlBody) {
  // Call the YouTube Data API's channels.list method to retrieve channels.
  $channels = $youtube->channels->listChannels("snippet", array(
      'id' => $channelId,
      'hl' => $language
  ));

  // If $channels is empty, the specified channel was not found.
  if (empty($channels)) {
    $htmlBody .= sprintf('<h3>Can\'t find a channel with channel id: %s</h3>', $channelId);
  } else {
    // Since the request specified a channel ID, the response only
    // contains one channel resource.
    $localized = $channels[0]["snippet"]["localized"];

    $htmlBody .= "<h3>Channel</h3><ul>";
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localized['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns a list of localized metadata for a channel.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $channelId The channelId parameter instructs the API to return the
 * localized metadata for the channel specified by the channel id.
 * @param $htmlBody - html body.
 */
function listChannelLocalizations(Google_Service_YouTube $youtube, $channelId, &$htmlBody) {
  // Call the YouTube Data API's channels.list method to retrieve channels.
  $channels = $youtube->channels->listChannels("snippet,localizations", array(
      'id' => $channelId
  ));

  // If $channels is empty, the specified channel was not found.
  if (empty($channels)) {
    $htmlBody .= sprintf('<h3>Can\'t find a channel with channel id: %s</h3>', $channelId);
  } else {
    // Since the request specified a channel ID, the response only
    // contains one channel resource.
    $localizations = $channels[0]["localizations"];

    $htmlBody .= "<h3>Channel</h3><ul>";
    foreach ($localizations as $language => $localization) {
      $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localization['description']);
    }
    $htmlBody .= '</ul>';
  }
}
?>

<!doctype html>
<html>
<head>
<title>Set and retrieve localized metadata for a channel</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Set and retrieve localized channel section metadata

This sample demonstrates how to use the following API methods to set and retrieve localized metadata for a channel section:

  • It calls the channelSections.update method to update the default language of a channel section's metadata and to add a localized version of this metadata in a selected language.
  • It calls the channelSections.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the channelSections.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that channel section.

<?php

/**
 * This sample sets and retrieves localized metadata for a channel section by:
 *
 * 1. Updating language of the default metadata and setting localized metadata
 *   for a channel section via "channelSections.update" method.
 * 2. Getting the localized metadata for a channel section in a selected language using the
 *   "channelSections.list" method and setting the "hl" parameter.
 * 3. Listing the localized metadata for a channel section using the "channelSections.list" method
 *   and including "localizations" in the "part" parameter.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

$htmlBody = <<<END
<form method="GET">
  <div>
    Action:
    <select id="action" name="action">
      <option value="set">Set Localization - Fill in: channel section ID, default language, language, title</option>
      <option value="get">Get Localization- Fill in: channel section ID, language</option>
      <option value="list">List Localizations - Fill in: channel section ID, language</option>
    </select>
  </div>
  <br>
  <div>
    Channel section ID: <input type="text" id="channelSectionId" name="channelSectionId" placeholder="Enter Channel Section ID">
  </div>
  <br>
  <div>
    Default Language: <input type="text" id="defaultLanguage" name="defaultLanguage" placeholder="Enter Default Language">
  </div>
  <br>
  <div>
    Default Language: <input type="text" id="defaultLanguage" name="defaultLanguage" placeholder="Enter Default Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Language: <input type="text" id="language" name="language" placeholder="Enter Local Language (BCP-47 language code)">
  </div>
  <br>
  <input type="submit" value="GO!">
</form>
END;

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  // This code executes if the user enters an action in the form
  // and submits the form. Otherwise, the page displays the form above.
  if (isset($_GET['action'])) {
    $resource = $_GET['resource'];
    $channelSectionId = $_GET['channelSectionId'];
    $language = $_GET['language'];
    $defaultLanguage = $_GET['defaultLanguage'];
    $title = $_GET['title'];
    try {
      switch ($_GET['action']) {
        case 'set':
          setChannelSectionLocalization($youtube, $channelSectionId, $defaultLanguage,
              $language, $title, $htmlBody);
          break;
        case 'get':
          getChannelSectionLocalization($youtube, $channelSectionId, $language, $htmlBody);
          break;
        case 'list':
          listChannelSectionLocalizations($youtube, $channelSectionId, $htmlBody);
          break;
      }
    } catch (Google_Service_Exception $e) {
      $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    } catch (Google_Exception $e) {
      $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    }
  }
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}


/**
 * Updates a channel section's default language and sets its localized metadata.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $channelSectionId The id parameter specifies the channel section ID
 * for the resource that is being updated.
 * @param string $defaultLanguage The language of the channel section's default metadata
 * @param string $language The language of the localized metadata
 * @param string $title The localized title to be set
 * @param $htmlBody - html body.
 */
function setChannelSectionLocalization(Google_Service_YouTube $youtube, $channelSectionId,
    $defaultLanguage, $language, $title, &$htmlBody) {
  // Call the YouTube Data API's channelSections.list method to retrieve channel sections.
  $channelSections = $youtube->channelSections->listChannelSections("snippet,localizations", array(
      'id' => $channelSectionId
  ));

  // If $channelSections is empty, the specified channel section was not found.
  if (empty($channelSections)) {
    $htmlBody .= sprintf('<h3>Can\'t find a channel section with channel section id: %s</h3>',
        $channelSectionId);
  } else {
    // Since the request specified a channel section ID, the response only
    // contains one channel section resource.
    $updateChannelSection = $channelSections[0];

    // Modify channel section's default language and localizations properties.
    // Ensure that a value is set for the resource's snippet.defaultLanguage property.
    $updateChannelSection['snippet']['defaultLanguage'] = $defaultLanguage;
    $localizations = $updateChannelSection['localizations'];

    if (is_null($localizations)) {
      $localizations = array();
    }
    $localizations[$language] = array('title' => $title);
    $updateChannelSection['localizations'] = $localizations;

    // Call the YouTube Data API's channelSections.update method to update an
    // existing channel section.
    $channelSectionUpdateResponse = $youtube->channels->update("snippet,localizations",
        $updateChannelSection);

    $htmlBody .= "<h2>Updated channel section</h2><ul>";
    $htmlBody .= sprintf('<li>(%s) default language: %s</li>', $channelSectionId,
        $channelSectionUpdateResponse['snippet']['defaultLanguage']);
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language,
        $channelSectionUpdateResponse['localizations'][$language]['title']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns localized metadata for a channel section in a selected language.
 * If the localized text is not available in the requested language,
 * this method will return text in the default language.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $channelSectionId The channelSectionId parameter instructs the API to return the
 * localized metadata for the channel section specified by the channel section id.
 * @param string language The language of the localized metadata.
 * @param $htmlBody - html body.
 */
function getChannelSectionLocalization(Google_Service_YouTube $youtube, $channelSectionId,
    $language, &$htmlBody) {
  // Call the YouTube Data API's channelSections.list method to retrieve channel sections.
  $channelSections = $youtube->channelSections->listChannelSections("snippet", array(
      'id' => $channelSectionId,
      'hl' => $language
  ));

  // If $channelSections is empty, the specified channel section was not found.
  if (empty($channelSections)) {
    $htmlBody .= sprintf('<h3>Can\'t find a channel section with channel section id: %s</h3>',
        $channelSectionId);
  } else {
    // Since the request specified a channel section ID, the response only
    // contains one channel section resource.
    $localized = $channelSections[0]["snippet"]["localized"];

    $htmlBody .= "<h3>Channel Section</h3><ul>";
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localized['title']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns a list of localized metadata for a channel section.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $channelId The channelSectionId parameter instructs the API to return the
 * localized metadata for the channel section specified by the channel section id.
 * @param $htmlBody - html body.
 */
function listChannelSectionLocalizations(Google_Service_YouTube $youtube,
    $channelSectionId, &$htmlBody) {
  // Call the YouTube Data API's channelSections.list method to retrieve channel sections.
  $channelSections = $youtube->channelSections->listChannelSections("snippet", array(
      'id' => $channelSectionId
  ));

  // If $channelSections is empty, the specified channel section was not found.
  if (empty($channelSections)) {
    $htmlBody .= sprintf('<h3>Can\'t find a channel section with channel section id: %s</h3>',
        $channelSectionId);
  } else {
    // Since the request specified a channel section ID, the response only
    // contains one channel section resource.
    $localizations = $channelSections[0]["localizations"];

    $htmlBody .= "<h3>Channel Section</h3><ul>";
    foreach ($localizations as $language => $localization) {
      $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localization['title']);
    }
    $htmlBody .= '</ul>';
  }
}
?>

<!doctype html>
<html>
<head>
<title>Set and retrieve localized metadata for a channel section</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Set and retrieve localized playlist metadata

This sample demonstrates how to use the following API methods to set and retrieve localized metadata for a playlist:

  • It calls the playlists.update method to update the default language of a playlist's metadata and to add a localized version of this metadata in a selected language.
  • It calls the playlists.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the playlists.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that playlist.

<?php

/**
 * This sample sets and retrieves localized metadata for a playlist by:
 *
 * 1. Updating language of the default metadata and setting localized metadata
 *   for a playlist via "playlists.update" method.
 * 2. Getting the localized metadata for a playlist in a selected language using the
 *   "playlists.list" method and setting the "hl" parameter.
 * 3. Listing the localized metadata for a playlist using the "playlists.list" method
 *   and including "localizations" in the "part" parameter.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

$htmlBody = <<<END
<form method="GET">
  <div>
    Action:
    <select id="action" name="action">
      <option value="set">Set Localization - Fill in: playlist ID, default language, language, , title and description</option>
      <option value="get">Get Localization- Fill in: playlist ID, language</option>
      <option value="list">List Localizations - Fill in: playlist ID, language</option>
    </select>
  </div>
  <br>
  <div>
    Playlist ID: <input type="text" id="playlistId" name="playlistId" placeholder="Enter Playlist ID">
  </div>
  <br>
  <div>
    Default Language: <input type="text" id="defaultLanguage" name="defaultLanguage" placeholder="Enter Default Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Language: <input type="text" id="language" name="language" placeholder="Enter Local Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Title: <input type="text" id="title" name="title" placeholder="Enter Title">
  </div>
  <br>
  <div>
    Description: <input type="text" id="description" name="description" placeholder="Enter Description">
  </div>
  <br>
  <input type="submit" value="GO!">
</form>
END;

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  // This code executes if the user enters an action in the form
  // and submits the form. Otherwise, the page displays the form above.
  if (isset($_GET['action'])) {
    $resource = $_GET['resource'];
    $playlistId = $_GET['playlistId'];
    $language = $_GET['language'];
    $defaultLanguage = $_GET['defaultLanguage'];
    $title = $_GET['title'];
    $description = $_GET['description'];
    try {
      switch ($_GET['action']) {
        case 'set':
          setPlaylistLocalization($youtube, $playlistId, $defaultLanguage,
              $language, $title, $description, $htmlBody);
          break;
        case 'get':
          getPlaylistLocalization($youtube, $playlistId, $language, $htmlBody);
          break;
        case 'list':
          listPlaylistLocalizations($youtube, $playlistId, $htmlBody);
          break;
      }
    } catch (Google_Service_Exception $e) {
      $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    } catch (Google_Exception $e) {
      $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    }
  }
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}


/**
 * Updates a playlist's default language and sets its localized metadata.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $playlistId The id parameter specifies the playlist ID for the resource
 * that is being updated.
 * @param string $defaultLanguage The language of the playlist's default metadata
 * @param string $language The language of the localized metadata
 * @param string $title The localized title to be set
 * @param string $description The localized description to be set
 * @param $htmlBody - html body.
 */
function setPlaylistLocalization(Google_Service_YouTube $youtube, $playlistId, $defaultLanguage,
    $language, $title, $description, &$htmlBody) {
  // Call the YouTube Data API's playlists.list method to retrieve playlists.
  $playlists = $youtube->playlists->listPlaylists("snippet,localizations", array(
      'id' => $playlistId
  ));

  // If $playlists is empty, the specified playlist was not found.
  if (empty($playlists)) {
    $htmlBody .= sprintf('<h3>Can\'t find a playlist with playlist id: %s</h3>', $playlistId);
  } else {
    // Since the request specified a playlist ID, the response only
    // contains one playlist resource.
    $updatePlaylist = $playlists[0];

    // Modify playlist's default language and localizations properties.
    // Ensure that a value is set for the resource's snippet.defaultLanguage property.
    $updatePlaylist['snippet']['defaultLanguage'] = $defaultLanguage;
    $localizations = $updatePlaylist['localizations'];

    if (is_null($localizations)) {
      $localizations = array();
    }
    $localizations[$language] = array('title' => $title, 'description' => $description);
    $updatePlaylist['localizations'] = $localizations;

    // Call the YouTube Data API's playlists.update method to update an existing playlist.
    $playlistUpdateResponse = $youtube->playlists->update("snippet,localizations", $updatePlaylist);

    $htmlBody .= "<h2>Updated playlist</h2><ul>";
    $htmlBody .= sprintf('<li>(%s) default language: %s</li>', $playlistId,
        $playlistUpdateResponse['snippet']['defaultLanguage']);
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language,
        $playlistUpdateResponse['localizations'][$language]['title']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language,
        $playlistUpdateResponse['localizations'][$language]['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns localized metadata for a playlist in a selected language.
 * If the localized text is not available in the requested language,
 * this method will return text in the default language.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $playlistId The videoId parameter instructs the API to return the
 * localized metadata for the playlist specified by the playlist id.
 * @param string language The language of the localized metadata.
 * @param $htmlBody - html body.
 */
function getPlaylistLocalization(Google_Service_YouTube $youtube, $playlistId,
    $language, &$htmlBody) {
  // Call the YouTube Data API's playlists.list method to retrieve playlists.
  $playlists = $youtube->playlists->listPlaylists("snippet", array(
      'id' => $playlistId,
      'hl' => $language
  ));

  // If $playlists is empty, the specified playlist was not found.
  if (empty($playlists)) {
    $htmlBody .= sprintf('<h3>Can\'t find a playlist with playlist id: %s</h3>', $playlistId);
  } else {
    // Since the request specified a playlist ID, the response only
    // contains one playlist resource.
    $localized = $playlists[0]["snippet"]["localized"];

    $htmlBody .= "<h3>Playlist</h3><ul>";
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localized['title']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localized['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns a list of localized metadata for a playlist.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $playlistId The videoId parameter instructs the API to return the
 * localized metadata for the playlist specified by the playlist id.
 * @param $htmlBody - html body.
 */
function listPlaylistLocalizations(Google_Service_YouTube $youtube, $playlistId, &$htmlBody) {
  // Call the YouTube Data API's playlists.list method to retrieve playlists.
  $playlists = $youtube->playlists->listPlaylists("snippet", array(
      'id' => $playlistId
  ));

  // If $playlists is empty, the specified playlist was not found.
  if (empty($playlists)) {
    $htmlBody .= sprintf('<h3>Can\'t find a playlist with playlist id: %s</h3>', $playlistId);
  } else {
    // Since the request specified a playlist ID, the response only
    // contains one playlist resource.
    $localizations = $playlists[0]["localizations"];

    $htmlBody .= "<h3>Playlist</h3><ul>";
    foreach ($localizations as $language => $localization) {
      $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localization['title']);
      $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localization['description']);
    }
    $htmlBody .= '</ul>';
  }
}
?>

<!doctype html>
<html>
<head>
<title>Set and retrieve localized metadata for a playlist</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Set and retrieve localized video metadata

This sample demonstrates how to use the following API methods to set and retrieve localized metadata for a video:

  • It calls the videos.update method to update the default language of a video's metadata and to add a localized version of this metadata in a selected language.
  • It calls the videos.list method with the hl parameter set to a specific language to retrieve localized metadata in that language.
  • It calls the videos.list method and includes localizations in the part parameter value to retrieve all of the localized metadata for that video.

<?php

/**
 * This sample sets and retrieves localized metadata for a video by:
 *
 * 1. Updating language of the default metadata and setting localized metadata
 *   for a video via "videos.update" method.
 * 2. Getting the localized metadata for a video in a selected language using the
 *   "videos.list" method and setting the "hl" parameter.
 * 3. Listing the localized metadata for a video using the "videos.list" method and
 *   including "localizations" in the "part" parameter.
 *
 * @author Ibrahim Ulukaya
 */

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

$htmlBody = <<<END
<form method="GET">
  <div>
    Action:
    <select id="action" name="action">
      <option value="set">Set Localization - Fill in: video ID, default language, language, title and description</option>
      <option value="get">Get Localization- Fill in: video ID, language</option>
      <option value="list">List Localizations - Fill in: video ID, language</option>
    </select>
  </div>
  <br>
  <div>
    Video ID: <input type="text" id="videoId" name="videoId" placeholder="Enter Video ID">
  </div>
  <br>
  <div>
    Default Language: <input type="text" id="defaultLanguage" name="defaultLanguage" placeholder="Enter Default Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Language: <input type="text" id="language" name="language" placeholder="Enter Local Language (BCP-47 language code)">
  </div>
  <br>
  <div>
    Title: <input type="text" id="title" name="title" placeholder="Enter Title">
  </div>
  <br>
  <div>
    Description: <input type="text" id="description" name="description" placeholder="Enter Description">
  </div>
  <br>
  <input type="submit" value="GO!">
</form>
END;

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);

/*
 * This OAuth 2.0 access scope allows for full read/write access to the
 * authenticated user's account.
 */
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  // This code executes if the user enters an action in the form
  // and submits the form. Otherwise, the page displays the form above.
  if (isset($_GET['action'])) {
    $htmlBody = '';
    $videoId = $_GET['videoId'];
    $language = $_GET['language'];
    $defaultLanguage = $_GET['defaultLanguage'];
    $title = $_GET['title'];
    $description = $_GET['description'];
    try {
      switch ($_GET['action']) {
        case 'set':
          setVideoLocalization($youtube, $videoId, $defaultLanguage,
              $language, $title, $description, $htmlBody);
          break;
        case 'get':
          getVideoLocalization($youtube, $videoId, $language, $htmlBody);
          break;
        case 'list':
          listVideoLocalizations($youtube, $videoId, $htmlBody);
          break;
      }
    } catch (Google_Service_Exception $e) {
      $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    } catch (Google_Exception $e) {
      $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
          htmlspecialchars($e->getMessage()));
    }
  }
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}


/**
 * Updates a video's default language and sets its localized metadata.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $videoId The id parameter specifies the video ID for the resource
 * that is being updated.
 * @param string $defaultLanguage The language of the video's default metadata
 * @param string $language The language of the localized metadata
 * @param string $title The localized title to be set
 * @param string $description The localized description to be set
 * @param $htmlBody - html body.
 */
function setVideoLocalization(Google_Service_YouTube $youtube, $videoId, $defaultLanguage,
    $language, $title, $description, &$htmlBody) {
  // Call the YouTube Data API's videos.list method to retrieve videos.
  $videos = $youtube->videos->listVideos("snippet,localizations", array(
      'id' => $videoId
  ));

  // If $videos is empty, the specified video was not found.
  if (empty($videos)) {
    $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
  } else {
    // Since the request specified a video ID, the response only
    // contains one video resource.
    $updateVideo = $videos[0];

    // Modify video's default language and localizations properties.
    // Ensure that a value is set for the resource's snippet.defaultLanguage property.
    $updateVideo['snippet']['defaultLanguage'] = $defaultLanguage;
    $localizations = $updateVideo['localizations'];

    if (is_null($localizations)) {
      $localizations = array();
    }
    $localizations[$language] = array('title' => $title, 'description' => $description);
    $updateVideo['localizations'] = $localizations;

    // Call the YouTube Data API's videos.update method to update an existing video.
    $videoUpdateResponse = $youtube->videos->update("snippet,localizations", $updateVideo);

    $htmlBody .= "<h2>Updated video</h2><ul>";
    $htmlBody .= sprintf('<li>(%s) default language: %s</li>', $videoId,
        $videoUpdateResponse['snippet']['defaultLanguage']);
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language,
        $videoUpdateResponse['localizations'][$language]['title']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language,
        $videoUpdateResponse['localizations'][$language]['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns localized metadata for a video in a selected language.
 * If the localized text is not available in the requested language,
 * this method will return text in the default language.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $videoId The videoId parameter instructs the API to return the
 * localized metadata for the video specified by the video id.
 * @param string language The language of the localized metadata.
 * @param $htmlBody - html body.
 */
function getVideoLocalization(Google_Service_YouTube $youtube, $videoId, $language, &$htmlBody) {
  // Call the YouTube Data API's videos.list method to retrieve videos.
  $videos = $youtube->videos->listVideos("snippet", array(
      'id' => $videoId,
      'hl' => $language
  ));

  // If $videos is empty, the specified video was not found.
  if (empty($videos)) {
    $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
  } else {
    // Since the request specified a video ID, the response only
    // contains one video resource.
    $localized = $videos[0]["snippet"]["localized"];

    $htmlBody .= "<h3>Video</h3><ul>";
    $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localized['title']);
    $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localized['description']);
    $htmlBody .= '</ul>';
  }
}

/**
 * Returns a list of localized metadata for a video.
 *
 * @param Google_Service_YouTube $youtube YouTube service object.
 * @param string $videoId The videoId parameter instructs the API to return the
 * localized metadata for the video specified by the video id.
 * @param $htmlBody - html body.
 */
function listVideoLocalizations(Google_Service_YouTube $youtube, $videoId, &$htmlBody) {
  // Call the YouTube Data API's videos.list method to retrieve videos.
  $videos = $youtube->videos->listVideos("snippet,localizations", array(
      'id' => $videoId
  ));

  // If $videos is empty, the specified video was not found.
  if (empty($videos)) {
    $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
  } else {
    // Since the request specified a video ID, the response only
    // contains one video resource.
    $localizations = $videos[0]["localizations"];

    $htmlBody .= "<h3>Video</h3><ul>";
    foreach ($localizations as $language => $localization) {
      $htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localization['title']);
      $htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localization['description']);
    }
    $htmlBody .= '</ul>';
  }
}

?>

<!doctype html>
<html>
<head>
<title>Set and retrieve localized metadata for a video</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Shuffle existing channel sections

This sample calls the API's channelSections.list method to get the list of current channel sections, shuffles them, and then calls channelSections.update to change the position of each.

More information on channel sections is available in the YouTube Help Center.

<?php

/**
 * This sample shuffles user's existing channel sections by:
 *
 * 1. Getting the active user's channel sections via "channelSections.list" method.
 * 2. Shuffling channel sections offline.
 * 3. Saving the newly shuffled channel sections list via the "channelSections.update" method.
 *
 * @author Ibrahim Ulukaya
*/

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  try {
    // Call the YouTube Data API's channelSections.list method to retrieve your channel sections.
    $listResponse = $youtube->channelSections->listChannelSections('snippet,contentDetails', array('mine' => true));
    $channelSections = $listResponse['items'];

    // This will randomly reorder the items in the channel_sections list.
    shuffle($channelSections);

    $htmlBody .= "<h2>Sections Shuffled</h2><ul>";

    foreach ($channelSections as $channelSection) {
      // Each section in the list of shuffled sections is sequentially
      // set to position 0, i.e. the top.
      $channelSection['snippet']['position'] = 0;

      // Call the YouTube Data API's channelSections.update method to update a channel section.
      $updateResponse = $youtube->channelSections->update('snippet,contentDetails', $channelSection);

      $htmlBody .= sprintf('<li>%s "%s"</li>',
          $updateResponse['id'], $updateResponse['snippet']['title']);
    }

    $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
 }
    ?>

<!doctype html>
<html>
<head>
<title>Sections Shuffled</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Update a video

This code sample demonstrates how to add tags into an existing video.

The following code sample calls the API's youtube.videos.list method with id parameter set to videoId to get the video object. Using this video object, the sample gets the list of tags and appends new tags at the end of this list. Finally, the code calls youtube.videos.update method with updated video object to persist these changes on YouTube.

<?php

/**
 * This sample adds new tags to a YouTube video by:
 *
 * 1. Retrieving the video resource by calling the "youtube.videos.list" method
 *    and setting the "id" parameter
 * 2. Appending new tags to the video resource's snippet.tags[] list
 * 3. Updating the video resource by calling the youtube.videos.update method.
 *
 * @author Ibrahim Ulukaya
*/

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  try{

    // REPLACE this value with the video ID of the video being updated.
    $videoId = "VIDEO_ID";

    // Call the API's videos.list method to retrieve the video resource.
    $listResponse = $youtube->videos->listVideos("snippet",
        array('id' => $videoId));

    // If $listResponse is empty, the specified video was not found.
    if (empty($listResponse)) {
      $htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
    } else {
      // Since the request specified a video ID, the response only
      // contains one video resource.
      $video = $listResponse[0];
      $videoSnippet = $video['snippet'];
      $tags = $videoSnippet['tags'];

      // Preserve any tags already associated with the video. If the video does
      // not have any tags, create a new list. Replace the values "tag1" and
      // "tag2" with the new tags you want to associate with the video.
      if (is_null($tags)) {
        $tags = array("tag1", "tag2");
      } else {
        array_push($tags, "tag1", "tag2");
      }

      // Set the tags array for the video snippet
      $videoSnippet['tags'] = $tags;

      // Update the video resource by calling the videos.update() method.
      $updateResponse = $youtube->videos->update("snippet", $video);

      $responseTags = $updateResponse['snippet']['tags'];

      $htmlBody .= "<h3>Video Updated</h3><ul>";
      $htmlBody .= sprintf('<li>Tags "%s" and "%s" added for video %s (%s) </li>',
          array_pop($responseTags), array_pop($responseTags),
          $videoId, $video['snippet']['title']);

      $htmlBody .= '</ul>';
    }
  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

    $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>Video Updated</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Upload a banner image and set as channel's banner

This sample calls the API's channelBanners.insert method to upload an image. With the returned URL, the sample calls channels.update method to update the channel's banner to this image.

<?php

/**
 * This sample sets a custom banner for a user's channel by:
 *
 * 1. Uploading a banner image with "youtube.channelBanners.insert" method via resumable upload
 * 2. Getting user's channel object with "youtube.channels.list" method and "mine" parameter
 * 3. Updating channel's banner external URL with "youtube.channels.update" method
 *
 * @author Ibrahim Ulukaya
*/

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  try{

    // REPLACE with the path to your file that you want to upload for thumbnail
    $imagePath = "/path/to/file.jpg";

    // Specify the size of each chunk of data, in bytes. Set a higher value for
    // reliable connection as fewer chunks lead to faster uploads. Set a lower
    // value for better recovery on less reliable connections.
    $chunkSizeBytes = 1 * 1024 * 1024;

    // Setting the defer flag to true tells the client to return a request which can be called
    // with ->execute(); instead of making the API call immediately.
    $client->setDefer(true);

    $chan = new Google_Service_YouTube_ChannelBannerResource();

    // Create a request for the API's channelBanners.insert method to upload the banner.
    $insertRequest = $youtube->channelBanners->insert($chan);

    // Create a MediaFileUpload object for resumable uploads.
    $media = new Google_Http_MediaFileUpload(
        $client,
        $insertRequest,
        'image/jpeg',
        null,
        true,
        $chunkSizeBytes
    );
    $media->setFileSize(filesize($imagePath));


    // Read the media file and upload it chunk by chunk.
    $status = false;
    $handle = fopen($imagePath, "rb");
    while (!$status && !feof($handle)) {
      $chunk = fread($handle, $chunkSizeBytes);
      $status = $media->nextChunk($chunk);
    }

    fclose($handle);

    // If you want to make other calls after the file upload, set setDefer back to false
    $client->setDefer(false);

    $thumbnailUrl = $status['url'];

    // Call the API's channels.list method with mine parameter to fetch authorized user's channel.
    $listResponse = $youtube->channels->listChannels('brandingSettings', array(
        'mine' => 'true',
    ));

    $responseChannel = $listResponse[0];
    $responseChannel['brandingSettings']['image']['bannerExternalUrl']=$thumbnailUrl;

     // Call the API's channels.update method to update branding settings of the channel.
     $updateResponse = $youtube->channels->update('brandingSettings', $responseChannel);

     $bannerMobileUrl = $updateResponse["brandingSettings"]["image"]["bannerMobileImageUrl"];

     $htmlBody .= "<h3>Thumbnail Uploaded</h3><ul>";
     $htmlBody .= sprintf('<li>%s</li>',
         $thumbnailUrl);
     $htmlBody .= sprintf('<img src="%s">', $bannerMobileUrl);
     $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>Banner Uploaded and Set</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Upload a custom video thumbnail image

This sample demonstrates how to upload a custom video thumbnail to YouTube and set it for a video. It calls the API's youtube.thumbnails.set method with videoId parameter set to a video ID to use a custom image as a thumbnail to the video. For the image upload, the program utilizes the Google_MediaFileUpload class with the resumable parameter set to true to upload the image piece-by-piece, allowing for subsequent retries to resume uploading from a point close to where the previous retry failed, a feature useful for programs that need to upload large files.

<?php

/**
 * This sample uploads and sets a custom thumbnail for a video.
 *
 * 1. It uploads an image using the "Google_MediaFileUpload" class.
 * 2. It sets the uploaded image as a custom thumbnail to the video by
 *    calling the API's "youtube.thumbnails.set" method
 *
 * @author Ibrahim Ulukaya
*/

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  try{

    // REPLACE this value with the video ID of the video being updated.
    $videoId = "VIDEO_ID";

    // REPLACE this value with the path to the image file you are uploading.
    $imagePath = "/path/to/file.png";

    // Specify the size of each chunk of data, in bytes. Set a higher value for
    // reliable connection as fewer chunks lead to faster uploads. Set a lower
    // value for better recovery on less reliable connections.
    $chunkSizeBytes = 1 * 1024 * 1024;

    // Setting the defer flag to true tells the client to return a request which can be called
    // with ->execute(); instead of making the API call immediately.
    $client->setDefer(true);

    // Create a request for the API's thumbnails.set method to upload the image and associate
    // it with the appropriate video.
    $setRequest = $youtube->thumbnails->set($videoId);

    // Create a MediaFileUpload object for resumable uploads.
    $media = new Google_Http_MediaFileUpload(
        $client,
        $setRequest,
        'image/png',
        null,
        true,
        $chunkSizeBytes
    );
    $media->setFileSize(filesize($imagePath));


    // Read the media file and upload it chunk by chunk.
    $status = false;
    $handle = fopen($imagePath, "rb");
    while (!$status && !feof($handle)) {
      $chunk = fread($handle, $chunkSizeBytes);
      $status = $media->nextChunk($chunk);
    }

    fclose($handle);

    // If you want to make other calls after the file upload, set setDefer back to false
    $client->setDefer(false);


    $thumbnailUrl = $status['items'][0]['default']['url'];
    $htmlBody .= "<h3>Thumbnail Uploaded</h3><ul>";
    $htmlBody .= sprintf('<li>%s (%s)</li>',
        $videoId,
        $thumbnailUrl);
    $htmlBody .= sprintf('<img src="%s">', $thumbnailUrl);
    $htmlBody .= '</ul>';


  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>Claim Uploaded</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>

Upload a video

The following code sample calls the API's videos.insert method to add a video to user's channel. The code also utilizes Google_MediaFileUpload class with the resumable upload parameter set to true to be able to to upload the video in chunks.

<?php

/**
 * Library Requirements
 *
 * 1. Install composer (https://getcomposer.org)
 * 2. On the command line, change to this directory (api-samples/php)
 * 3. Require the google/apiclient library
 *    $ composer require google/apiclient:~2.0
 */
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}

require_once __DIR__ . '/vendor/autoload.php';
session_start();

/*
 * You can acquire an OAuth 2.0 client ID and client secret from the
 * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
 * For more information about using OAuth 2.0 to access Google APIs, please see:
 * <https://developers.google.com/youtube/v3/guides/authentication>
 * Please ensure that you have enabled the YouTube Data API for your project.
 */
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

if (isset($_SESSION[$tokenSessionKey])) {
  $client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
  $htmlBody = '';
  try{
    // REPLACE this value with the path to the file you are uploading.
    $videoPath = "/path/to/file.mp4";

    // Create a snippet with title, description, tags and category ID
    // Create an asset resource and set its snippet metadata and type.
    // This example sets the video's title, description, keyword tags, and
    // video category.
    $snippet = new Google_Service_YouTube_VideoSnippet();
    $snippet->setTitle("Test title");
    $snippet->setDescription("Test description");
    $snippet->setTags(array("tag1", "tag2"));

    // Numeric video category. See
    // https://developers.google.com/youtube/v3/docs/videoCategories/list
    $snippet->setCategoryId("22");

    // Set the video's status to "public". Valid statuses are "public",
    // "private" and "unlisted".
    $status = new Google_Service_YouTube_VideoStatus();
    $status->privacyStatus = "public";

    // Associate the snippet and status objects with a new video resource.
    $video = new Google_Service_YouTube_Video();
    $video->setSnippet($snippet);
    $video->setStatus($status);

    // Specify the size of each chunk of data, in bytes. Set a higher value for
    // reliable connection as fewer chunks lead to faster uploads. Set a lower
    // value for better recovery on less reliable connections.
    $chunkSizeBytes = 1 * 1024 * 1024;

    // Setting the defer flag to true tells the client to return a request which can be called
    // with ->execute(); instead of making the API call immediately.
    $client->setDefer(true);

    // Create a request for the API's videos.insert method to create and upload the video.
    $insertRequest = $youtube->videos->insert("status,snippet", $video);

    // Create a MediaFileUpload object for resumable uploads.
    $media = new Google_Http_MediaFileUpload(
        $client,
        $insertRequest,
        'video/*',
        null,
        true,
        $chunkSizeBytes
    );
    $media->setFileSize(filesize($videoPath));


    // Read the media file and upload it chunk by chunk.
    $status = false;
    $handle = fopen($videoPath, "rb");
    while (!$status && !feof($handle)) {
      $chunk = fread($handle, $chunkSizeBytes);
      $status = $media->nextChunk($chunk);
    }

    fclose($handle);

    // If you want to make other calls after the file upload, set setDefer back to false
    $client->setDefer(false);


    $htmlBody .= "<h3>Video Uploaded</h3><ul>";
    $htmlBody .= sprintf('<li>%s (%s)</li>',
        $status['snippet']['title'],
        $status['id']);

    $htmlBody .= '</ul>';

  } catch (Google_Service_Exception $e) {
    $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  } catch (Google_Exception $e) {
    $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
        htmlspecialchars($e->getMessage()));
  }

  $_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
  $htmlBody = <<<END
  <h3>Client Credentials Required</h3>
  <p>
    You need to set <code>\$OAUTH2_CLIENT_ID</code> and
    <code>\$OAUTH2_CLIENT_ID</code> before proceeding.
  <p>
END;
} else {
  // If the user hasn't authorized the app, initiate the OAuth flow
  $state = mt_rand();
  $client->setState($state);
  $_SESSION['state'] = $state;

  $authUrl = $client->createAuthUrl();
  $htmlBody = <<<END
  <h3>Authorization Required</h3>
  <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p>
END;
}
?>

<!doctype html>
<html>
<head>
<title>Video Uploaded</title>
</head>
<body>
  <?=$htmlBody?>
</body>
</html>