2012-04-10 3 views
5

que tienen algún código de trabajo que carga un archivo de vídeo a YouTube:Conseguir un vídeo de S3 y Carga en YouTube en 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'); 

tengo vídeos en S3 y quiero subirlos a YouTube. El video en nuestra cuenta S3 es público, entonces puedo usar un comando como wget. ¿Debo ejecutar un comando que actualice el archivo de video y lo descargue localmente antes de ejecutar este script (shell_exec("wget ".$s3videoURL))?

¿O debería intentar ingresar a MediaFileSource como la URL del archivo S3?

Principalmente, solo necesito estabilidad (no es una solución sujeta a tiempos muertos frecuentes); la velocidad y el almacenamiento local no son realmente importantes (puedo eliminar localmente el archivo de video una vez que ha sido cargado).

¿Cuál sería la mejor manera de hacerlo?

Gracias!

Actualización: Probablemente debería mencionar que esta secuencia de comandos va a subir unos 5 videos a YouTube por ejecución.

Respuesta

7

Esta es una vieja pregunta, pero creo que tengo una mejor respuesta.

No tiene que escribir video en la unidad de disco duro y no puede guardar todo en la memoria RAM (supongo que es un archivo grande).

Puede utilizar las bibliotecas PHP AWS SDK y Google Client para almacenar en búfer el archivo de S3 y enviarlo a YouTube sobre la marcha. Utilice el método registerStreamWrapper para registrar S3 como sistema de archivos y usar cargas reanudables desde la API de YouTube. Entonces, todo lo que tienes que hacer es leer los fragmentos de S3 con fread y enviarlos a YouTube. De esta forma, incluso puedes limitar el uso de la RAM.

Supongo que ha creado el objeto de video ($ video en el código) de la clase Google_Video. Este es un código 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

Gracias. Me salvaste el tiempo :). – BCoder

+0

Solo en caso de que alguien encuentre problemas al tratar de simplificar esto, debe agregar el fragmento al búfer de fragmentos debido a la limitación de fread en php desde ubicaciones remotas. De php.net: " Advertencia Al leer cualquier archivo que no sea un archivo local normal, como secuencias devueltas al leer archivos remotos o desde popen() y fsockopen(), la lectura se detendrá después de que un paquete esté disponible. Esto significa que debe recopilar los datos juntos en fragmentos, como se muestra en los ejemplos a continuación ". – bertmaclin

2

El "MediaFileSource" debe ser un archivo real. No tomará una URL, por lo que tendrá que copiar los videos a su servidor desde S3, antes de enviarlos a YouTube.

Probablemente pueda salirse con la "shell_exec" si su uso es ligero, pero por una variedad de razones es mejor usar Zend S3 Service o cURL para extraer archivos de S3.

+0

Muchas gracias por su respuesta, voy a explorar estas alternativas –

-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); 
    } 
Cuestiones relacionadas