Using the YouTube API to upload videos to a single channel is straightforward. This is how I currently do it using the PHP Client Library:
<?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 authorize access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>Video Updated</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
update_video.php
The very first time the script runs, I am prompted with a window to authenticate the request, a token is granted and expires in 60 minutes.
I want to use the same script to upload videos to different channels which I own. For example if I have 3 different channels I can sign in to different browsers to authenticate the application. I currently have more than 10 YouTube channels that I want to upload content to after every few hours.
Is there a way I can manage all these channels from a central service so as to avoid authenticating each time I add a new channel. Or is there a way to authenticate the YouTube API using my YouTube login details?
The YouTube API is slightly different then other Google APIs. Normally authentication is user account based. So if I authenticate you to access my Google calendar you have access to all my Google calendars.
The YouTube API is how ever User channel based. Your going to have to authenticate your application once for each channel. Then make sure you have a refresh token. Store the refresh token someplace associated with the name of the channel. Then you your automated script will be able to use the refresh token to request a new access token and gain access to your account when ever it needs.
This question is for the Analytics api but the code should work for YouTube as well with a few minor alterations to point to the YouTube API instead. How to refresh token with Google API client?
Related
I am currently using the Google Calendar API for a web application. However, every hour, I am prompted with a link to verify quickstart access. Does anyone know how to fix this?
Details:
I have created a new gmail id: redu#gmail.com
redu#gmail.com has an associated calendar
My php based web application needs to do the following with calendar:
Create a new calendar for every registered user (as an additional calendar for redu#gmail.com)
Create an event for a logged in user and add another registered user as an invitee
I have tried using OAUTH and service accounts with no luck. Any help is greatly appreciated.
Below is the code that creates Google_Client and Srvice objects using service account's credentials
function __construct()
{
Service account based client creation.
$this->client = new Google_Client();
$this->client->setApplicationName("Redu");
$this->client->setAuthConfig(CREDENTIALS_PATH);
$this->client->setScopes([SCOPES]);
$this->client->setSubject('redu#gmail.com');
$this->client->setAccessType('offline');
$this->service = new Google_Service_Calendar($this->client);
}
When I try to use the $service object to create a calendar or create an event I get an error saying that domain wide permissions are not setup. However, when I created the service account I did enable domain wide delegation.
EDIT:
Below is my code to create a Google_Client using service account key and use the client to create a new calendar for redu#gmail.com. Note that I shared redu#gmail.com's calendar with reduservice#subtle-breaker-280602.iam.gserviceaccount.com and set the permission to "Manage Changes and Manage Sharing". The error I am getting is below the code:
require (__DIR__.'/../../../vendor/autoload.php');
define('CREDENTIALS_PATH', __DIR__ . '/redu_service_account_credentials.json');
define('SCOPES', Google_Service_Calendar::CALENDAR);
function createNewCalendar($userName) {
//Service account based client creation.
$client = new Google_Client();
$client->setApplicationName("REdu");
// path to the credentials file obtained upon creating key for service account
$client->setAuthConfig(CREDENTIALS_PATH);
$client->setScopes([SCOPES]);
$client->setSubject('redu#gmail.com');
$client->setAccessType('offline');
$service = new Google_Service_Calendar($client);
$calendar = new Google_Service_Calendar_Calendar();
$calendar->setSummary($userName);
$calendar->setTimeZone('America/Los_Angeles');
$createdCalendar = $service->calendars->insert($calendar);
// Make the newly created calendar public
$rule = new Google_Service_Calendar_AclRule();
$scope = new Google_Service_Calendar_AclRuleScope();
$scope->setType("default");
$scope->setValue("");
$rule->setScope($scope);
$rule->setRole("reader");
// Make the calendar public
$createdRule = $service->acl->insert($createdCalendar->getId(), $rule);
return $createdCalendar->getId();
}
ERROR:
Fatal error: Uncaught exception 'Google_Service_Exception' with message '{
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}'
OAUTH2 vs Service accounts
Oauth2 and service accounts are two different things. You use oauth2 if you are trying to access a users data. The consent window you mentioned will prop up and ask that they grant permission for your application to access their data.
Service accounts on the other hand are dummy users who can be pre approved to access data you the developer control. You could share a calendar with a service account granting it access to that calendar it will no need to be authenticated in the same manner as a user.
A service account will never popup and request access again.
Oauth2 example with refresh token.
The issue is that your access token is expiring. If it expires then the user will need to grant your application access to their data again. To avoid this we use a refresh token and store that in a session varable and when the acces stoken expires we just request a new one.
Notice how i am requesting $client->setAccessType("offline"); this will give me a refresh token.
the session vars are now set storing this data
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
Then latter i can check if the access token is expired if so i refresh it
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
oauth2callback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
Authentication.php
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
?>
code for service account
The credential files are different dont mix them up.
function getServiceAccountClient() {
try {
// Create and configure a new client object.
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope([YOUR SCOPES HERE]);
return $client;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
Error
Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.
There are two types of clients Oauth2 clients and Service account clients. The .json file you download is diffrent for each client. As is the code you will use for each client. You cant interchange this code.
The error you are getting stats that the client you are using cant be used for the code you are using. Try to download the client secret .json for the service account again.,
Here's a working example that generates the authentication object using the Service Account's JSON file
$client = new Google\Client();
$client->setApplicationName(APP_NAME);
$client->setAuthConfig(PATH_TO_JSON_FILE);
$client->setScopes(['YOUR_SCOPE1','YOUR_SCOPE2']);
$client->setSubject(EMAIL_OF_PERSON_YOURE_IMPERSONATING);
$client->setAccessType('offline');
$service = new Google_Service_Drive($client);
// Do stuff with the $service object
Generate Service Account in Google API Console
Delegate domain wide authority to that Service Account's Client ID in Google workspace and define the scopes that the Service Account will have access to
Use the code above and make sure to include one more more relevant scopes
I'm trying to upload Videos via a PHP Script using the YouTube API V3 with a free third party Script. I have been through multiple Scripts including the YouTube code snippets but this one seems to be the one fitting my needs the most.
The Problem I have right now is, that the script seems stuck in a cycle of granting access, starting over and requesting access again without ever uploading a video.
Besides, this script specifically aims for only having to grant access once, which is exactly what I need.
I already asked for help on the 3rd party site, sadly got no response yet.
We have configured the Application, got the correct credentials, setup the redirct URI etc apparently correct, since we do get responses allowing us to authorize the Application to use the YouTube Account/Channel.
It seems the script cannot get an accessToken via the API method.
The original Code can be found at:
https://artisansweb.net/use-youtube-api-upload-video-youtube-channel/
What fails for seems to be this:
$client->getAccessToken();
There is an if else construct and the script always uses the else part.
if ($client->getAccessToken()) {...}
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 authorize access before proceeding.<p>
END;
}
The function getAccessToken() is provided by the youtube API.
I have been through the process of authorizing the App multiple times over the course of multiple days but still it wont work.
I can't figure out why and where this process fails and would appreciate any help regarding this. All I initially needed was a script to upload videos to YouTube , with only having to grant access once.
But as described the Script is stuck on the granting access part. I would appreciate it if anyone could point me to the Problem or could point me to another Script I could use to achieve this.
This is the code i use for authorization.
Oauth2Authentication.php
require_once __DIR__ . '/vendor/autoload.php';
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
$client = getOauth2Client();
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Scopes will need to be changed depending upon the API's being accessed.
* Example: array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function buildClient(){
$client = new Google_Client();
$client->setAccessType("offline"); // offline access. Will result in a refresh token
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setAuthConfig(__DIR__ . '/client_secrets.json');
$client->addScope([YOUR SCOPES HERE]);
$client->setRedirectUri(getRedirectUri());
return $client;
}
/**
* Builds the redirect uri.
* Documentation: https://developers.google.com/api-client-library/python/auth/installed-app#choosingredirecturi
* Hostname and current server path are needed to redirect to oauth2callback.php
* #return A redirect uri.
*/
function getRedirectUri(){
//Building Redirect URI
$url = $_SERVER['REQUEST_URI']; //returns the current URL
if(strrpos($url, '?') > 0)
$url = substr($url, 0, strrpos($url, '?') ); // Removing any parameters.
$folder = substr($url, 0, strrpos($url, '/') ); // Removeing current file.
return (isset($_SERVER['HTTPS']) ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . $folder. '/oauth2callback.php';
}
/**
* Authenticating to Google using Oauth2
* Documentation: https://developers.google.com/identity/protocols/OAuth2
* Returns a Google client with refresh token and access tokens set.
* If not authencated then we will redirect to request authencation.
* #return A google client object.
*/
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
oauth2callback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
For upload i would follow large-file-upload.php
I am receiving an error message when trying to download YouTube Reporting API bulk reports on behalf of a content owner.
I have successfully created report jobs and report job returns download URLs but the download fails with the following error message:
A service error occurred: Invalid json in service response:
date,channel_id,video_id,claimed_status,uploader_type,country_code,ad_type,estimated_youtube_ad_revenue,ad_impressions,estimated_cpm
Please can someone help me understand what this error means and how to resolve the issue? I've tracked issue down to failure in function downloadReport. The line that fails is:
response = $client->execute($request);
I have used the PHP sample code provided on Google developers here:
https://developers.google.com/youtube/reporting/v1/reports/#code-samples
My version of code for "Retrieve a report" follows:
<?php
/**
* This sample retrieves reports created by a specific job by:
*
* 1. Listing the jobs using the "jobs.list" method.
* 2. Retrieving reports using the "reports.list" method.
*
* #author Ibrahim Ulukaya
*/
// Call set_include_path() as needed to point to your client library.
require_once '/../src/Google/autoload.php';
require_once '/../src/Google/Client.php';
require_once '/../src/Google/Service/YouTubeReporting.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* Google Developers Console <https://console.developers.google.com/>
* 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/yt-analytics-monetary.readonly https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/youtubepartner https://www.googleapis.com/auth/youtube.readonly https://www.googleapis.com/auth/youtubepartner-channel-audit https://www.googleapis.com/auth/youtubepartner-content-owner-readonly');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// YouTube Reporting object used to make YouTube Reporting API requests.
$youtubeReporting = new Google_Service_YoutubeReporting($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
try {
if (empty(listReportingJobs($youtubeReporting, $htmlBody)))
{
$htmlBody .= sprintf('<p>No jobs found.</p>');
}
else
{
if ($_GET['reportUrl'])
{
downloadReport($youtubeReporting, $_GET['reportUrl'], $htmlBody);
}
else
{
if ($_GET['jobId'])
{
retrieveReports($youtubeReporting, $_GET['jobId'], $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['token'] = $client->getAccessToken();
} 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 authorize access before proceeding.<p>
END;
}
/**
* Returns a list of reporting jobs. (jobs.listJobs)
*
* #param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object.
* #param $htmlBody - html body.
*/
function listReportingJobs(Google_Service_YouTubeReporting $youtubeReporting, &$htmlBody) {
// Call the YouTube Reporting API's jobs.list method to retrieve reporting jobs.
$optParams=array("onBehalfOfContentOwner"=>"REPLACE_ME");
$reportingJobs = $youtubeReporting->jobs->listJobs($optParams);
$htmlBody .= "<h3>Reporting Jobs</h3><ul>";
foreach ($reportingJobs as $job) {
$htmlBody .= sprintf('<li>id: "%s", name: "%s" report type: "%s"</li>', $job['id'],
$job['name'], $job['reportTypeId']);
}
$htmlBody .= '</ul>';
return $reportingJobs;
}
/**
* Lists reports created by a specific job. (reports.listJobsReports)
*
* #param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object.
* #param string $jobId The ID of the job.
* #param $htmlBody - html body.
*/
function retrieveReports(Google_Service_YouTubeReporting $youtubeReporting, $jobId, &$htmlBody) {
// Call the YouTube Reporting API's reports.list method to retrieve reports created by a job.
$optParams=array("onBehalfOfContentOwner"=>"REPLACE_ME");
$reports = $youtubeReporting->jobs_reports->listJobsReports($jobId, $optParams);
if (empty($reports)) {
$htmlBody .= sprintf('<p>No reports found.</p>');
} else {
$htmlBody .= sprintf('<h2>Reports for the job "%s"</h2>', $jobId);
foreach ($reports as $report) {
$htmlBody .= sprintf('<ul><li>From "%s" to "%s" downloadable at "%s"</li>',
$report['startTime'], $report['endTime'], $report['downloadUrl']);
$htmlBody .= '</ul>';
}
}
}
/**
* Download the report specified by the URL. (media.download)
*
* #param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object.
* #param string $reportUrl The URL of the report to be downloaded.
* #param $htmlBody - html body.
*/
function downloadReport(Google_Service_YouTubeReporting $youtubeReporting, $reportUrl, &$htmlBody) {
$client = $youtubeReporting->getClient();
// 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);
// Call the YouTube Reporting API's media.download method to download a report.
$request = $youtubeReporting->media->download("");
$request->setUrl($reportUrl);
$response = $client->execute($request);
file_put_contents("reportFile", $response->getResponseBody());
$client->setDefer(false);
}
?>
<!doctype html>
<html>
<head>
<title>Retrieve reports</title>
</head>
<body>
<form method="GET">
<div>
Job Id: <input type="text" id="jobId" name="jobId" placeholder="Enter Job Id">
</div>
<br>
<div>
Report URL: <input type="text" id="reportUrl" name="reportUrl" placeholder="Enter Report Url">
</div>
<br> <input type="submit" value="Retrieve!">
</form>
<?=$htmlBody?>
</body>
</html>
I am managing a Google account and it has a YouTube channel connected to a Google+ profile, and a YouTube channel connected to a Google+ page. Using a OAuth key of this account, I want to upload videos to the "page"'s channel, so far I've only managed with the "profile"'s channel. The "page" channel has our company name and logo, so I don't want it to be a personal (at least appear to be) "profile"'s channel
I'm using a script almost identical to the video upload sample script:
https://developers.google.com/youtube/v3/code_samples/php?hl=en#upload_a_video
<?php
// Call set_include_path() as needed to point to your client library.
require_once 'Google/Client.php';
require_once 'Google/Service/YouTube.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* Google Developers Console <https://console.developers.google.com/>
* 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);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
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['token'] = $client->getAccessToken();
} 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 authorize access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>Video Uploaded</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
As mentioned, the script works for the channel that was connected to the "profile" .. I've since deleted this as it was just for testing. I want to upload videos instead to the other Google+ "page"'s channel which is also owned by this account. So far I've tried setting the desired channel as the default of this account, but do I need to actually move the channel to the Google+ "profile"? .. unless I can specify channel in the above script? If I move the channel, will it retain the channel's name though? I don't want anything about the channel to change (name, logo). From what I see it will change the channel name (see image) which is not ideal, I just want to upload to this channel - that's all
Checkout this:
https://developers.google.com/youtube/v3/docs/videos/insert
And notice the onBehalfOfContentOwner and the onBehalfOfContentOwnerChannel parameters for the request, i think this is what you need.
This parameter is intended for YouTube content partners that own and manage many different YouTube channels. It allows content owners to authenticate once and perform actions on behalf of the channel specified in the parameter value, without having to provide authentication credentials for each separate channel.
I am using Youtube data api its properly working on localhost but when I am trying to access this code on live server its not working. giving an exception :
Uncaught exception 'Google_IO_Exception' with message 'Protocol
"https" not supported or disabled in libcurl' in
/home/legenddude/public_html/newUpload/Google/IO/Curl.php:115 Stack
trace: #0
/home/legenddude/public_html/newUpload/Google/IO/Abstract.php(136):
Google_IO_Curl->executeRequest(Object(Google_Http_Request)) #1
/home/legenddude/public_html/newUpload/Google/Auth/OAuth2.php(111):
Google_IO_Abstract->makeRequest(Object(Google_Http_Request)) #2
/home/legenddude/public_html/newUpload/Google/Client.php(128):
Google_Auth_OAuth2->authenticate('4/x7_AOHFKvmlea...', false) #3
/home/legenddude/public_html/newUpload/youtube.php(44):
Google_Client->authenticate('4/x7_AOHFKvmlea...') #4 {main} thrown in
Here is my code youtube.php-:
<?php
// Call set_include_path() as needed to point to your client library.
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
set_include_path($_SERVER['DOCUMENT_ROOT'] . '/newUpload/');
require_once 'Google/autoload.php';
require_once 'Google/Client.php';
require_once 'Google/Service/YouTube.php';
session_start();
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
/*
* 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 = '619899784025-5nn2tqomt3cr6g231qd93nr0lsojdvq9.apps.googleusercontent.com';
$OAUTH2_CLIENT_SECRET = '49K6Ou9PK9n1aamAeg27fnIC';
$REDIRECT = 'http://www.legenddude.com/newUpload/youtube.php';
$APPNAME = "legenddudes";
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes("https://www.googleapis.com/auth/youtube");
$client->setRedirectUri($REDIRECT);
$client->setApplicationName($APPNAME);
$client->setAccessType('online');
$client->setDeveloperKey('619899784025-5nn2tqomt3cr6g231qd93nr0lsojdvq9#developer.gserviceaccount.com');
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
//echo $_SESSION['state'];exit;
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
echo '<code>' . $_SESSION['token'] . '</code>';
}
// 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_ServiceException $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['token'] = $client->getAccessToken();
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorise access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>My Uploads</title>
</head>
<body>
<?php echo $htmlBody?>
</body>
</html>`enter code here`
From curl_faq:
When passing on a URL to curl to use, it may respond that the particular protocol is not supported or disabled. The particular way this error message is phrased is because curl doesn't make a distinction internally of whether a particular protocol is not supported (i.e. never got any code added that knows how to speak that protocol) or if it was explicitly disabled. curl can be built to only support a given set of protocols, and the rest would then be disabled or not supported.
And more:
To get the https:// support into a curl that was previously built but that reports that https:// is not supported, you should dig through the document and logs and check out why the configure script doesn't find the SSL libs and/or include files.