as YouTube v2 API is getting deprecated I need to migrate to v3.
With v2 I used the also deprecated ClientLogin authentication method to authenticate and then upload user videos to my YouTube channel.
With v3 I tried to authenticate with a service account, with the same codebase used here
PHP Youtube API v3 - Direct Upload - Unauthorized message
and I'm getting the same error message from the API endpoint:
Error calling POST https://www.googleapis.com/youtube/v3/videos?part=status%2Csnippet: (401) Unauthorized
I also checked via Google's 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. But that's not the way I want: The user shouldn't see any "Please authorize whatever.de to upload YouTube videos" AND the videos should be uploaded to my YT channel instead of theirs.
If there's no possibilty to use an API service account for that, could you please give me a hint how to do that with OAuth2? :-)
Here's 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!!
'; // 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
';
$cont++;
}
fclose($handle);
echo '
OK
';
}
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)
{
echo $e->getMessage();
}
?>