Pushing video to YouTube from S3 account successful but video is “processing” forever

We have the following function running on a WordPress site that accesses an Amazon S3 (public) bucket and attempts to push the video over to YouTube for processing and taking some postmeta with it for title, description, tags, etc.

This script appears to work great except for the actual video upload. We get the video object created on YouTube with the correct title, description, privacy and tags but the video itself just absolutely refuses to process and YouTube reports processing forever.

Read More

Below is the relevant code chunk for uploading:

try {
    // 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();

    if ( ! empty( $args['title'] ) )
        $snippet->setTitle( $args['title'] );

    if ( ! empty( $args['description'] ) )
        $snippet->setDescription( $args['description'] );

    // if ( ! empty( $args['tags'] ) )
    //  $snippet->setTags( $args['tags'] );

    // Numeric video category. See
    // https://developers.google.com/youtube/v3/docs/videoCategories/list
    $snippet->setCategoryId("28");

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

    // 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 = 50 * 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.
    $ytclient->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(
        $ytclient,
        $insertRequest,
        'video/*',
        null,
        true,
        $chunkSizeBytes
    );
    $videoFileSize = filesize($videoPath);
    $media->setFileSize( $videoFileSize );

What could be causing the failure?

Related posts

Leave a Reply

1 comment

  1. You are not sending the content length and youtube is sitting there waiting for “more” content.

    Looking at your code you are using resume-able uploads.

    Updated with more info:

    From your code

    $videoFileSize = filesize($videoPath);
    

    where

    $videoPath = $s3dir . $args['file_path'];
    

    and

    $s3dir is "s3://coughvideo/"
    

    Therefore when you do the setFileSize here:

        $media = new Google_Http_MediaFileUpload(
        $ytclient,
        $insertRequest,
        'video/*',
        null,
        true,
        $chunkSizeBytes
    );
    $videoFileSize = filesize($videoPath);
    $media->setFileSize( $videoFileSize );
    

    Quite sure filesize will only work with local files, so you wont be able to get the filesize for a remote URL.

    You are going to have either

    • Request the filesize from Amazon first and use that
    • Download it locally so you can figure out the filesize (not sure if you want to do that).
    • Use CURL either example below (not sure if an option on your S3 instance – depending on your security).

    PHP: Remote file size without downloading file

    Edit:

    Switching the “bad” code above to:

    $head = get_headers($videoPath,1); // get the header array from Amazon S3
    $videoSize = $head['Content-Length']; // Get Mr. FileSize
    $media->setFileSize($videoSize); // Set Mr. FileSize
    

    This works to get the filesize in place.