YouTube API v3 - 直接上传到自己的频道
YouTube API v3 - Direct upload to own channel
由于 YouTube v2 API 即将弃用,我需要迁移到 v3。
对于 v2,我使用同样已弃用的 ClientLogin (http://bit.ly/v2_ClientLogin_authentification) 身份验证方法进行身份验证,然后将用户视频上传到我的 YouTube 频道。
对于 v3,我尝试使用 服务帐户 进行身份验证,这里使用的是相同的代码库
PHP Youtube API v3 - Direct Upload - Unauthorized message
并且我从 API 端点收到相同的错误消息:
Error calling POST https://www.googleapis.com/youtube/v3/videos?part=status%2Csnippet: (401) Unauthorized
我也通过Google的令牌信息进行了检查
(https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=[ACCESS_TOKEN]) 访问令牌有效:
{
"issued_to": "***.apps.googleusercontent.com",
"audience": "***.apps.googleusercontent.com",
"scope": "https://www.googleapis.com/auth/youtube",
"expires_in": 3592,
"access_type": "offline"
}
我找到的所有 YouTube 示例均基于 OAuth2 和用户授权。 (就像这里的这个:http://bit.ly/yt-api-example-videoupload)。但这不是我想要的方式:用户不应该看到任何 "Please authorize whatever.de to upload YouTube videos" AND 视频应该上传到我的 YT 频道而不是他们的。
如果无法为此使用 API 服务帐户,您能否提示我如何使用 OAuth2 执行此操作? :-)
这是我当前的代码:
/** 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();
}
?>
无法使用服务帐户访问 YouTube API
Issue 5370: Youtube v3 Google Service Account Access
您将需要使用 Oauth2您只需要验证一次。使用离线访问保存您的刷新令牌。然后您可以将其用于 运行 您的脚本。
$client->setAccessType('offline'); // Gets us our refreshtoken
由于 YouTube v2 API 即将弃用,我需要迁移到 v3。
对于 v2,我使用同样已弃用的 ClientLogin (http://bit.ly/v2_ClientLogin_authentification) 身份验证方法进行身份验证,然后将用户视频上传到我的 YouTube 频道。
对于 v3,我尝试使用 服务帐户 进行身份验证,这里使用的是相同的代码库
PHP Youtube API v3 - Direct Upload - Unauthorized message
并且我从 API 端点收到相同的错误消息:
Error calling POST https://www.googleapis.com/youtube/v3/videos?part=status%2Csnippet: (401) Unauthorized
我也通过Google的令牌信息进行了检查 (https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=[ACCESS_TOKEN]) 访问令牌有效:
{
"issued_to": "***.apps.googleusercontent.com",
"audience": "***.apps.googleusercontent.com",
"scope": "https://www.googleapis.com/auth/youtube",
"expires_in": 3592,
"access_type": "offline"
}
我找到的所有 YouTube 示例均基于 OAuth2 和用户授权。 (就像这里的这个:http://bit.ly/yt-api-example-videoupload)。但这不是我想要的方式:用户不应该看到任何 "Please authorize whatever.de to upload YouTube videos" AND 视频应该上传到我的 YT 频道而不是他们的。
如果无法为此使用 API 服务帐户,您能否提示我如何使用 OAuth2 执行此操作? :-)
这是我当前的代码:
/** 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();
}
?>
无法使用服务帐户访问 YouTube API
Issue 5370: Youtube v3 Google Service Account Access
您将需要使用 Oauth2您只需要验证一次。使用离线访问保存您的刷新令牌。然后您可以将其用于 运行 您的脚本。
$client->setAccessType('offline'); // Gets us our refreshtoken