This question already has answers here:
How to obtain a feed of comments entered through the 'chat' box during a YouTube live broadcast?
(3 answers)
Closed 6 years ago.
Since this is a question about the new YouTube API that has just been released it is not a duplicate.
I am trying to fetch the chat messages from the YouTube API 3. I have tried everything I can and I am stuck.
I need the liveChatId to be able to fetch them but I don't know how to retrieve that value. The API says that you get it from liveBroadcast snippet.liveChatId, but with the code I've attached in this post there is no value in the liveChatId field. It is just empty. How do I properly retrieve the liveChatId?
<?php
session_start();
// Call set_include_path() as needed to point to your client library.
require_once 'Google/autoload.php';
require_once 'Google/Client.php';
require_once 'Google/Service/YouTube.php';
$OAUTH2_CLIENT_ID = 'MY-CLIENT-ID';
$OAUTH2_CLIENT_SECRET = 'MY-CLIENT-SECRET';
$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);
$_SESSION['state'] = $_GET['state'];
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 {
// Execute an API request that lists broadcasts owned by the user who
// authorized the request.
$broadcastsResponse = $youtube->liveBroadcasts->listLiveBroadcasts(
'id,snippet',
array(
'mine' => 'true',
));
var_dump($broadcastsResponse['items']);
$htmlBody .= "<h3>Live Broadcasts</h3><ul>";
foreach ($broadcastsResponse['items'] as $broadcastItem) {
$htmlBody .= $broadcastItem['snippet']['title'] ."<br />Chat ID: ". $broadcastItem['liveChatId'] ."<br />ID: ". $broadcastItem['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>My Live Streams</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
Where am I lost?
Your comment has exposed the problem. YouTube currently doesn't support mixing live calls with "Stream Now" and creating Events via the API. Complete live events using either one flow or the other, not interchanging both.
Related
I am working on the following code, it a sample code for using Youtube Data API to list user broadcasts
it works for me and I have modified some parts but then the token expired and I had to clear my session and re-authenticate to be able to work again, I searched a lot and found some posts that say that the token expired after 1 hour
how can I make the token not expire at all?
<?php
include 'oauth.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 = $clientid;
$OAUTH2_CLIENT_SECRET = $clientsecret;
$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 {
// Execute an API request that lists broadcasts owned by the user who
// authorized the request.
$broadcastsResponse = $youtube->liveBroadcasts->listLiveBroadcasts(
'id,snippet,contentDetails',
array(
'mine' => 'true',
));
$htmlBody = "<h3>Live Broadcasts</h3>";
foreach ($broadcastsResponse['items'] as $broadcastItem) {
//$htmlBody .= sprintf('<li>%s (%s) (%s)</li>', $broadcastItem['snippet']['title'],
//$broadcastItem['id'], $broadcastItem['snippet']['description']);
$htmlBody .= "<div><ul>";
$htmlBody .= "<li><b>Title:</b> ".$broadcastItem['snippet']['title']."</li>";
$htmlBody .= "<li><b>ID:</b> ".$broadcastItem['id']."</li>";
$htmlBody .= "<li><b>Description:</b> ".$broadcastItem['snippet']['description']."</li>";
$htmlBody .= "<li><b>Thumbnail</b> <img src='".$broadcastItem['snippet']['thumbnails']['default']['url']."' width='100px'/></li>";
$htmlBody .= "<li><b>Embed:</b><iframe width='560' height='315' src='https://www.youtube.com/embed/".$broadcastItem['id']."' title='YouTube video player' frameborder='0' allow='accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture' allowfullscreen></iframe></li>";
$htmlBody .= "</ul></div>";
}
$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 authorize access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>My Live Broadcasts</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
Access tokens by design expire. This is how they work. Googles access tokens expire after an hour.
If you are requesting offline access you will have a refresh token. You can then use your refresh token to request a new access token when ever you need.
Oauth2Authentication.php
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;
}
Then its simply a matter of testing if the access token has expired and requesting a new one
$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();
}
I am trying to create a simple automation for myself.
I want to send the title of my next YouTube video to telegram.
This will then be caught by a webhook on my website (Public accessible Domain) and auto-schedule the video respective to time specified.
My problem is that when using the YouTube's API, the Gmail account of the channel has to sign in. This creates a problem... I don't want to go through the authentication process.
I've read about service accounts, and how they can be used to do things similar to these; I've set up my "RIG" but it doesn't work. I keep getting error:
A service error occurred: { "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." }
Please see code below.
(Google's Documentation on the subject is terrible.)
<?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.
*/
?>
<?PHP
$client = new Google_Client();
$user_to_impersonate = "sXXXXXXXXXm#gmail.com";
$client->setSubject($user_to_impersonate);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$client->setAuthConfig('ultimate-figure-XXX-XXXXX.json'); //JSON OF THE SERVICE ACCOUNT
$redirect = filter_var('https://' . $_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 {
// Create an object for the liveBroadcast resource's snippet. Specify values
// for the snippet's title, scheduled start time, and scheduled end time.
$broadcastSnippet = new Google_Service_YouTube_LiveBroadcastSnippet();
$broadcastSnippet->setTitle('New Broadcast');
$broadcastSnippet->setScheduledStartTime('2034-01-30T00:00:00.000Z');
$broadcastSnippet->setScheduledEndTime('2034-01-31T00:00:00.000Z');
// Create an object for the liveBroadcast resource's status, and set the
// broadcast's status to "private".
$status = new Google_Service_YouTube_LiveBroadcastStatus();
$status->setPrivacyStatus('private');
// Create the API request that inserts the liveBroadcast resource.
$broadcastInsert = new Google_Service_YouTube_LiveBroadcast();
$broadcastInsert->setSnippet($broadcastSnippet);
$broadcastInsert->setStatus($status);
$broadcastInsert->setKind('youtube#liveBroadcast');
// Execute the request and return an object that contains information
// about the new broadcast.
$broadcastsResponse = $youtube->liveBroadcasts->insert('snippet,status',
$broadcastInsert, array());
// Create an object for the liveStream resource's snippet. Specify a value
// for the snippet's title.
$streamSnippet = new Google_Service_YouTube_LiveStreamSnippet();
$streamSnippet->setTitle('New Stream');
// Create an object for content distribution network details for the live
// stream and specify the stream's format and ingestion type.
$cdn = new Google_Service_YouTube_CdnSettings();
$cdn->setFormat("1080p");
$cdn->setIngestionType('rtmp');
// Create the API request that inserts the liveStream resource.
$streamInsert = new Google_Service_YouTube_LiveStream();
$streamInsert->setSnippet($streamSnippet);
$streamInsert->setCdn($cdn);
$streamInsert->setKind('youtube#liveStream');
// Execute the request and return an object that contains information
// about the new stream.
$streamsResponse = $youtube->liveStreams->insert('snippet,cdn',
$streamInsert, array());
// Bind the broadcast to the live stream.
$bindBroadcastResponse = $youtube->liveBroadcasts->bind(
$broadcastsResponse['id'],'id,contentDetails',
array(
'streamId' => $streamsResponse['id'],
));
$htmlBody .= "<h3>Added Broadcast</h3><ul>";
$htmlBody .= sprintf('<li>%s published at %s (%s)</li>',
$broadcastsResponse['snippet']['title'],
$broadcastsResponse['snippet']['publishedAt'],
$broadcastsResponse['id']);
$htmlBody .= '</ul>';
$htmlBody .= "<h3>Added Stream</h3><ul>";
$htmlBody .= sprintf('<li>%s (%s)</li>',
$streamsResponse['snippet']['title'],
$streamsResponse['id']);
$htmlBody .= '</ul>';
$htmlBody .= "<h3>Bound Broadcast</h3><ul>";
$htmlBody .= sprintf('<li>Broadcast (%s) was bound to stream (%s).</li>',
$bindBroadcastResponse['id'],
$bindBroadcastResponse['contentDetails']['boundStreamId']);
$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;
}
?>
When loading the token script :
token.php
<?php
require_once '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 = '516195178663-5pgnd88unc38khttmgj67scinlhk7caf.apps.googleusercontent.com'; // Enter your Client ID here
$OAUTH2_CLIENT_SECRET = 'QLsIeOBhHLIee4_d-OOqjblK'; // Enter your Client Secret here
$REDIRECT = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'], FILTER_SANITIZE_URL);
$APPNAME = "BrickFame";
$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('offline');
$client->setApprovalPrompt('force');
// 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();
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
echo "Access Token: " . json_encode($_SESSION['token']);
}
// 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>
I can fetch my access token and refresh token is shown and i saved it under token.txt
Access Token: {"access_token":"ya29.Ci8tA-3KvN7LE03mLLWsJJOsKHPr3ArvEw9xDaCX8wpFxGM-VpLswYwR1Mnhc7wS1Q","token_type":"Bearer","expires_in":3600,"refresh_token":"1\/BopX8bClCDuDkg0WO9KKyvxKMC-y1GiFhFOO8JQ5HkU","created":1469621552}
However when accessing the upload script:
api.php
<?php
$key = file_get_contents('token.txt');
require_once 'vendor/autoload.php';
$client_id = '516195178663-5pgnd88unc38khttmgj67scinlhk7caf.apps.googleusercontent.com'; // Enter your Client ID here
$client_secret = 'QLsIeOBhHLIee4_d-OOqjblK'; // Enter your Client Secret here
$videoPath = "videos/example.mkv";
$videoTitle = "Just an Example Title";
$videoDescription = "This is the YouTube video's description";
$videoCategory = "22";
$videoTags = array("first tag","second tag","third tag");
try{
// Client init
$client = new Google_Client();
$client->setClientId($client_id);
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->setAccessToken($key);
$client->setClientSecret($client_secret);
if ($client->getAccessToken()) {
/**
* Check to see if our access token has expired. If so, get a new one and save it to file for future use.
*/
if($client->isAccessTokenExpired()) {
$newToken = json_decode($client->getAccessToken());
$client->refreshToken($newToken->refresh_token);
file_put_contents($key, $client->getAccessToken());
}
$youtube = new Google_Service_YouTube($client);
// Create a snipet with title, description, tags and category id
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle($videoTitle);
$snippet->setDescription($videoDescription);
$snippet->setCategoryId($videoCategory);
$snippet->setTags($videoTags);
$snippet->setDefaultLanguage("en");
$snippet->setDefaultAudioLanguage("en");
$recordingDetails = new Google_Service_YouTube_VideoRecordingDetails();
$recordingDetails->setLocationDescription("United States of America");
$recordingDetails->setRecordingDate("2016-01-20T12:34:00.000Z");
$locationdetails = new Google_Service_YouTube_GeoPoint();
$locationdetails->setLatitude("38.8833");
$locationdetails->setLongitude("77.0167");
$recordingDetails->setLocation($locationdetails);
// Create a video status with privacy status. Options are "public", "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->setPrivacyStatus("public");
$status->setPublicStatsViewable(false);
$status->setEmbeddable(false); // Google defect still not editable https://code.google.com/p/gdata-issues/issues/detail?id=4861
// Create a YouTube video with snippet and status
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setRecordingDetails($recordingDetails);
$video->setStatus($status);
// Size of each chunk of data in bytes. Setting it higher leads faster upload (less chunks,
// for reliable connections). Setting it lower leads better recovery (fine-grained chunks)
$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,recordingDetails", $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);
/**
* Video has successfully been uploaded, now lets perform some cleanup functions for this video
*/
if ($status->status['uploadStatus'] == 'uploaded') {
// Actions to perform for a successful upload
}
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(true);
} else{
// #TODO Log error
echo 'Problems creating the client';
}
} catch(Google_Service_Exception $e) {
print "Caught Google service Exception ".$e->getCode(). " message is ".$e->getMessage();
print "Stack trace is ".$e->getTraceAsString();
}catch (Exception $e) {
print "Caught Google service Exception ".$e->getCode(). " message is ".$e->getMessage();
print "Stack trace is ".$e->getTraceAsString();
}
?>
It is when i encountered the error : Here is the return value
Caught Google service Exception 0 message is refresh token must be passed in or set as part of setAccessTokenStack trace is #0 /home/vol11_2/freecluster.eu/fceu_18534127/htdocs/vendor/google/apiclient/src/Google/Client.php(246): Google_Client->fetchAccessTokenWithRefreshToken(NULL) #1 /home/vol11_2/freecluster.eu/fceu_18534127/htdocs/api.php(29): Google_Client->refreshToken(NULL) #2 {main}
What might i have missed? Could it be possibly my files error?
I dont understand the line that says : refresh token must be passed in or set as part of setAccessTokenStack trace is #0
Can anyone guide me out?
Thanks ! :)
I am not able to load my video live streaming on YouTube. I have gone through the YouTube documentation, tried searching on Google but no result to get success.
I have a complete running PHP example code to stream video live on YouTube and video is broadcasting but message is
Please stand by, Starting Soon
I am using this code
<?php
// Call set_include_path() as needed to point to your client library.
require_once 'Google/Service/Resource.php';
require_once 'Google/Service.php';
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 = '**************';
$OAUTH2_CLIENT_SECRET = '****************';
$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 {
// Create an object for the liveBroadcast resource's snippet. Specify values
// for the snippet's title, scheduled start time, and scheduled end time.
$broadcastSnippet = new Google_Service_YouTube_LiveBroadcastSnippet();
$broadcastSnippet->setTitle('New Broadcast');
$broadcastSnippet->setScheduledStartTime('2015-04-15T00:00:00.000Z');
$broadcastSnippet->setScheduledEndTime('2015-04-16T00:00:00.000Z');
// Create an object for the liveBroadcast resource's status, and set the
// broadcast's status to "private".
$status = new Google_Service_YouTube_LiveBroadcastStatus();
$status->setPrivacyStatus('private');
// Create the API request that inserts the liveBroadcast resource.
$broadcastInsert = new Google_Service_YouTube_LiveBroadcast();
$broadcastInsert->setSnippet($broadcastSnippet);
$broadcastInsert->setStatus($status);
$broadcastInsert->setKind('youtube#liveBroadcast');
// Execute the request and return an object that contains information
// about the new broadcast.
$broadcastsResponse = $youtube->liveBroadcasts->insert('snippet,status',
$broadcastInsert, array());
// Create an object for the liveStream resource's snippet. Specify a value
// for the snippet's title.
$streamSnippet = new Google_Service_YouTube_LiveStreamSnippet();
$streamSnippet->setTitle('New Stream');
// Create an object for content distribution network details for the live
// stream and specify the stream's format and ingestion type.
$cdn = new Google_Service_YouTube_CdnSettings();
$cdn->setFormat("1080p");
$cdn->setIngestionType('rtmp');
// Create the API request that inserts the liveStream resource.
$streamInsert = new Google_Service_YouTube_LiveStream();
$streamInsert->setSnippet($streamSnippet);
$streamInsert->setCdn($cdn);
$streamInsert->setKind('youtube#liveStream');
// Execute the request and return an object that contains information
// about the new stream.
$streamsResponse = $youtube->liveStreams->insert('snippet,cdn',
$streamInsert, array());
// Bind the broadcast to the live stream.
$bindBroadcastResponse = $youtube->liveBroadcasts->bind(
$broadcastsResponse['id'],'id,contentDetails',
array(
'streamId' => $streamsResponse['id'],
));
$htmlBody = '';
$htmlBody .= "<h3>Added Broadcast</h3><ul>";
$htmlBody .= sprintf('<li>%s published at %s (%s)</li>',
$broadcastsResponse['snippet']['title'],
$broadcastsResponse['snippet']['publishedAt'],
$broadcastsResponse['id']);
$htmlBody .= '</ul>';
$htmlBody .= "<h3>Added Stream</h3><ul>";
$htmlBody .= sprintf('<li>%s (%s)</li>',
$streamsResponse['snippet']['title'],
$streamsResponse['id']);
$htmlBody .= '</ul>';
$htmlBody .= "<h3>Bound Broadcast</h3><ul>";
$htmlBody .= sprintf('<li>Broadcast (%s) was bound to stream (%s).</li>',
$bindBroadcastResponse['id'],
$bindBroadcastResponse['contentDetails']['boundStreamId']);
$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 {
// 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>Bound Live Broadcast</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
Creating Broadcast with snippet and status I.e insert method.
Creating Live Stream with cdn (1080p, rtmp) and snippet with I.e insert.
Binding these together with broadcast bind method.
When I go to my https://www.youtube.com/my_live_events it is showing new event created, but I am not getting where is cam missing to use live streaming.
When you create your Live Stream object in step 2, an ingestionAddress will be returned in the response under cdn -> ingestionInfo. This is your RTMP endpoint where you need to send your video, using the streamName returned as the stream key.
Your response will look something like this (I've obfuscated some of my personal YouTube info):
{
cdn = {
format = 480p;
ingestionInfo = {
backupIngestionAddress = "rtmp://b.rtmp.youtube.com/live2?backup=1";
ingestionAddress = "rtmp://a.rtmp.youtube.com/live2";
streamName = "xxxxxx";
};
ingestionType = rtmp;
};
etag = "\"xxxxxx\"";
id = "xxxxxx";
kind = "youtube#liveStream";
snippet = {
channelId = "xxxxxx";
description = "";
publishedAt = "2015-04-15T14:33:43.000Z";
title = "live_stream_test";
};
}
Relevant documentation here.
I am trying to use Google's OAuth2 API. In their generic documentation, they mention a call called UserInfo: http://code.google.com/apis/accounts/docs/OAuth2Login.html#userinfocall , which would allow me to retrieve user ids, email, name and other basic stuff.
However I cannot find it in their PHP client library: https://code.google.com/p/google-api-php-client/
Where is it?
The Google OAuth2 API has changed - here is how you fetch user information nowadays:
<?php
require_once('google-api-php-client-1.1.7/src/Google/autoload.php');
const TITLE = 'My amazing app';
const REDIRECT = 'https://example.com/myapp/';
session_start();
$client = new Google_Client();
$client->setApplicationName(TITLE);
$client->setClientId('REPLACE_ME.apps.googleusercontent.com');
$client->setClientSecret('REPLACE_ME');
$client->setRedirectUri(REDIRECT);
$client->setScopes(array(Google_Service_Plus::PLUS_ME));
$plus = new Google_Service_Plus($client);
if (isset($_REQUEST['logout'])) {
unset($_SESSION['access_token']);
}
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
error_log('The session state did not match.');
exit(1);
}
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
header('Location: ' . REDIRECT);
}
if (isset($_SESSION['access_token'])) {
$client->setAccessToken($_SESSION['access_token']);
}
if ($client->getAccessToken() && !$client->isAccessTokenExpired()) {
try {
$me = $plus->people->get('me');
$body = '<PRE>' . print_r($me, TRUE) . '</PRE>';
} catch (Google_Exception $e) {
error_log($e);
$body = htmlspecialchars($e->getMessage());
}
# the access token may have been updated lazily
$_SESSION['access_token'] = $client->getAccessToken();
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$body = sprintf('<P>Login</P>',
$client->createAuthUrl());
}
?>
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE><?= TITLE ?></TITLE>
</HEAD>
<BODY>
<?= $body ?>
<P>Logout</P>
</BODY>
</HTML>
Do not forget to -
Get web client id and secret at Google API console
Authorize the https://example.com/myapp/ at the same place
You can find official examples at Youtube GitHub.
The PHP client was updated: https://code.google.com/p/google-api-php-client/issues/detail?id=43
I have posted a solution that works for me, a patch to the Google PHP client library to retrieve UserInfo, in this similar question: How to identify a Google OAuth2 user?