YouTube API v3 - Direct Upload to Native Channel

since YouTube v2 API is becoming obsolete I need to upgrade to v3.

With v2, I also used the legacy ClientLogin verification method ( http://bit.ly/v2_ClientLogin_authentification ) to authenticate and then upload custom videos to my YouTube channel.

With v3, I tried to authenticate using a service account with the same codebase as here.

PHP Youtube API v3 - Direct Download - Unauthorized Message

and I get the same error message from the API endpoint:

Error while calling POST https://www.googleapis.com/youtube/v3/videos?part=status%2Csnippet : (401) Unauthorized

I also verified through Google tokeninfo ( https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=[ACCESS_TOKEN] ) that the access token is valid:

{ "issued_to": "***.apps.googleusercontent.com", "audience": "***.apps.googleusercontent.com", "scope": "https://www.googleapis.com/auth/youtube", "expires_in": 3592, "access_type": "offline" } 

All YouTube examples I found are based on OAuth2 and user authorization. (e.g. here: http://bit.ly/yt-api-example-videoupload ). But this is not the way I want: the user should not see "Please authorize what.de to upload videos to YouTube" And the videos should be uploaded to my YT channel instead of them.

If there is no way to use the API service account for this, could you give me a hint how to do this with OAuth2? :-)

Here is my current code:

 /** Config */ $private_key_password = 'notasecret'; $private_key_file = '***.p12'; $applicationName = '***'; $client_secret = '***'; // <--- WHERE IS THAT CLIENT_SECRET COMING FROM? Secret accounts do not have a client secret? $client_id = '***.apps.googleusercontent.com'; $service_mail = '***@developer.gserviceaccount.com'; $scope = 'https://www.googleapis.com/auth/youtube'; $url_youtube_token = 'https://accounts.google.com/o/oauth2/token'; $jwt = new Google_Auth_AssertionCredentials($service_mail, $scope, $private_key_file, $private_key_password, $url_youtube_token); $jwt_assertion = $jwt->generateAssertion(); $data = array ( 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt_assertion, ); $options = array ( 'http' => array ( 'header' => "Content-type: application/x-www-form-urlencoded\r\n", 'method' => 'POST', 'content' => http_build_query($data), ), ); $context = stream_context_create($options); $result = file_get_contents($url_youtube_token, false, $context); //var_dump($result); die(); try{ // Client init $client = new Google_Client(); $client->setClientId($client_id); //$client->setClientSecret($client_secret); // <-- See above $client->setApplicationName($applicationName); $client->setAccessToken($result); if ($client->getAccessToken()) { if($client->isAccessTokenExpired()) { // @TODO Log error echo 'Access Token Expired!!<br/>'; // Debug } $youtube = new Google_Service_Youtube($client); $videoPath = "./test.mp4"; // Create a snipet with title, description, tags and category id $snippet = new Google_Service_YouTube_VideoSnippet(); $snippet->setTitle("fmgonzalez test " . time()); $snippet->setDescription("fmgonzalez test " . time() ); $snippet->setTags(array("tag1", "tag2")); // Numeric video category. See // https://developers.google.com/youtube/v3/docs/videoCategories/list $snippet->setCategoryId("22"); // Create a video status with privacy status. Options are "public", "private" and "unlisted". $status = new Google_Service_YouTube_VideoStatus(); $status->privacyStatus = "public"; // 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; // Create a MediaFileUpload with resumable uploads $insertRequest = $youtube->videos->insert("status,snippet", $video); $media = new Google_Http_MediaFileUpload ( $client, $insertRequest, 'video/*', null, true, $chunkSizeBytes ); $media->setFileSize(filesize($videoPath)); // Create a video insert request $insertResponse = $youtube->videos->insert("status,snippet", $video, array('mediaUpload' => $media)); $uploadStatus = false; // Read file and upload chunk by chunk $handle = fopen($videoPath, "rb"); $cont = 1; while (!$uploadStatus && !feof($handle)) { $chunk = fread($handle, $chunkSizeBytes); $uploadStatus = $media->nextChunk($insertResponse, $chunk); echo 'Chunk ' . $cont . ' uploaded <br/>'; $cont++; } fclose($handle); echo '<br/>OK<br/>'; } else { // @TODO Log error echo 'Problems creating the client'; } } catch(Google_Service_Exception $e) { print "Caught Google service Exception ".$e->getCode(). " message is <br>".$e->getMessage(). " <br>"; //print "Stack trace is ".$e->getTraceAsString(); } catch (Exception $e) { echo $e->getMessage(); } ?> 
+5
source share
1 answer

Unable to access YouTube API with service account

Issue 5370: Youtube v3 Access to Google Apps Account

You will need to use Oauth2. You will only need to authenticate once. Save the update token using offline access. then you can use it to run the script.

 $client->setAccessType('offline'); // Gets us our refreshtoken 
+1
source

All Articles