Astor
Astor

Reputation: 426

Video upload stop working - Youtube API

I use a PHP script to upload some daily videos to a Youtube channel (based on this code sample: https://developers.google.com/youtube/v3/code_samples/php#resumable_uploads)

The problem is after this loop:

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

Normally the $status variable has the video id ($status['id']) after the upload is complete but since mid January all the uploads failed with one of this errors:

When I access the Youtube channel I can see the new videos with a status "Preparing upload" or stuck with a fixed percentage.

My code has not changed for months but now I can't upload any new video.

Anyone can please help me to know what's wrong? Thanks in advance!

Upvotes: 2

Views: 2110

Answers (3)

Sodu Parsiev
Sodu Parsiev

Reputation: 81

in previous answer from eveyrat everything is okay except one thing, readVideoChunk() doesn't always return exact amount of bytes as it is required in chunk upload docs. Moreover google accepts only as much bytes as it was in the first chunk request. I fixed that issue by custom buffering of overlap bytes: (consider following piece of the code as a method of a class, the class has to have $remaining property)

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)
        {
            break;
        }
    }

    $chunks = str_split(($this->remaining . $giantChunk), $chunkSize);
    if (count($chunks) > 1) {
        $giantChunk = $chunks[0];
        $this->remaining = $chunks[1];
    }
    else {
        $giantChunk = $chunks[0];
        $this->remaining = '';
    }

    return $giantChunk;
}

Upvotes: 0

eveyrat
eveyrat

Reputation: 21

The solution proposed by @pom (thanks by the way) doesn't really solve this issue if you need to implement a progress indicator.

I'm facing the same problem than @astor; after calling ->nextChunk for the final chunk i get:

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 38099 bytes, which does not meet this requirement.

See this log file :

The code is copy-paste from the google/google-api-php-client doc. The log file shows the size of the first chunk being a bit superior to the others (except the last one) which i couldn't explain. Another "strange" thing is that its size changes test after test. The size of the last chunk seems correct, and at the end all bytes should have been uploaded. However, uploading the remaining bytes in the last chunk ->nextChunk($chunk) throws this error.

One important precision is that my source file is on AWS S3. File operations (filesize, fread, fopen) are done with the Amazon S3 Stream Wrapper. It may add some headers or IDK that causes the problem. EDIT: I don't have such problem with local files

Has anyone run into the same problem? ?

...
  $chunkSizeBytes = 5 * 1024 * 1024;
  $client->setDefer(true);
  $request = $service->files->create($file);

  $media = new Google_Http_MediaFileUpload(
      $client,
      $request,
      'text/plain',
      null,
      true,
      $chunkSizeBytes
  );
  $media->setFileSize(filesize(TESTFILE));
  // Upload the various chunks. $status will be false until the process is
  // complete.
  $status = false;
  $handle = fopen(TESTFILE, "rb");
  while (!$status && !feof($handle)) {
    // read until you get $chunkSizeBytes from TESTFILE
    // fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
    // An example of a read buffered file is when reading from a URL
    $chunk = readVideoChunk($handle, $chunkSizeBytes);
    $status = $media->nextChunk($chunk);
  }
  // The final value of $status will be the data from the API for the object
  // that has been uploaded.
  $result = false;
  if ($status != false) {
    $result = $status;
  }
  fclose($handle);
}
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;
}

Upvotes: 2

pom
pom

Reputation: 38

Maybe you can try like that and then let MediaFileUpload cut the chunk itself:

$media = new \Google_Http_MediaFileUpload(
   $client,
   $insertRequest,
   'video/*',
   file_get_contents($pathToFile),  <== put file content instead of null
   true,
   $chunkSizeBytes
);
$media->setFileSize($size);

$status = false;
while (!$status) {
   $status = $media->nextChunk();
}

Upvotes: 2

Related Questions