Получение видео с S3 и загрузка на YouTube на PHP
У меня есть работающий код, который загружает видеофайл на YouTube:
$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');
У меня есть видео в S3, и я хочу загрузить их на YouTube. Видео в нашей учетной записи S3 является общедоступным, поэтому я могу использовать такую команду, как wget. Должен ли я выполнить команду, которая извлекает видеофайл и загружает его локально, прежде чем запускать этот скрипт (shell_exec("wget ".$s3videoURL)
)?
Или мне следует попытаться ввести источник медиафайлов в качестве URL-адреса самого файла S3?
В основном, мне просто нужна стабильность (не решение, подлежащее частые тайм-ауты); скорость и локальное хранилище на самом деле не важны (я могу локально удалить видеофайл после его загрузки).
Каков был бы наилучший способ сделать это?
Спасибо!
Обновление: Я, вероятно, должен упомянуть, что этот скрипт будет загружать около 5 видео на YouTube за выполнение.
3 answers
Это старый вопрос, но я думаю, что у меня есть лучший ответ.
Вам не нужно записывать видео на жесткий диск, и вы не можете хранить все это в оперативной памяти (я предполагаю, что это большой файл).
Вы можете использовать PHP AWS SDK и клиентские библиотеки Google для буферизации файла из S3 и отправки его на YouTube на лету. Используйте метод registerStreamWrapper, чтобы зарегистрировать S3 в качестве файловой системы и использовать возобновляемые загрузки из API YouTube. Затем все, что вам нужно сделать, это прочитать фрагменты из S3 с помощью fread и отправить их на YouTube. Таким образом, вы даже можете ограничить использование оперативной памяти.
Я предполагаю, что вы создали объект video ($video в коде) из класса Google_Video. Это полный код.
<?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);
"Источник медиафайлов" должен быть реальным файлом. Для этого не потребуется URL-адрес, поэтому вам нужно будет скопировать видео на свой сервер с S3, прежде чем отправлять их на YouTube.
Вы, вероятно, можете обойтись без "shell_exec", если ваше использование невелико, но по ряду причин, вероятно, лучше использовать либо Службу Zend S3, либо CURL для извлечения файлов из S3.
$куски в байтах = 2 * 1024 * 1024; // 2 мб
$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
//$фрагмент->Установить идентификатор категории("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);
}