Подтвердить что ты не робот

YouTube API усекает видео [PHP]

Я использую API YouTube для загрузки фрагментов видео (см. код ниже). Тем не менее, загрузка иногда прерывается с большими файлами (+ 1 ГБ), но не всегда. Загрузка будет завершена, но можно сыграть всего пару минут, а остальная часть будет усечена. Я сделал некоторые исследования, но без видимых успехов. Мой вопрос сейчас:

  • Есть ли возможность напрямую связаться с YouTube (просмотрев журналы о том, что происходит)?
  • Это проблема с кодировкой?
  • Может ли ошибка быть обнаружена/обнаружена через API (на данный момент не генерируется исключение)
  • Возможно ли это, если вы загружаете разные видеоролики сразу (параллельно, то есть)?
  • Кто-нибудь еще столкнулся с этой проблемой?

Любая помощь/руководство в правильном направлении очень ценится. Я даже назвал бы щедрость в 500 очков, так как это сводит меня с ума (просто сделал это...)

Приложение. script запускается в командной строке через сервер Gearman с параметром set_time_limit(0);. Код/функция - это просто экстракт (и отлично работает с меньшими файлами, иногда даже до 10 ГБ).

РЕДАКТИРОВАТЬ. В соответствии с вышеприведенными комментариями от aergistal и GeorgeQ я изменил цикл while, чтобы читать фрагменты напрямую (нет feof()) и сохранить статус в базе данных.

/*
    Uploads one file to youtube chunk by chunk
*/
function uploadFile($dbfile) {
    $client = $this->client;
    $youtube = new Google_Service_YouTube($client);
    $htmlBody = "";

    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 title, description, keyword tags, and
        // video category.
        $snippet = new Google_Service_YouTube_VideoSnippet();
        $snippet->setTitle("SO Example");

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

        // Set the video 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 = 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 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($dbfile->localfile));

        // Read the media file and upload it chunk by chunk.
        $status = false;
        $handle = fopen($dbfile->localfile, "rb");

        while (!$status && ($chunk = (fread($handle, $chunkSizeBytes))) !== FALSE) { 
            $status = $media->nextChunk($chunk);
            $data = array("filename" => $dbfile->localfile, "status" => print_r($status, true));
            $db->saveLog($data);
        }

        /* the old code
        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);

        $log = array("success" => true, "snippet_id" => $status["id"]);
    } catch (Google_ServiceException $e) {
        $log = array("success" => false, "errormsg" => $e->getMessage());
    } catch (Google_Exception $e) {
        $log = array("success" => false, "errormsg" => $e->getMessage());
    }

    return $log;
}
4b9b3361

Ответ 1

Есть ли возможность напрямую связаться с YouTube (просмотр журналов что действительно происходит)?

Ну, это невозможная миссия. Вам нужно отправить им многочисленные письма (возможно) получить ответ. Я пробовал несколько раз, но ответа от них не было.

Это какая-то проблема с кодировкой?

Да, это проблема с кодировкой. Если вы пытаетесь загрузить HD-видео, и если он усекается или сокращается или вообще что-то, это проблема с кодировкой. У YouTube есть их периодически.

Может ли ошибка быть обнаружена/обнаружена через API (на данный момент нет исключение)

Нет, не может. Вы должны увидеть видео, когда оно загружено, чтобы увидеть сообщение об ошибке. Нет исключения в середине процесса или в любой части загрузки.

Возможно ли это, если вы загружаете разные видеоролики сразу (в параллельный, то есть)?

Это не имеет значения. Если вы загружаете одно видео или два, три, пять видео одновременно, это не имеет значения. Это просто загрузка. Только плохая вещь, которая может произойти в процессе, - потеря связи. Каждое видео идет в своем направлении. Это похоже на то, что вы копируете несколько файлов из одной папки в другую.

Кто-нибудь еще столкнулся с этой проблемой?

Да. Вы, я, и вся группа других пользователей. Это проблема с YouTube. Это их ошибка или некоторая кодировка/рендеринг/перекодировка, какая бы проблема у них была. Все это из-за выбора обработки YouTube.

Когда это случилось со мной, моим решением было использование HTTPS/SSL при загрузке видео. И это сработало. Не было никакой функции резки, обрезки, перекодирования и кодирования/рендеринга.

Ответ 2

выглядит как script. попробуйте этот код в первой строке: set_time_limit(0);

Ответ 3

Загрузка будет завершена, но можно сыграть всего пару минут, а остальная часть будет усечена. Я сделал некоторые исследования, но без видимых успехов.

Это какая-то проблема с кодировкой?

Хорошо. Вы используете загрузку "chunked". В других словах: его "возобновляемая" загрузка, как описано в YT Upload API.

Мое первое предположение: проблема с заголовком content-range (одного из запросов). Все части должны идеально выравниваться по байтам на стороне сервера YT, иначе вы получите только первую часть двоичного файла. Реферирование: Загрузить куски и обратите внимание на синюю рамку на Заголовок диапазона содержимого.

google-api-php-client должен работать с этим правильно. Но по ошибке это может быть что угодно: API не синхронизирован с клиентом, проблема конфигурации cURL, заголовок не установлен, диапазон неверно рассчитан.

Может ли ошибка быть обнаружена/обнаружена через API (на данный момент не выбрасывается исключение)

Отладка клиента не ваша работа. Можно было бы включить GuzzleHttp\RequestOptions::DEBUG, чтобы увидеть, правильно ли все заголовки. Затем вы можете попытаться загрузить статус загрузки параллельно самой загрузке (второй запрос на жужжание).

Есть ли возможность напрямую связаться с YouTube (видя журналы того, что происходит на самом деле)?

Да, вы используете Google_Http_MediaFileUpload и ту часть google-api-php-client.

Просто откройте проблему в своем репозитории Github: https://github.com/google/google-api-php-client/issues


Мое предложение:

  • оставить лук PHP PHP(ext_curl(libcurl))) + yourscript(google-api-client(guzzle)))
    • PHP onion означает: ваш script использует google-api-client, который использует guzzle, который использует php_ext_curl, который использует libcurl внутри
    • у вас есть несколько уровней, и ошибки могут возникнуть у всех из них
    • нижняя строка: позволяет просто обойти стек PHP для тестирования из CLI
  • попытайтесь воспроизвести проблему с помеченной загрузкой в ​​CLI, используя cURL
  • используйте вторую консоль для запроса статуса активной загрузки между загруженными фрагментами
  • тогда, если загрузка из CLI
    • не удалось: это указывает на проблему сервера YT
    • преуспеть: сравните заголовки из CLI с PHP script (жужжание в режиме отладки), чтобы приблизиться к проблеме