2012-04-10 16 views
5

ho qualche codice di lavoro che consente di caricare un file video fino a YouTube:Ottenere un video da S3 e caricare su YouTube in PHP

$yt = new Zend_Gdata_YouTube($httpClient); 

// create a new VideoEntry object 
$myVideoEntry = new Zend_Gdata_YouTube_VideoEntry(); 

// create a new Zend_Gdata_App_MediaFileSource object 
$filesource = $yt->newMediaFileSource('file.mov'); 
$filesource->setContentType('video/quicktime'); 
// set slug header 
$filesource->setSlug('file.mov'); 

Ho video in S3 e voglio caricarli su YouTube. Il video nel nostro account S3 è pubblico, quindi posso usare un comando come wget. Devo eseguire un comando che automatizza il file video e lo scarica localmente prima di eseguire questo script (shell_exec("wget ".$s3videoURL))?

O dovrei provare ad inserire MediaFileSource come URL del file S3 stesso?

Principalmente, ho solo bisogno di stabilità (non una soluzione soggetta a frequenti timeout); la velocità e l'archiviazione locale non sono molto importanti (posso eliminare localmente il file video una volta che è stato caricato).

Quale sarebbe il modo migliore per farlo?

Grazie!

Aggiornamento: probabilmente dovrei menzionare che questo script caricherà circa 5 video su YouTube per esecuzione.

risposta

7

Questa è una vecchia domanda ma credo di avere una risposta migliore.

Non è necessario scrivere video su HDD e non è possibile mantenere tutto nella RAM (presumo che sia un file di grandi dimensioni).

È possibile utilizzare PHP AWS SDK e librerie client di Google per archiviare il file da S3 e inviarlo a YouTube al volo. Utilizza il metodo registerStreamWrapper per registrare S3 come file system e utilizzare i caricamenti ripristinabili dall'API di YouTube. Quindi tutto quello che devi fare è leggere frammenti di S3 con fread e inviarli a YouTube. In questo modo puoi anche limitare l'utilizzo della RAM.

Suppongo che tu abbia creato l'oggetto video ($ video in codice) dalla classe Google_Video. Questo è un codice completo.

<?php 
require_once 'path/to/libraries/aws/vendor/autoload.php'; 
require_once 'path/to/libraries/google-client-lib/autoload.php'; 

use Aws\S3\S3Client; 

$chunkSizeBytes = 2 * 1024 * 1024; // 2 mb 
$streamName = 's3://bucketname/video.mp4'; 

$s3client = S3Client::factory(array(
        'key' => S3_ACCESS_KEY, 
        'secret' => S3_SECRET_KEY, 
        'region' => 'eu-west-1' // if you need to set. 
       )); 
$s3client->registerStreamWrapper(); 

$client = new Google_Client(); 
$client->setClientId(YOUTUBE_CLIENT_ID); 
$client->setClientSecret(YOUTUBE_CLIENT_SECRET); 
$client->setAccessToken(YOUTUBE_TOKEN); 

$youtube = new Google_YoutubeService($client); 
$media = new Google_MediaFileUpload('video/*', null, true, $chunkSizeBytes); 

$filesize = filesize($streamName); // use it as a reguler file. 
$media->setFileSize($filesize); 

$insertResponse = $youtube->videos->insert("status,snippet", $video, array('mediaUpload' => $media)); 
$uploadStatus = false; 

$handle = fopen($streamName, "r"); 
$totalReceived = 0; 
$chunkBuffer = ''; 
while (!$uploadStatus && !feof($handle)) { 
    $chunk = fread($handle, $chunkSizeBytes); 
    $chunkBuffer .= $chunk; 
    $chunkBufferSize = strlen($chunkBuffer); 
    if($chunkBufferSize > $chunkSizeBytes) { 
     $fullChunk = substr($chunkBuffer, 0, $chunkSizeBytes); 
     $leapChunk = substr($chunkBuffer, $chunkSizeBytes); 
     $uploadStatus = $media->nextChunk($insertResponse, $fullChunk); 
     $totalSend += strlen($fullChunk); 

     $chunkBuffer = $leapChunk; 
     echo PHP_EOL.'Status: '.($totalReceived).'/'.$filesize.' (%'.(($totalReceived/$filesize) * 100).')'.PHP_EOL; 
    } 

    $totalReceived += strlen($chunk); 
} 

