2015-06-30 17 views
18

Tôi đang cố gắng tạo ứng dụng máy chủ để tải video lên YouTube. Trong ứng dụng máy chủ của tôi, người dùng có thể tải video trực tiếp lên kênh YouTube của tôi để công khai.Tải lên Youtube API PHP, ngoại lệ: Không thể bắt đầu tải lên lại, tải lên phải được gửi đến URL tải lên

enter image description here

  1. Phần client của ứng dụng của tôi mua lại video và tải lên nó vào máy chủ của tôi.
  2. Máy chủ của tôi sau đó sử dụng API YouTube để tải video lên kênh YouTube của tôi.

Để làm công việc này, tôi đã tạo ra một ứng dụng web giả có thể nắm bắt những dấu hiệu làm mới được tạo ra và tôi đã lưu trữ nó trong một tập tin key.txt

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

Kịch bản upload_video.php sẽ tự động cập nhật "key.txt" tập tin nếu access_token đã lỗi thời. Đây là mã từ 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(); 
} 

Khi kịch bản chạy, nó nâng cao ngoại lệ này:

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} 

ngoại lệ huy động vào getResumeUri() (dòng 281) trong Google_Http_MediaFileUpload, tôi đã var đổ phản hồi từ 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] => 
) 

Điều gì là sai? Cảm ơn bạn đã giúp đỡ và xin lỗi vì tiếng Anh xấu.

Trả lời

4

Điều này có vẻ là một vấn đề với Thư viện ứng dụng khách PHP API của Google. Tới GOOGLE_LIB_PATH/Http/MediaFileUpload.php và thay thế dòng này:

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

Với một cú này:

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

Vui lòng thử lại và chia sẻ các kết quả. Tôi đã gặp phải sự cố tương tự với API Google Pubsub nơi đường dẫn API được đặt bởi thư viện không chính xác.

+0

hoàn hảo, cảm ơn! – ar099968

+1

cố định trong các cam kết mới nhất trên github –

1

Tôi hy vọng bạn cần thể tiếp tục lại ơn (https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol)

Sau đó sử dụng this mà không sửa đổi bất kỳ.

Ngoài ra kiểm tra nếu định dạng video được hỗ trợ từ https://support.google.com/youtube/troubleshooter/2888402?hl=en

+0

Mã của tôi đã được lấy cảm hứng từ ví dụ về resumable_upload.php của google. – ar099968

+0

@ ar099968 Mã của bạn không thể nhận được Uri tiếp tục có nghĩa là nó không thể được tải lên như tiếp tục, như đã chỉ ra bởi Mithun –

+0

@FurhanShabir Tôi không hiểu. Tôi đã sử dụng một ví dụ có thể tiếp tục từ google ... – ar099968

1

Có một phương pháp google để có được những dấu hiệu làm mới, vì vậy thay vì sử dụng json_decode:

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

Bạn có thể làm:

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

cảm ơn cho các tip – ar099968

-1

Đây là những gì tôi đã thử nghiệm cho đến nay và hoạt động tốt.

$key = trim(file_get_contents('key.txt')); 
$scope = 'https://www.googleapis.com/auth/youtube'; 
Các vấn đề liên quan