Dec 2014 – Please note this post is based on the 1.0.5 version of the API. If you are using the latest version you’ll need to update file paths as the file/folder structure has changed significantly.
Many bothans died to bring you this information. And when I say bothans, I refer of course to brain cells that have died as result of me smashing my head against the YouTube api.
To make this work, you’ll need to create a dummy web application that can capture the refresh token generated when you authorise your app. You can read a detailed explanation of what we’ll be doing and how the OAuth process works here.
This implementation has no requirements for any PHP frameworks (such as Zend). It is a barebones implementation based off the documentation for the YouTube V3 API utilising the Google PHP API client.
Creating your project
- You’ll need to head over to https://console.developers.google.com/ and create a new project.
- Then go and enable the YouTube Data API – (Your Project > APIS & AUTH > APIs)
- We’ll now need to create some credentials. Go to Your Project > APIS & AUTH > Credentials
- Click “Create new Client ID” and then under “Application Type” select “Web Application”.
- You’ll then need to enter your JavaScript origin and authorised redirect URI. I just set this to localhost, but you can set it to where ever you want.
- We’ve now created our client ID, we just need to fill in the Consent Screen. We can do this by navigating to Your Project > APIS & AUTH > Consent Screen. Once you’re on this page, ensure you fill out all the required fields (Email Address and Product Name).
- Hurray, we’ve created our project.
Getting your refresh token
I used the following PHP script as my dummy application to generate the OAuth token.
This script utilises Google APIs Client Library for PHP. You’ll need to download and install it a directory that can be read using the below script.
<?php // Call set_include_path() as needed to point to your client library. set_include_path($_SERVER['DOCUMENT_ROOT'] . '/directory/to/google/api/'); 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 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 = 'XXXXXXX.apps.googleusercontent.com'; $OAUTH2_CLIENT_SECRET = 'XXXXXXXXXX'; $REDIRECT = 'http://localhost/oauth2callback.php'; $APPNAME = "XXXXXXXXX"; $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'); // 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 '<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 <a href="$authUrl">authorise access</a> before proceeding.<p> END; } ?> <!doctype html> <html> <head> <title>My Uploads</title> </head> <body> <?php echo $htmlBody?> </body> </html>
Once you’ve got the script above and the Google Client Library API in place, load the script in your browser. You should be prompted to Authorise access before you can continue. Once you click on this link you should be taken through the steps to authorise your currently logged in Google account to access your new application.
Once it’s all done you should be redirected back to the localhost page, except now you will see a JSON string along the top of the page. Save this string somewhere for use later on. You might also notice if you’ve already uploaded videos to YouTube, a list of your videos on the page – just to confirm the access token works!
Saving your credentials
Now that you’ve received your refresh tokens create a text file called “the_key.txt” with the following information you’ve just received, it should look something similar to the format below:
{"access_token":"XXXXXXXXX","token_type":"Bearer", "expires_in":3600, "refresh_token":"XXXXXXX", "created":000000}
I suggest you write your refresh token down somewhere for safe keeping.
Creating the upload script
The script below is a very basic implementation. It requires the following file structure:
- Google/
- upload.php (the script below)
- the_key.txt (the file we created in the previous section)
- tutorial.mp4 (the video to upload)
The script will automatically update your “the_key.txt” file if your access_token is out of date.
Set the include path to ensure the Google API works correctly (line 3).
Replace the following variables with your own information:
- $application_name
- $client_secrect
- $client_id
- $videoPath
- $videoTitle
- $videoDescription
- $videoCategory
- $videoTags
$key = file_get_contents('the_key.txt'); set_include_path($_SERVER['DOCUMENT_ROOT'] . '/path-to-your-director/'); require_once 'Google/Client.php'; require_once 'Google/Service/YouTube.php'; $application_name = 'XXXXXX'; $client_secret = 'XXXXXXX'; $client_id = 'XXXXXXX.apps.googleusercontent.com'; $scope = array('https://www.googleapis.com/auth/youtube.upload', 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtubepartner'); $videoPath = "tutorial.mp4"; $videoTitle = "A tutorial video"; $videoDescription = "A video tutorial on how to upload to YouTube"; $videoCategory = "22"; $videoTags = array("youtube", "tutorial"); try{ // Client init $client = new Google_Client(); $client->setApplicationName($application_name); $client->setClientId($client_id); $client->setAccessType('offline'); $client->setAccessToken($key); $client->setScopes($scope); $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('the_key.txt', $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); // Create a video status with privacy status. Options are "public", "private" and "unlisted". $status = new Google_Service_YouTube_VideoStatus(); $status->setPrivacyStatus('private'); // Create a YouTube video with snippet and status $video = new Google_Service_YouTube_Video(); $video->setSnippet($snippet); $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", $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 upload, now lets perform some cleanup functions for this video */ if ($status->status['uploadStatus'] == 'uploaded') { // Actions to perform for a successful upload // $uploaded_video_id = $status['id']; } // 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(); }
Suggestions
As you can see, the script is very primitive, among other things, this script should not be located in a publicly accessible directory due to the obvious abuse that could occur. In my situation, I created a queue of files to upload and setup a cron to execute the script once an hour that would then check a directory for any files of a certain type (mp4) and then loop through and upload to YouTube. The method I described hasn’t been tested on files more than 10 x 400mb in size so I’m not sure what the impacts would be on your server for more files / larger sizes etc.
Hopefully that’s enough to get your started, if you have any questions feel free to ask :)
https://www.domsammut.com/?p=1142#comment-1269
#J.J.
Hello Dom,
Thanks for taking the time to share your knowledge on this with us!
I successfully obtained an access_token with your script, however when I try to upload a movie clip, I get the following error message:
Caught Google service Exception 0 message is Failed to start the resumable upload (HTTP 401: youtube.header, Unauthorized)Stack trace is #0 /var/www/html/externals/youtube_v3/src/Google/Http/MediaFileUpload.php(134): Google_Http_MediaFileUpload->getResumeUri() #1 /var/www/html/youtube_test/upload.php(89): Google_Http_MediaFileUpload->nextChunk(‘????ftypisom???…’) #2 {main}
Any idea what this could be?
Thank you and kind regards,
J.J.
https://www.domsammut.com/?p=1142#comment-1277
#Dom Sammut
Hey J.J.,
Thanks for the kind words.
If you haven’t already, can you have a look at this comment and the thread below it.
If the suggestions in that thread don’t help, can you
var_dump()
your$media
variable after line 80 on my example.Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1683
#Patrick
I got exactly the same error, below is I var dump $media:
object(Google_Http_MediaFileUpload)[32]
private ‘mimeType’ => string ‘video/*’ (length=7)
private ‘data’ => null
private ‘resumable’ => boolean true
private ‘chunkSize’ => int 1048576
private ‘size’ => int 219616
private ‘resumeUri’ => null
private ‘progress’ => int 0
private ‘client’ =>
object(Google_Client)[1]
private ‘auth’ =>
object(Google_Auth_OAuth2)[3]
private ‘assertionCredentials’ => null
private ‘state’ => null
private ‘token’ =>
array (size=5)
…
private ‘client’ =>
&object(Google_Client)[1]
private ‘io’ => null
private ‘cache’ => null
private ‘config’ =>
object(Google_Config)[2]
protected ‘configuration’ =>
array (size=7)
…
private ‘logger’ =>
object(Google_Logger_Null)[25]
protected ‘level’ => int 100
protected ‘logFormat’ => string ‘[%datetime%] %level%: %message% %context%
‘ (length=42)
protected ‘dateFormat’ => string ‘d/M/Y:H:i:s O’ (length=13)
protected ‘allowNewLines’ => boolean true
private ‘deferExecution’ => boolean true
protected ‘requestedScopes’ =>
array (size=3)
0 => string ‘https://www.googleapis.com/auth/youtube.upload’ (length=46)
1 => string ‘https://www.googleapis.com/auth/youtube’ (length=39)
2 => string ‘https://www.googleapis.com/auth/youtubepartner’ (length=46)
protected ‘services’ =>
array (size=0)
empty
private ‘authenticated’ => boolean false
private ‘request’ =>
object(Google_Http_Request)[41]
private ‘batchHeaders’ =>
array (size=3)
‘Content-Type’ => string ‘application/http’ (length=16)
‘Content-Transfer-Encoding’ => string ‘binary’ (length=6)
‘MIME-Version’ => string ‘1.0’ (length=3)
protected ‘queryParams’ =>
array (size=2)
‘part’ => string ‘status,snippet’ (length=14)
‘uploadType’ => string ‘resumable’ (length=9)
protected ‘requestMethod’ => string ‘POST’ (length=4)
protected ‘requestHeaders’ =>
array (size=2)
‘content-type’ => string ‘video/*’ (length=7)
‘authorization’ => string ‘Bearer ya29.DwFgfwoiKWReevLO2BqIBIHnSZMtixO3IB-0yf3WQbFBow_psWMwFpdH_j8wgdkKd2THJBZsB_uHDA’ (length=90)
protected ‘baseComponent’ => string ‘https://www.googleapis.com/upload’ (length=33)
protected ‘path’ => string ‘/youtube/v3/videos’ (length=18)
protected ‘postBody’ => string ‘{“snippet”:{“categoryId”:”22″,”tags”:[“arefilm”],”title”:”test”},”status”:{“privacyStatus”:”private”}}’ (length=102)
protected ‘userAgent’ => null
protected ‘canGzip’ => null
protected ‘responseHttpCode’ => null
protected ‘responseHeaders’ => null
protected ‘responseBody’ => null
protected ‘expectedClass’ => string ‘Google_Service_YouTube_Video’ (length=28)
public ‘accessKey’ => null
private ‘boundary’ => boolean false
private ‘httpResultCode’ => null
https://www.domsammut.com/?p=1142#comment-1684
#Dom Sammut
Hi Patrick,
I assume you’ve received the error in the comment you’ve replied to? I’ve checked the access token you supplied in your dump at it is valid (though it is soon to expire, which is expected).
Can you try uploading a small video file, something under 10mb? Can I also confirm you’re using version 1.0.5 of the API?
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1685
#Patrick
Hi Dom,
Just noticed that I am not using the correct version. Now it works! Billion thanks!
Thanks,
Patrick
https://www.domsammut.com/?p=1142#comment-1874
#Developer
Getting the following errors:
Caught Google service Exception 0 message is Failed to start the resumable uploadStack trace is #0 C:\xampp\htdocs\youtubev2\google-api-php-client-1.0.5-beta\src\Google\Http\MediaFileUpload.php(142): Google_Http_MediaFileUpload->getResumeUri() #1 C:\xampp\htdocs\youtubev2\upload2.php(102): Google_Http_MediaFileUpload->nextChunk(‘??? ftypisom???…’) #2 {main}
Note: I have installed a XAMPP on Server. The first part of key creation works fine and it displayed Video Name in the Channel.
I have changed library version as you mentioned in the comments.
Checked with media object and video size is also displayed.
https://www.domsammut.com/?p=1142#comment-1875
#Developer
I could solve my issue. It was related to my Youtube account.
I have printed different variables and responses in “src\Google\Http\MediaFileUpload.php -> getResumeUri()”. One of such output contains the text “reason” : “youtubeSignupRequired” Comments already contains the steps to solve this issue. I followed the steps and could solve it.
To test Video Uploading to Youtube, I created a new gmail account. Then login into Youtube using new Gmail. I created a Channel in Youtube because it doesn’t have any in the beginning. Then I moved back to code and started testing. What I remember is, the first step of generating Key worked fine. And I could see the “Video Name” in the output. Then after getting above error, I logged out from Youtube and login again. This time, a dialog box appears with a question “Use Yutube as “My Gmail xx Name” or “Youtube Profile Name I given as part of Channel creation”. I selected Gmail and now the issue is resolved. So even after gmail Sign In using Youtube, there is still possibility of the above error.
Thank you for the good article and your efforts to answer all comments.
https://www.domsammut.com/?p=1142#comment-1910
#birbal
i think this is outdated. i’m using google api v3. and in responce i get {“access_token”:”ya29.IAJBeu4xafxuf8s8ojtPKwOY5JMlzHXXQGrrWW2X8UvYGszaOv6r-VQIJfdUaWqx3iwQxdvMcg”,”token_type”:”Bearer”,”expires_in”:3599,”created”:1446466871} .
there is no refresh token which i’m looking for. i’m also trying to upload video on youtube channel from my development server
https://www.domsammut.com/?p=1142#comment-1911
#Dom Sammut
Hi Birbal,
No this isn’t outdated, refresh tokens are still used as per Google Documentation. I also re-ran the script and successfully harvested a token.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1913
#Fabio
hi Dom,
i have some trovel to ipload videos after token expired. only me use the app. not for other user. is like to upload the recorded videos on my local app to youtube. what im doing wrong?
https://www.domsammut.com/?p=1142#comment-1914
#Dom Sammut
Hi Fabio,
You’ll need to implement the refresh token which will in turn allow you to generate a new access token.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1135
#Cris
Hi,
Something is causing my token to expire.
My script is bulk uploading videos, before i was able to upload about 5k videos a day.
But after some days i’m getting token expired after about 1h of running script.
Any ideas?
https://www.domsammut.com/?p=1142#comment-1161
#Dom Sammut
Hey Cris,
Can you confirm that you are regenerating your access token if it is expired? If so can you provide the snippet of code that currently attempts to do this?
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1162
#Cris
I don’t know how to regenerate it, without accesing token.php and copy paste it to my the_key.txt all manually.
https://www.domsammut.com/?p=1142#comment-1165
#Dom Sammut
Hey Cris,
Can you confirm the following code is executing?
https://www.domsammut.com/?p=1142#comment-1226
#Cris
Yes I have that in my code.
This what i got from google, when enter token.php
“An client error occurred: The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved.”
https://www.domsammut.com/?p=1142#comment-1241
#Dom Sammut
Hi Cris,
Can you var_dump():
$newToken
$client->refreshToken
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1242
#Cris
PHP Notice: Undefined property: stdClass::$refresh_token in /home…./Google/functions.php on line 420
Notice: Undefined property: stdClass::$refresh_token in /home/…./Google/functions.php on line 420
Caught Google service Exception 400 message is Error refreshing the OAuth2 token, message: ‘{
“error” : “invalid_request”,
“error_description” : “Missing required parameter: refresh_token”
Thx
https://www.domsammut.com/?p=1142#comment-1265
#Dom Sammut
Hey Cris,
Can you
var_dump($client->getAccessToken())
just before thefile_put_contents()
.You can check if the new token is valid by using this link: https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=xxxyourtokenherexxx
Can you also confirm that the “the_key.txt” file also has the refresh token value in it.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1267
#Cris
Hi, var_dump(), output is blank.
No refresh token is added to the_key.txt,
Also it’s not showing EXPIRED or NOT EXPIRED, but it’s giving error on line 196.
Notice: Undefined property: stdClass::$refresh_token in /home/vhosts/…./functions.php on line 196
Caught Google service Exception 400 message is Error refreshing the OAuth2 token, message: ‘{
“error” : “invalid_request”,
“error_description” : “Missing required parameter: refresh_token”
————————————————
https://www.domsammut.com/?p=1142#comment-1276
#Dom Sammut
Hi Cris,
If you don’t have a refresh token in your “the_key.txt”, you’ll need to run the Getting your refresh token part of the guide again as it would appear you’ve lost your refresh token at some point along the way.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1117
#Luna
Hi. I was able to figure out how to upload a video to my youtube channel with the api thanks to you and this article. Now I’m trying to figure out the api for discogs but I’m completely lost. Basically, I’d like to let users of my website complete a search by artist or song title and the results show up. I signed up at discogs and recieved a consumer key and a consumer secret, however, I don’t know what to do from there. I read all of the developer pages and attempted to interpret the single php oauth example from github, but I was unsuccessful. I mainly know javascript but am learning some php. Could you help me out? Thanks.
https://www.domsammut.com/?p=1142#comment-1120
#Dom Sammut
Hey Luna,
I’m glad you’ve found this article useful. In regards to the discogs API. I’ve never even heard of that site until your comment. I won’t be of much help in attempting to find a solution for it. It appears they have good documentation so I’d suggest trying to find some similar examples or continue learning PHP as you’ve said you’re doing as they’re your best bets at this point.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1121
#Luna
Ok, thanks for the reply.
https://www.domsammut.com/?p=1142#comment-1100
#Avinash
Hi Dom,
I have got following error while executing your code.
Caught Google service Exception 0 message is Failed to start the resumable upload (HTTP 401: global, Invalid Credentials)Stack trace is #0 /mnt/hgfs/tapes/POC/youtube/google-api/src/Google/Http/MediaFileUpload.php(134): Google_Http_MediaFileUpload->getResumeUri() #1 /mnt/hgfs/tapes/POC/youtube/uploadOnYoutube_1.php(100): Google_Http_MediaFileUpload->nextChunk(‘????ftypisom???…’) #2 {main}
My vardump($media) object is
Can you please tell me what’s wrong with my code?
https://www.domsammut.com/?p=1142#comment-1103
#Dom Sammut
Hi Avinash,
If you’re receiving invalid credentials errors. I’d double check your tokens using the Google API to see exactly what the error is:
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=12345
Just replace the 12345 with the access token used in the request. Note these tokens are time sensitive so you’ll need to check the API within 1 hour of generation.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1129
#Avinash
I used suggested API and got following response,
Is my token is valid? but I still got the same error
Caught Google service Exception 0 message is Failed to start the resumable upload (HTTP 401: global, Invalid Credentials)Stack trace is #0 /mnt/hgfs/sepat/POC/youtube/google-api/src/Google/Http/MediaFileUpload.php(134): Google_Http_MediaFileUpload->getResumeUri() #1 /mnt/hgfs/sepat/POC/youtube/uploadOnYoutube_1.php(100): Google_Http_MediaFileUpload->nextChunk(‘????ftypmp42???…’) #2 {main}
https://www.domsammut.com/?p=1142#comment-1048
#Kipyegon Derricks
This is super, it worked for me perfectly after a few tweaks. Problem is it uploads two videos
https://www.domsammut.com/?p=1142#comment-864
#warswitcherLukas Vollmer
Hey, Dom.
As David already say, with the current Google PHP API client the script is no longer working. Google has updatet the folder structure. Could you plese upload your version of your Google PHP API client?
Thank you
https://www.domsammut.com/?p=1142#comment-865
#Dom Sammut
Hey Lukas,
Thanks for pointing this out. I’ll look to provide an updated version of my script in the next week. In the interim you can find all the previous version of Google PHP API client on GitHub. I would suggest using the 1.0.5 release.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-844
#Cris
Hi
Do you see any strange, in my $media dump?
I have same problem of: “failed to start resumable video”
=============
Thanks
Cris
https://www.domsammut.com/?p=1142#comment-845
#Dom Sammut
Hey Cris,
Having a very quick look, it would appear your title is too long. You can only have a maximum of 100 characters. You appear to have 139 characters. Just double check the limits for the snippet fields in the YouTube V3 API.
Can you provide the stack trace dump as well if you’re still running into issues?
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-850
#Cris
Hi,
Yes title is limited to 100 chars and description to 5000 bytes, also they can’t include chars like “” .
Thanks
https://www.domsammut.com/?p=1142#comment-860
#Dom Sammut
Hey Cris,
Once you made these changes where you able to successfully upload your video?
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-861
#Cris
Yes it’s working.
Not allowed chars are
https://www.domsammut.com/?p=1142#comment-854
#minionsvevo
Thank You Thank You Thank You :) I’m very happy…
https://www.domsammut.com/?p=1142#comment-1762
#Abuzar
HI,
I’ve just used google apis with help of your tutorial, and I must say it’s awesome. I’ve a question to ask.
Is there any way through which I can upload all videos to a specific channel?
currently videos are being uploaded on logged in user’s channel. I just want that whenever any user upload a video, it must be uploaded on my channel as user is using my platform.
Thanks in advance.
https://www.domsammut.com/?p=1142#comment-1763
#Dom Sammut
Hi Abuzar,
Thank you for the kind words.
In regards to your question, based on this tutorial, your users don’t have to be authenticate with YouTube, they should just be interacting with your web server. Your web server then handles the upload of those videos so they should only be uploading to the account you have authenticated server-side.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-786
#Filip
Hi, thanks for this tutorial. its help a lot.
But do you know how to implement the browser-based upload using only v3 api php without zend framework and without curl too?? Just youtube v3 api php.
I was searching for weeks for this implementation.
Thanks in advance!! it will help me…
https://www.domsammut.com/?p=1142#comment-789
#Dom Sammut
Hi Filip,
I haven’t had the need to build this, but it wouldn’t be too hard based off the existing code above. If you’re using the Google PHP API it’s underlying code utilises CURL to upload just so you’re aware.
I would also ensure that you don’t have the upload ability on a public-facing website as this potentially anyone can upload to your account (which could lead to your account getting banned). Ensure that there is authentication required before they are able to upload video(s).
As for the line-for-line implementation of this, I don’t have the time (or need) to build something like this. If you do come up with a solution, please share the final product or work in progress.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-809
#Filip
Hi, thanks for your fast response.
I didnt know about that v3 uses curl inside the api.
However, I still searching the solution because
I have all my code organized to use the api methods.
Thanks for the advice…
https://www.domsammut.com/?p=1142#comment-812
#Dom Sammut
Hi Filip,
I’m not exactly sure what you’re issue is then?
If you are able to use the Google PHP API you can follow my example in this post and implement a solution.
If your server has CURL disabled, I haven’t developed an alternative that runs without CURL and you won’t be able to use the Google API either, so you’d most likely have to start from scratch or write an extension of API for the upload function that utilizes an alternative method.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-746
#Webbho
How come I do not have the value ” refresh_token “: ” XXXXXXX ” in my output ?
https://www.domsammut.com/?p=1142#comment-751
#Dom Sammut
Hey Webbho,
Can you let me know what part of the script you’re up to?
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-2039
#Mario
I also did not get the refresh_token value in first attempt.
I added
$client->setApprovalPrompt('force');
in the line 34 of oauth2callback.php and its works now.
https://www.domsammut.com/?p=1142#comment-745
#Webbho
I get this error, ideas ?
Notice: Undefined property: stdClass::$refresh_token in /var/www/vhosts/…youtube.php on line 39 Fatal error: Uncaught exception ‘Google_Auth_Exception’ with message ‘Error refreshing the OAuth2 token, message: ‘{ “error” : “invalid_request”, “error_description” : “Missing required parameter: refresh_token” }” in /var/www/vhosts/…google-api-php-client-master/src/Google/Auth/OAuth2.php:345 Stack trace: #0 /var/www/vhosts/…google-api-php-client-master/src/Google/Auth/OAuth2.php(269): Google_Auth_OAuth2->refreshTokenRequest(Array) #1 /var/www/vhosts/…google-api-php-client-master/src/Google/Client.php(412): Google_Auth_OAuth2->refreshToken(NULL) #2 /var/www/vhosts/…youtube.php(39): Google_Client->refreshToken(NULL) #3 {main} thrown in /var/www/vhosts/…google-api-php-client-master/src/Google/Auth/OAuth2.php on line 345
https://www.domsammut.com/?p=1142#comment-890
#Fabb
Hi,
I have the same problem, how did you solve it?
https://www.domsammut.com/?p=1142#comment-670
#Jakub
Hello Dom,
I fixed the problem before was my categoryId I wrote it wrong like you said. A question about that the categoryID can be what numbers I want or there are specific id’s I didn’t understand this.
Second question I have to create a similar system to this but for videos in a database. I have to send a selected video from the DB from the customer to the youtube Chanel. Do you have any suggestion how to make this or something I can look it?
Thank you a lot for your help.
Cheers,
Jakub
https://www.domsammut.com/?p=1142#comment-671
#Dom Sammut
That’s great to hear. I think category numbers are region specific. To be honest, I just went to youtube and uploaded a video and inspected the category select box and picked the id from there.
In regards to creating a system, I can’t imagine it would be too difficult to create something basic. As to examples I don’t have any off the top of my head. You should be able to integrate the upload method relatively easily into an existing system.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-651
#sameer
Fatal error: Maximum execution time of 30 seconds exceeded in E:\xampp\htdocs\googleapi\src\Google\IO\Curl.php on line 80
https://www.domsammut.com/?p=1142#comment-652
#Dom Sammut
Hi Sameer,
You’ll need to provide a little more information than that.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-654
#Jakub
Hello,
I’m Jakub and I’m trying your script but when I arrived at that moment when there is the auth2callback I received object don’t found. I tried to create a file auth2callback.php but when open in the browser is empty without the refresh token,.
This is my code:
Thanks for help
https://www.domsammut.com/?p=1142#comment-656
#Dom Sammut
Hey Jakub,
I have a number of steps to check / get back to me with answers:
oauth2callback.php
file in your web browser it shows “Authorisation Required”?Cheers
Dom
https://www.domsammut.com/?p=1142#comment-657
#Jakub
Hello Dom,
The first part I fixed. I changed the callback to my directory in localhost and then works. Now I have this problem when I try to upload
Caught Google service Exception 0 message is Failed to start the resumable upload (HTTP 400: youtube.video, Bad Request)Stack trace is #0 /Applications/XAMPP/xamppfiles/htdocs/YoutubeKTF/Google/src/Google/Http/MediaFileUpload.php(134): Google_Http_MediaFileUpload->getResumeUri() #1 /Applications/XAMPP/xamppfiles/htdocs/YoutubeKTF/upload.php(95): Google_Http_MediaFileUpload->nextChunk('\x00\x00\x00\x18ftypmp42\x00\x00\x00...') #2 {main}
Can you explain the meaning of this?
Cheers
Jakub
https://www.domsammut.com/?p=1142#comment-658
#Dom Sammut
Hey Jakub,
Glad to hear you sorted out the first part.
Can you confirm that your script is reading in the
$key
file correctly. Can you alsovar_dump
your$media
variable after line 80 on my example.Also maybe try uploading a different video file to see if that makes any difference.
It might also be handy to have a look at code in the Google PHP API that threw the error:
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-659
#Jakub
Hey Dom,
I corrected the permission on that file and the var_dump output of $media is:
Caught Google service Exception 0 message is Failed to start the resumable upload (HTTP 400: youtube.video, Bad Request)Stack trace is #0 /Applications/XAMPP/xamppfiles/htdocs/YoutubeKTF/Google/src/Google/Http/MediaFileUpload.php(134): Google_Http_MediaFileUpload->getResumeUri() #1 /Applications/XAMPP/xamppfiles/htdocs/YoutubeKTF/upload.php(96): Google_Http_MediaFileUpload->nextChunk('\x00\x00\x00\x18ftypmp42\x00\x00\x00...') #2 {main}
Cheers
Jakub
https://www.domsammut.com/?p=1142#comment-660
#Dom Sammut
Hi Jakub,
It would appear from that dump, that your
$videoPath
isn’t referencing a video file. I’m basing this off the size parameter in the dump that has a value of 0.If you check
$media->setFileSize(filesize($videoPath));
on line 80 and ensure that it is outputting the correct file size.Let me know how that goes.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-661
#Jakub
Hey, really thanks for your help. I’m checked what you suggest and I received NULL. I have no idea how to fix it. I must put this video in youtube because is for a project at my company. The video is 8.4MB mp4 HD and the company wants the videos in this hight quality version so I need a solution to process files of this dimension to youtube if this is the main issue.
Thanks a lot.
https://www.domsammut.com/?p=1142#comment-666
#Dom Sammut
Hey Jakub,
8.4MB for a video isn’t a large size, so it shouldn’t be an issue related to that. I’d double check that you have specified a valid path (
$videoPath
) to your file if you’re receiving NULL. Also when youvar_dump(filesize($videoPath));
it should return a value around 8808038 (based on 8.4MB conversion to bytes).Cheers
Dom
https://www.domsammut.com/?p=1142#comment-668
#Jakub
Hello Dom,
The output of the $videoPath is the path of my video string(13) “video/1mb.mp4 and the other output like you said is the size int(1780768). I var_dump($media->setFileSize(filesize($videoPath)); and output is null.
I’m sending you my scripts so you can take a look what is wrong. Maybe I did something no correct.
Thanks a lot.
Cheers,
Jakub
http://laravel.io/bin/yLyk7 Index.php
http://laravel.io/bin/5a0eX Upload.php
http://laravel.io/bin/klG2e LogIn.php
https://www.domsammut.com/?p=1142#comment-669
#Dom Sammut
Hey Jakub,
$videoCategory must be an integer. It cannot be a string. You can read more about it here: https://developers.google.com/youtube/v3/docs/videoCategories/list.
You can use the number in my example “22”. See if that allows you to upload the vid.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1088
#Burak
Hi Dom
Thanks for the great doc! I have trouble creating the oauth2callback.php. Can you please give the code example for this?
I have uploaded the files to my server. Google says that “http://example.com” but you have written localhost, which one can I use? I do not use this at my own PC, I will use this in my remote webserver.
https://www.domsammut.com/?p=1142#comment-1089
#Dom Sammut
Hi Burak,
Thanks for the kind feedback.
In regards to creating the
oauth2callback.php
, the code is in this post. It is the first code example. If you read through the code, you’ll see this line (18):This should be the URL that you’ll be accessing the
oauth2callback.php
file in your web browser (note, you might run into problems usingfile://
).You should only need to use the
oauth2callback.php
file once to generate your access token that will also provide you with a refresh token. This can be done on your local machine or a web server.You can then save these values and generate new access tokens off your refresh token if you have an expired access token as demonstrated in the second code example (a crude implementation of a server-side automated YouTube video upload method).
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1094
#Cris
Hi,
How can I prevent user token expiration ?
Thanks
https://www.domsammut.com/?p=1142#comment-1095
#Dom Sammut
Hey Cris,
Are you referring to the Access Token? If so, the example provided checks to see if the access token is still valid, and if not, uses the refresh token we harvested to request a new one.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1907
#Master Icang
Hello Dom, i got the same error like sammer, but the information is provide just it, would you please help me?
https://www.domsammut.com/?p=1142#comment-1908
#Dom Sammut
Hi,
That is a PHP setting you’ll need to modify to increase the execution timeout. An example of this would be:
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-634
#David
I downloaded the library here: http://developers.google.com/api-client-library/php
Unfortunately I get the error Class ‘ Google_Service ‘ not found
It ‘ a problem of version of php ? I have the 5.3 and the 5.5
how can I fix it?
https://www.domsammut.com/?p=1142#comment-635
#Dom Sammut
Hey David,
It could be a couple things, ensure that you have PHP 5.3 or higher for the cryptographic algorithm requirements and class calls.
Have you double checked that the set_include_path() is pointing to the correct directory?
Alternatively can you pastebin your code or put it in a comment?
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-491
#kcode
Hi, today i try more example and i have an error, after the access token expired when i use the refresh token the response is like this
” Google_Auth_Exception: Error refreshing the OAuth2 token, message: ‘{ “error” : “invalid_grant” }'”
here is the peace of code i use to refresh the token, my refresh token is saved when i authenticate the app at first time
what the cause of the problem do i need to re-authenticate the app? or the refresh token is wrong?
Best Regards
Karim,
https://www.domsammut.com/?p=1142#comment-493
#Dom Sammut
Hey Karim,
You don’t need to re-authentic the app like you did when you harvested the refresh token. It doesn’t appear your using the demo script above. Have you ensured that you have correctly initialised the $client and passed in all the required parameters.
Has your script worked in the past after 3600 seconds of getting a valid access token?
Also double check your server clock is synced to the atomic clock. If your server time is out be even 30 seconds you can run into issues.
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-1979
#l
Hi Kcode,
i get the invalid grant error as well. Did you happen to fix it ?
$client->refreshToken($newToken->refresh_token);
this part is the problem eventhough im 100% sure my refresh token works because for 3600 seconds or an hour I was able to upload.
https://www.domsammut.com/?p=1142#comment-457
#kcode
thanks you for your helpful tutorial, i have some questions related to the access tokens,
i have created an application and run it from chrome and firefox, both of them give me a different refresh token,
witch one to use to generate my next token? can i use any of them?
does the access token related to the google account that authenticate my app?
https://www.domsammut.com/?p=1142#comment-458
#Dom Sammut
Hey kcode,
Yes running it from two different browsers will give you a different set of tokens, this is normal and either set can be used. In regards to your access relating to the google account that authenticated your app, yes the access / refresh tokens generated are for your google account.
Let me know if you have any further questions!
Cheers
Dom
https://www.domsammut.com/?p=1142#comment-478
#kcode
Thank you a lot, i run some example to understand how it works, in my test i capture two refresh tokens and both of them works well. i will try more examples
Thanks