I have some code working that uploads a video file up to 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');
I have videos in S3 and I want to upload them to YouTube. The video in our S3 account is public, so i can use a command like wget. Should I run a command that wgets the video file and downloads it locally before I run this script (shell_exec("wget ".$s3videoURL))?
Or should I try to enter the MediaFileSource as the URL of the S3 file itself?
Mainly, I just need stability (not a solution subject to frequent time-outs); speed and local storage isn't really important (I can locally delete video file once its been uploaded).
What would be the best way to go about this?
Thanks!
Update: I should probably mention that this script is going to be uploading about 5 videos to YouTube per execution.
This is an old question but i believe i have a better answer.
You don't have to write video to HDD and you can't keep the whole thing in RAM (I assume it is a big file).
You can use PHP AWS SDK and Google Client libraries to buffer file from S3 and send it to YouTube on the fly. Use registerStreamWrapper method to register S3 as file system and use resumable uploads from YouTube API. Then all you have to do is reading chunks from S3 with fread and sending them to YouTube. This way you can even limit the RAM usage.
I assume you created the video object ($video in code) from Google_Video class. This is a complete code.
<?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);
The "MediaFileSource" must be a real file. It won't take a URL, so you will need to copy the videos to your server from S3, before sending them to YouTube.
You can probably get away with the "shell_exec" if your usage is light, but for a variety of reasons its probably better to use either the Zend S3 Service, or cURL to pull files from S3.
I had to make some changes to #previous_developer 's answer to make it work with Youtube Data API V3 (Please upvote him as I could not find any working code except his).
$streamName = 's3://BUCKET-NAME/VIDEO.mp4';
/**
Since I have been using Yii 2. Use the AWS
SDK directly instead.
*/
$aws = Yii::$app->awssdk->getAwsSdk();
$s3client = $aws->createS3();
$s3client->registerStreamWrapper();
$service = new \Google_Service_YouTube($client);
$snippet = new \Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test descrition");
$snippet->setTags(array("tag1","tag2"));
$snippet->setCategoryId("22");
$status = new \Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "public";
$video = new \Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
$client->setDefer(true);
$insertResponse = $service->videos->insert("status,snippet", $video);
$media = new MediaFileUpload(
$client,
$insertResponse,
'video/*',
null,
true,
false
);
$filesize = filesize($streamName); // use it as a reguler file.
$media->setFileSize($filesize);
$chunkSizeBytes = 2 * 1024 * 1024; // 2 mb
$uploadStatus = false;
$handle = fopen($streamName, "r");
$totalSend = 0;
$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($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($chunkBuffer);
$totalSend += strlen($chunkBuffer);
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
$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);
}
Related
I'm trying to implement uploading video to YouTube from the server but I'm having problems with that. I'm using Laravel 9 and Google API client for php. The code is like this, pretty much the same as a google example:
public function goToAuthUrl() {
$client = new Client();
$client->setApplicationName('Test');
$client->setScopes([
YouTube::YOUTUBE_UPLOAD,
]);
$client->setAuthConfig('client_secret_***.apps.googleusercontent.com.json');
$client->setAccessType('offline');
$authUrl = $client->createAuthUrl();
return redirect()->away($authUrl);
}
public function youtubeHandle(Request $request) {
session_start();
$htmlBody = '';
$client = new Google_Client();
$client->setAuthConfigFile('client_secret_***.apps.googleusercontent.com.json');
$client->setRedirectUri('https://***/youtube');
$client->addScope(YouTube::YOUTUBE_UPLOAD);
if (!isset($request->code)) {
$auth_url = $client->createAuthUrl();
} else {
$accessToken = $client->fetchAccessTokenWithAuthCode($request->code);
$client->setAccessToken($accessToken);
try{
$videoPath = url('storage/images/rain.mp4');
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test description");
$snippet->setTags(array("test"));
// Numeric video category.
$snippet->setCategoryId(27);
// Set the video's status to "public". Valid statuses are "public",
// "private" and "unlisted".
$status = new Google_Service_YouTube_VideoStatus();
$status->privacyStatus = "unlisted";
// Associate the snippet and status objects with a new video resource.
$video = new Google_Service_YouTube_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$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(Storage::size('public/images/rain.mp4'));
// 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);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
$htmlBody .= "<h3>Video Uploaded</h3><ul>";
$htmlBody .= sprintf('<li>%s (%s)</li>',
$status['snippet']['title'],
$status['id']);
$htmlBody .= '</ul>';
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION['token'] = $client->getAccessToken();
}
echo $htmlBody;
So, oauth process goes well, first I run goToAuthUrl() function, give the permissions, it redirects me back to the website and runs youtubeHandle() function. And here are the problems. It throws an error
Invalid request. The number of bytes uploaded is required to be equal or greater than 262144, except for the final request (it's recommended to be the exact multiple of 262144). The received request contained 16098 bytes, which does not meet this requirement.
and points to this line $status = $media->nextChunk($chunk);.
I tried to find the solutions and change the code, like changing $insertRequest variable to this:
$insertRequest = $youtube->videos->insert("status,snippet", $video, [
'data' => file_get_contents(url('storage/images/rain.mp4')),
'mimeType' => 'video/*',
'uploadType' => 'multipart'
]);
This way it throws another error
Failed to start the resumable upload (HTTP 200)
and video isn't being created on the channel.
Could you tell me where's the problem?
Once again I make sure that to make a question is a half way to get an answer. I found a solution, the example I used is old but it's there in the documentation. If someone meet this problem - it's all about chunks and there's a function to get it:
private function readVideoChunk($handle, $chunkSize) {
$byteCount = 0;
$giantChunk = "";
while (!feof($handle)) {
// fread will never return more than 8192 bytes if the stream is read
// buffered and it does not represent a plain file
$chunk = fread($handle, 8192);
$byteCount += strlen($chunk);
$giantChunk .= $chunk;
if ($byteCount >= $chunkSize) {
return $giantChunk;
}
}
return $giantChunk;
}
So uploading should look like this:
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = $this->readVideoChunk($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
I am uploading video to my channel with youtube data api. This works perfectly but when i upload video it uploads in my channel. I want it to upload in given playlist.(I have some already created playlists). Is there any way i can give playlistId in following code. I dont want to use playlistitem.insert.
thanks in Advance
$OAUTH2_CLIENT_ID = 'ds';
$OAUTH2_CLIENT_SECRET = 'sd';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
$tokenExisted = $this->Token->find('first');
if(!empty($tokenExisted)){
$token = $tokenExisted['Token']['token'];
$refreshToken = $tokenExisted['Token']['ref_token'];
$client->refreshToken($refreshToken);
$token = $client->getAccessToken();
}
if (isset($token)) {
$client->setAccessToken($token);
}
if ($client->isAccessTokenExpired()){
$refreshToken = $tokenExisted['Token']['ref_token'];
$client->refreshToken($refreshToken);
$token = $client->getAccessToken();
}else{
$token = $client->getAccessToken();
}
$token=json_encode($token);
// Check to ensure that the access token was successfully acquired.
if ($token) {
try{
// REPLACE this value with the path to the file you are uploading.
$videoPath = $dest . '/' . $img_name . '.' . $image['1'];
// 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($input['title']);
$snippet->setDescription($input['description']);
//$snippet->playlistId($playlistId);
// Numeric video category. See
// https://developers.google.com/youtube/v3/docs/videoCategories/list
$snippet->setCategoryId($input['category']);
// 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);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$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(false);
// 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);
// If you want to make other calls after the file upload, set setDefer back to false
//$client->setDefer(false);
} catch (Google_Service_Exception $e) {
$htmlBody = sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody = sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
}
According to this SO answer, you cannot upload video directly into a playlist. It's normal that when uploading video, it will redirect to your channel. Once it's uploaded in the channel, you can now put it in the playlist.
If the video is already uploaded, you can follow this Adding a video to a playlist documentation. You can add a video to a playlist by using a VideoEntry object.
Here's a sample code retrieves a VideoEntry object with a known entry ID and then adds it to the playlist corresponding to the PlaylistListEntry object. Since the request does not specify a position where the video will appear in the playlist, the new video is added to the end of the playlist.
$postUrl = $playlistToAddTo->getPlaylistVideoFeedUrl();
// video entry to be added
$videoEntryToAdd = $yt->getVideoEntry('4XpnKHJAok8');
// create a new Zend_Gdata_PlaylistListEntry, passing in the underling DOMElement of the VideoEntry
$newPlaylistListEntry = $yt->newPlaylistListEntry($videoEntryToAdd->getDOM());
// post
try {
$yt->insertEntry($newPlaylistListEntry, $postUrl);
} catch (Zend_App_Exception $e) {
echo $e->getMessage();
}
Here's a related SO post which might help:
Youtube API (PHP) - how to add (existing) video to existing playlist?
I am amazed by the lack of information at the official documentation of Google Cloud Storage with PHP.
Here we go... I'm trying to manage bucket's uploads and downloads with Google APIs Client Library for PHP, but I can't find anywhere the way to specify to the API where I want to upload my files at google's bucket (I can only upload them at bucket's root).
Here's the code that I'm using for the upload (extracted from https://github.com/guillefd/Backup-manager-gcs/blob/master/application/libraries/Googlecloudstorage.php):
public function media_file_upload($file_path = null, $file_name = null) {
# init
$result = new stdClass();
$result->error = null;
$result->status = null;
$result->exception = null;
# timer
$result->starttime = microtime();
# init gcs api
$gso = new Google_Service_Storage_StorageObject();
$gso->setName($file_name);
$gso->setBucket($this->bucket);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo,$file_path);
$chunkSizeBytes = 1 * 1024 * 1024;
$this->client->setDefer(true);
$filetoupload = array(
'name'=>$file_name,
'uploadType'=>'resumable'
);
# service
$this->newStorageService();
$status = false;
# try
try {
$request = $this->storageService->objects->insert($this->bucket, $gso, $filetoupload);
$media = new Google_Http_MediaFileUpload($this->client, $request, $mimetype, null, true, $chunkSizeBytes);
$media->setFileSize(filesize($file_path));
$handle = fopen($file_path, "rb");
# loop chunks
while(!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
$this->client->setDefer(false);
// $result->status = $status;
} catch(Exception $e) {
$result->error = true;
$result->status = 'Google Cloud Service upload failed';
$result->exception = $e;
}
# timer
$result->endtime = microtime();
$result->totaltime = $this->get_totaltime($result);
# verify response
$result->httpcode = http_response_code();
$result->error = isset($status->kind) && $status->kind==self::STORAGE_OBJECT ? false : true;
return $result;
}
The main question that I'm actually asking is: Is there a way to upload files to google's bucket at a specific route, using Google Cloud's PHP API?
Thanks!
I'm using Google API's PHP client library and when I use this solution:
https://stackoverflow.com/a/14552052/1181479
and the same as here
https://developers.google.com/youtube/v3/code_samples/php#resumable_uploads
witch contain such logic:
if ($client->getAccessToken()) {
$videoPath = "path/to/foo.mp4";
$snippet = new Google_VideoSnippet();
$snippet->setTitle("Test title2");
$snippet->setDescription("Test descrition");
$snippet->setTags(array("tag1", "tag2"));
$snippet->setCategoryId("22");
$status = new Google_VideoStatus();
$status->privacyStatus = "private";
$video = new Google_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
$chunkSizeBytes = 1 * 1024 * 1024;
$media = new Google_MediaFileUpload('video/mp4', null, true, $chunkSizeBytes);
$media->setFileSize(filesize($videoPath));
$result = $youtube->videos->insert("status,snippet", $video,
array('mediaUpload' => $media));
$status = false;
$handle = fopen($videoPath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$uploadStatus = $media->nextChunk($result, $chunk);
}
fclose($handle);
}
The main problem is this error:
ErrorException [ Recoverable Error ]: Argument 1 passed to Google_MediaFileUpload::nextChunk() must be an instance of Google_HttpRequest, instance of Google_Video given, called in /opt/code/host/resulinkpro/www/application/classes/Controller/Upload.php on line 132 and defined
the core of that stuff is:
$media is Google_Video class
and
$media->nextChunk($result, $chunk);
requires $result to be Google_HttpRequest SO Google documentation and any example in web will not help to achieve that task at all! Last chance on you guys!
Thank you!
Both of the examples were made for PHP client 0.6.3, I believe you are trying it with 1.0 version. You can read about migrating here.
We hope to post the updated examples really soon.
I am trying to upload a video to Youtube using PHP. I am using Youtube API v3 and I am using the latest checked out source code of Google API PHP Client library.
I am using the sample code given on
https://code.google.com/p/google-api-php-client/ to perform the authentication. The authentication goes through fine but when I try to upload a video I get Google_ServiceException with error code 500 and message as null.
I had a look at the following question asked earlier:
Upload video to youtube using php client library v3 But the accepted answer doesn't describe how to specify file data to be uploaded.
I found another similar question Uploading file with Youtube API v3 and PHP, where in the comment it is mentioned that categoryId is mandatory, hence I tried setting the categoryId in the snippet but still it gives the same exception.
I also referred to the Python code on the the documentation site ( https://developers.google.com/youtube/v3/docs/videos/insert ), but I couldn't find the function next_chunk in the client library. But I tried to put a loop (mentioned in the code snippet) to retry on getting error code 500, but in all 10 iterations I get the same error.
Following is the code snippet I am trying:
$youTubeService = new Google_YoutubeService($client);
if ($client->getAccessToken()) {
print "Successfully authenticated";
$snippet = new Google_VideoSnippet();
$snippet->setTitle = "My Demo title";
$snippet->setDescription = "My Demo descrition";
$snippet->setTags = array("tag1","tag2");
$snippet->setCategoryId(23); // this was added later after refering to another question on stackoverflow
$status = new Google_VideoStatus();
$status->privacyStatus = "private";
$video = new Google_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
$data = file_get_contents("video.mp4"); // This file is present in the same directory as the code
$mediaUpload = new Google_MediaFileUpload("video/mp4",$data);
$error = true;
$i = 0;
// I added this loop because on the sample python code on the documentation page
// mentions we should retry if we get error codes 500,502,503,504
$retryErrorCodes = array(500, 502, 503, 504);
while($i < 10 && $error) {
try{
$ret = $youTubeService->videos->insert("status,snippet",
$video,
array("data" => $data));
// tried the following as well, but even this returns error code 500,
// $ret = $youTubeService->videos->insert("status,snippet",
// $video,
// array("mediaUpload" => $mediaUpload);
$error = false;
} catch(Google_ServiceException $e) {
print "Caught Google service Exception ".$e->getCode()
. " message is ".$e->getMessage();
if(!in_array($e->getCode(), $retryErrorCodes)){
break;
}
$i++;
}
}
print "Return value is ".print_r($ret,true);
// We're not done yet. Remember to update the cached access token.
// Remember to replace $_SESSION with a real database or memcached.
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
print "<a href='$authUrl'>Connect Me!</a>";
}
Is it something that I am doing wrong?
I was able to get the upload working using the following code:
if($client->getAccessToken()) {
$snippet = new Google_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test descrition");
$snippet->setTags(array("tag1","tag2"));
$snippet->setCategoryId("22");
$status = new Google_VideoStatus();
$status->privacyStatus = "private";
$video = new Google_Video();
$video->setSnippet($snippet);
$video->setStatus($status);
$error = true;
$i = 0;
try {
$obj = $youTubeService->videos->insert("status,snippet", $video,
array("data"=>file_get_contents("video.mp4"),
"mimeType" => "video/mp4"));
} catch(Google_ServiceException $e) {
print "Caught Google service Exception ".$e->getCode(). " message is ".$e->getMessage(). " <br>";
print "Stack trace is ".$e->getTraceAsString();
}
}
I realize this is old, but here's the answer off the documentation:
// REPLACE this value with the path to the file you are uploading.
$videoPath = "/path/to/file.mp4";
$snippet = new Google_Service_YouTube_VideoSnippet();
$snippet->setTitle("Test title");
$snippet->setDescription("Test description");
$snippet->setTags(array("tag1", "tag2"));
// 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);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$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);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
I also realize this is old, but as I cloned the latest version of php-client from GitHub I ran in to trouble with Google_Service_YouTube_Videos_Resource::insert()-method.
I would pass an array with "data" => file_get_contents($pathToVideo) and "mimeType" => "video/mp4" set as an argument for the insert()-method, but I still kept getting (400) BadRequest in return.
Debugging and reading through Google's code i found in \Google\Service\Resource.php there was a check (on lines 179-180) against an array key "uploadType" that would initiate the Google_Http_MediaFielUpload object.
$part = 'status,snippet';
$optParams = array(
"data" => file_get_contents($filename),
"uploadType" => "media", // This was needed in my case
"mimeType" => "video/mp4",
);
$response = $youtube->videos->insert($part, $video, $optParams);
If I remember correctly, with version 0.6 of the PHP-api the uploadType argument wasn't needed. This might apply only for the direct upload style and not the resumable upload shown in Any Day's answer.
The answer would be using Google_Http_MediaFileUpload through the Google PHP client libraries.
Here's the sample code: https://github.com/youtube/api-samples/blob/master/php/resumable_upload.php