2014-02-12 1 views
4

API v3을 사용하여 Youtube에 동영상을 직접 업로드하려고합니다.PHP Youtube API v3 - 직접 업로드 - 권한이없는 메시지

내가 서비스 계정 시나리오 (https://developers.google.com/accounts/docs/OAuth2?hl=es&csw=1#scenarios)를 사용하고, 나는 구글-API-PHP 클라이언트 라이브러리합니다 (P12 파일을 읽을 수와 isAccessTokenExpired 항상 false를 돌려 피하기 위해)에서 몇 가지 문제를 해결했다. 나는이 같은 JSON 응답에서 액세스 토큰을 가지고 그 시점에서

<?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 = '[email protected]'; 
$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); 

:

{ 
    "access_token" : "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M", 
    "token_type" : "Bearer", 
    "expires_in" : 3600 
} 

은 "창조", "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(); 
    } 

는하지만 메시지 "를 재개 업로드를 시작하지 못했습니다"는 을받을 수 있습니다.

디버깅, 나는이 응답 본문을 가지고 Google_MediaFileUpload의 방법 getResumeUri : 다른 시나리오에 대한하지만 이것에 대한

"error": { 
    "errors": [ 
    { 
     "domain": "youtube.header", 
     "reason": "youtubeSignupRequired", 
     "message": "Unauthorized", 
     "locationType": "header", 
     "location": "Authorization" 
    } 
    ], 
    "code": 401, 
    "message": "Unauthorized" 
} 

내가 찾은 예.

마지막으로 비디오 파일을 업로드하려면 어떻게해야합니까? 이 시나리오에 대한 예가 있습니까?

미리 감사드립니다.

+0

나는 정확하게 토큰 만료를 피하기 위해 동일한 토큰 필드에 추가하고, 실제 업로드와 똑같은 문제 (인증되지 않은)를 가지고 있습니다. 결국이 문제를 해결할 수 있었습니까? 그렇다면 어떻게? – Claud

답변

3

동영상을 업로드하려는 계정에 최소한 하나의 채널을 만들었습니까? acceess_token에 대한 해결 방법과 거의 동일한 해결 방법을 사용하여 YouTube 계정 업로드 섹션에 가서 동영상을 업로드하기 전에 적어도 하나의 채널을 만드는 메시지를 볼 때까지 동일한 문제가 발생했습니다. 희망이 도움이됩니다.

2

오류 응답은 의도적으로 설계된 동작입니다. Google은 서비스 계정을 통한 YouTube API 액세스를 허용하지 않습니다. 유튜브 데이터 API 작동하지 않습니다

https://developers.google.com/youtube/v3/guides/moving_to_oauth#service-accounts-do-not-work-with-the-youtube-api

서비스 계정은 때문에 서비스 계정은 관련 YouTube 채널을 필요로 전화하면 사용자는 서비스 계정하지 연관 신규 또는 기존 채널을 할 수 있습니다. YouTube Data API를 호출 할 서비스 계정을 사용하는 경우 는 API 서버는 로 설정 무단로 설정 오류 유형과 그 이유에 오류가을 youtubeSignupRequired 반환합니다.