$extraChunkLen = strlen($chunkBuffer); 
$uploadStatus = $media->nextChunk($insertResponse, $chunkBuffer); 
$totalSend += strlen($chunkBuffer); 
fclose($handle); 
+0

Grazie. Mi hai salvato il tempo :). – BCoder

+0

Nel caso in cui qualcuno si imbattesse in problemi cercando di semplificare questo, è necessario aggiungere il blocco al buffer pezzo a causa della limitazione di fread in php da posizioni remote. Da php.net: " Avviso Durante la lettura da qualsiasi cosa che non sia un normale file locale, come gli stream restituiti durante la lettura di file remoti o da popen() e fsockopen(), la lettura si fermerà dopo che un pacchetto è disponibile. Ciò significa che dovresti raccogliere i dati insieme in blocchi come mostrato negli esempi qui sotto. " – bertmaclin

2

"MediaFileSource" deve essere un file reale. Non ci vorrà un URL, quindi dovrai copiare i video sul tuo server da S3, prima di inviarli a YouTube.

Probabilmente si può farcela con "shell_exec" se il tuo utilizzo è leggero, ma per una serie di motivi è probabilmente meglio usare lo Zend S3 Service o cURL per estrarre file da S3.

+0

Grazie mille per la risposta, ho intenzione di esplorare queste alternative –

-1

$ chunkSizeBytes = 2 * 1024 * 1024; // 2 mb

$s3client = $this->c_aws->getS3Client(); 
    $s3client->registerStreamWrapper(); 

    try { 

     $client = new \Google_Client(); 

     $client->setAccessType("offline"); 
     $client->setApprovalPrompt('force'); 

     $client->setClientId(GOOGLE_CLIENT_ID); 
     $client->setClientSecret(GOOGLE_CLIENT_SECRET); 
     $token = $client->fetchAccessTokenWithRefreshToken(GOOGLE_REFRESH_TOKEN); 


     $client->setAccessToken($token); 

     $youtube = new \Google_Service_YouTube($client); 

     // Create a snippet with title, description, tags and category ID 
     // Create an asset resource and set its snippet metadata and type. 
     // This example sets the video's title, description, keyword tags, and 
     // video category. 
     $snippet = new \Google_Service_YouTube_VideoSnippet(); 
     $snippet->setTitle($title); 
     $snippet->setDescription($summary); 
     $snippet->setTags(explode(',', $keywords)); 

     // Numeric video category. See 
     // https://developers.google.com/youtube/v3/docs/videoCategories/list 

// $ snippet-> setCategoryId ("22");

 // Set the video's status to "public". Valid statuses are "public", 
     // "private" and "unlisted". 
     $status = new \Google_Service_YouTube_VideoStatus(); 
     $status->privacyStatus = "public"; 


     // Associate the snippet and status objects with a new video resource. 
     $video = new \Google_Service_YouTube_Video(); 
     $video->setSnippet($snippet); 
     $video->setStatus($status); 

     // 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); 

     $insertRequest = $youtube->videos->insert("status,snippet", $video); 

     $media = new \Google_Http_MediaFileUpload(
      $client, 
      $insertRequest, 
      'video/*', 
      null, 
      true, 
      $chunkSizeBytes 
     ); 

     $result = $this->c_aws->getAwsFile($aws_file_path); 

     $media->setFileSize($result['ContentLength']); 

     $uploadStatus = false; 

     // Seek to the beginning of the stream 
     $result['Body']->rewind(); 

     // Read the body off of the underlying stream in chunks 
     while (!$uploadStatus && $data = $result['Body']->read($chunkSizeBytes)) { 

      $uploadStatus = $media->nextChunk($data); 

     } 
     $client->setDefer(false); 
     if ($uploadStatus->status['uploadStatus'] == 'uploaded') { 
      // Actions to perform for a successful upload 
      $uploaded_video_id = $uploadStatus['id']; 
      return ($uploadStatus['id']); 
     } 
    }catch (\Google_Service_Exception $exception){ 
     return ''; 
     print_r($exception); 
    } 
Problemi correlati