PHP API Youtube Uploads, exception: Falha ao iniciar o upload subseqüente, o upload deve ser enviado para o URL de upload

Estou tentando criar um aplicativo de servidor para fazer o upload de vídeos para o YouTube. No meu aplicativo de servidor, o usuário pode fazer o upload de um vídeo diretamente no meu canal do YouTube para torná-lo público.

insira a descrição da imagem aqui

  1. A parte do meu aplicativo adquire o vídeo e o envia para o meu servidor.
  2. Meu servidor usa a API do YouTube para fazer o upload do vídeo no meu canal do YouTube.

Para fazer isso funcionar, criei uma aplicação Web falsa que pode capturar o token de atualização gerado e eu o armazenei em um arquivo key.txt

 {"access_token":"MYTOKEN","token_type":"Bearer","expires_in":3600,"created":1435654774} 

O script upload_video.php atualizará automaticamente o arquivo "key.txt" se access_token estiver desatualizado. Este é o código de upload_video.php :

 $key = file_get_contents('key.txt'); $application_name = 'YouTube_Upload'; $client_secret = 'MY_CLIENT_SECRET'; $client_id = 'MY_CLIENT_ID'; $scope = array('https://www.googleapis.com/auth/youtube.upload', 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtubepartner'); $videoPath = "Test.f4v"; $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 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('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('unlisted'); // 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 */ if ($status->status['uploadStatus'] == 'uploaded') { // Actions to perform for a successful upload // ...... } // If 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 "Google_Service_Exception ".$e->getCode(). " message is ".$e->getMessage(); print "Stack trace is ".$e->getTraceAsString(); }catch (Exception $e) { print "Exception ".$e->getCode(). " message is ".$e->getMessage(); print "Stack trace is ".$e->getTraceAsString(); } 

Quando o script é executado, ele aumenta essa exceção:

 Exception 0 message is Failed to start the resume-able upload (HTTP 400: global, Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable)Stack trace is #0 D:\xampp\htdocs\youtube\src\Google\Http\MediaFileUpload.php(136): Google_Http_MediaFileUpload->getResumeUri() #1 D:\xampp\htdocs\youtube\resumable_upload.php(100): Google_Http_MediaFileUpload->nextChunk('\x00\x00\x00\x1Cftypf4v \x00\x00\x00...') #2 {main} 

aumento de exceção em getResumeUri() (linha 281) em Google_Http_MediaFileUpload , eu tenho var dump a resposta do google

 Google_Http_Request Object ( [batchHeaders:Google_Http_Request:private] => Array ( [Content-Type] => application/http [Content-Transfer-Encoding] => binary [MIME-Version] => 1.0 ) [queryParams:protected] => Array ( [part] => status,snippet [uploadType] => resumable ) [requestMethod:protected] => POST [requestHeaders:protected] => Array ( [content-type] => application/json; charset=UTF-8 [authorization] => Bearer XXXXXXXXXXXXXXXX [content-length] => 187 [x-upload-content-type] => video/* [x-upload-content-length] => 10201286 [expect] => ) [baseComponent:protected] => https://www.googleapis.com//upload [path:protected] => /youtube/v3/videos [postBody:protected] => {"snippet":{"categoryId":"22","description":"A video tutorial on how to upload to YouTube","tags":["youtube","tutorial"],"title":"A tutorial video"},"status":{"privacyStatus":"unlisted"}} [userAgent:protected] => [canGzip:protected] => [responseHttpCode:protected] => 400 [responseHeaders:protected] => Array ( [x-guploader-uploadid] => XXXXXXXXXXXXXXXXXXXXXXXXXX [location] => https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable [vary] => Origin X-Origin [content-type] => application/json; charset=UTF-8 [content-length] => 468 [date] => Fri, 10 Jul 2015 09:54:30 GMT [server] => UploadServer [alternate-protocol] => 443:quic,p=1 ) [responseBody:protected] => { "error": { "errors": [ { "domain": "global", "reason": "wrongUrlForUpload", "message": "Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable" } ], "code": 400, "message": "Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable" } } [expectedClass:protected] => Google_Service_YouTube_Video [expectedRaw:protected] => [accessKey] => ) 

O que está errado? Obrigado por qualquer ajuda e desculpe pelo inglês ruim.

Isso parece ser um problema com PHP Client Library of Google API. Vá para GOOGLE_LIB_PATH / Http / MediaFileUpload.php e substitua esta linha:

 $this->request->setBaseComponent($base . '/upload'); 

Com este:

 $this->request->setBaseComponent($base . 'upload'); 

Tente novamente e compartilhe os resultados. Eu enfrentei um problema semelhante com o Google Pubsub API, onde o caminho da API definido pela biblioteca estava incorreto.

Espero que você precise de Uploads Resumíveis ( https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol )

Em seguida, use isso sem qualquer modificação.

Verifique também se o formato de vídeo é suportado em https://support.google.com/youtube/troubleshooter/2888402?hl=pt-BR

Existe um método do google para obter o token de atualização, então em vez de usar json_decode:

 $newToken = json_decode($client->getAccessToken()); $client->refreshToken($newToken->refresh_token); 

Você pode fazer :

 $client->refreshToken( $client->getRefreshToken() ); 

Isto é o que testei até agora e funcionava bem.

 $key = trim(file_get_contents('key.txt')); $scope = 'https://www.googleapis.com/auth/youtube';