Я пытаюсь направить видео на Youtube с помощью API v3.
Я использую сценарий учетной записи службы ( https://developers.google.com/accounts/docs/OAuth2?hl=es&csw=1#scenarios ), и я решил некоторые проблемы в библиотеке google-api-php-client (для прочитайте файл p12 и, чтобы избежать isAccessTokenExpired, всегда возвращайте false).
<?php /** Config */ $private_key_password = 'notasecret'; $private_key_file = 'xxxxxxxx-privatekey.p12'; $applicationName = 'xxxxx-youtube'; $client_secret = 'CLIENT_SECRET'; $client_id = 'xxxxxxxxxxxxx.apps.googleusercontent.com'; $service_mail = 'xxxxxxxxxxx@developer.gserviceaccount.com'; $public_key = 'xxxxxxxxxxx'; /** Constants */ $scope = 'https://www.googleapis.com/auth/youtube'; $url_youtube_token = 'https://accounts.google.com/o/oauth2/token'; /** Create and sign JWT */ $jwt = new Google_AssertionCredentials($service_mail, $scope, $private_key_file, $private_key_password, $url_youtube_token); $jwt_assertion = $jwt->generateAssertion(); /** Use JWT to request token */ $data = array( 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt_assertion, ); // use key 'http' even if you send the request to https://... $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);
В этот момент у меня есть токен доступа в json-ответе следующим образом:
{ "access_token" : "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M", "token_type" : "Bearer", "expires_in" : 3600 }
без полей «created», «refresh_token» и «id_token». Поэтому я установил метод setAccessToken в классе Google_OAuth2, установив поле «created» в time (), если он не установлен. В противном случае isAccessTokenExpired всегда возвращает false.
Теперь давайте загрузим файл.
try{ // Client init $client = new Google_Client(); $client->setClientId($client_id); $client->setClientSecret($client_secret); $client->setApplicationName($applicationName); $client->setAccessToken($result); if ($client->getAccessToken()) { if($client->isAccessTokenExpired()) { // @TODO Log error echo 'Access Token Expired!!<br/>'; // Debug } $youtube = new Google_YoutubeService($client); $videoPath = "./test.mp4"; // Create a snipet with title, description, tags and category id $snippet = new Google_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_VideoStatus(); $status->privacyStatus = "public"; // Create a YouTube video with snippet and status $video = new Google_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 $media = new Google_MediaFileUpload('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_ServiceException $e) { print "Caught Google service Exception ".$e->getCode(). " message is ".$e->getMessage(). " <br>"; print "Stack trace is ".$e->getTraceAsString(); }catch (Exception $e) { echo $e->getMessage(); }
Но я получаю сообщение «Не удалось запустить возобновляемую загрузку» .
Отладка, метод getResumeUri в Google_MediaFileUpload У меня есть этот орган ответа:
"error": { "errors": [ { "domain": "youtube.header", "reason": "youtubeSignupRequired", "message": "Unauthorized", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Unauthorized" }
Я нашел примеры о других сценариях, но не об этом.
Что делать, чтобы, наконец, загрузить видеофайл? Любой пример об этом сценарии?
Заранее спасибо.
Это может показаться тривиальным, но вы создали хотя бы один канал в учетной записи, на которую хотите загрузить видео. Я использовал почти то же обходное решение, что и для acceess_token, после чего столкнулся с той же проблемой, пока не зашел в раздел загрузки учетной записи Youtube и не увидел, что сообщение создало по крайней мере один канал перед загрузкой видео. Надеюсь, поможет.
Ответ на ошибку, который вы получаете, по дизайну. Google не разрешает доступ к API Youtube через учетные записи служб.
Учетные записи служб не работают для вызовов API данных YouTube, потому что учетные записи служб требуют связанного канала YouTube, и вы не можете связывать новые или существующие каналы с учетными записями служб. Если вы используете учетную запись службы для вызова API данных YouTube, сервер API возвращает ошибку с типом ошибки, установленным для несанкционированного доступа, и причина, установленная для youtubeSignupRequired .