PHP serve MP4 — Chrome «Отображаются предварительные заголовки / запрос еще не завершен» ошибка

Я хочу проверить подписку пользователей, прежде чем разрешить им смотреть видео, поэтому я использую PHP для взаимодействия с нашивка проверить подписку пользователя и чем пользоваться PHP скрипт служить MP4 для браузера

Он отлично работает при первом воспроизведении видео в Google Chrome (с помощью проигрывателя HTML5) …
Но когда я закрываю видео и воспроизводлю его снова, видео больше не воспроизводится … Я НЕ могу также перезагрузить текущую страницу. Это как сервер перестает работать.

Когда я проверяю 1-й видео запрос (тот, который воспроизводился), во вкладке Timing я вижу: «ВНИМАНИЕ: запрос еще не закончен!» (скриншот ниже)

ВНИМАНИЕ: запрос еще не закончен!

Когда я проверяю второй видео-запрос (тот, который не воспроизводился), на вкладке «Заголовки» появляется сообщение «[знак предостережения] Отображаются предварительные заголовки» (скриншот ниже)

введите описание изображения здесь

все работало как положено в Safari или Firefox

Кто-нибудь имеет представление о том, что происходит? Единственный способ воспроизвести видео снова — закрыть текущую вкладку и снова зайти на сайт. Перезагрузка не работает!

9

Решение

Я предлагаю вам использовать следующую функцию вместо вашего текущего «потокового скрипта». Если вы передадите $ filename_output, файл будет загружен, а в противном случае он будет транслироваться!

Это должно работать в каждом браузере.

serveFile ( ‘/, где / мой / vid.mp4’);

public function serveFile($filename, $filename_output = false, $mime = 'application/octet-stream')
{
$buffer_size = 8192;
$expiry = 90; //days
if(!file_exists($filename))
{
throw new Exception('File not found: ' . $filename);
}
if(!is_readable($filename))
{
throw new Exception('File not readable: ' . $filename);
}

header_remove('Cache-Control');
header_remove('Pragma');

$byte_offset = 0;
$filesize_bytes = $filesize_original = filesize($filename);

header('Accept-Ranges: bytes', true);
header('Content-Type: ' . $mime, true);

if($filename_output)
{
header('Content-Disposition: attachment; filename="' . $filename_output . '"');
}

// Content-Range header for byte offsets
if (isset($_SERVER['HTTP_RANGE']) && preg_match('%bytes=(\d+)-(\d+)?%i', $_SERVER['HTTP_RANGE'], $match))
{
$byte_offset = (int) $match[1];//Offset signifies where we should begin to read the file
if (isset($match[2]))//Length is for how long we should read the file according to the browser, and can never go beyond the file size
{
$filesize_bytes = min((int) $match[2], $filesize_bytes - $byte_offset);
}
header("HTTP/1.1 206 Partial content");
header(sprintf('Content-Range: bytes %d-%d/%d', $byte_offset, $filesize_bytes - 1, $filesize_original)); ### Decrease by 1 on byte-length since this definition is zero-based index of bytes being sent
}

$byte_range = $filesize_bytes - $byte_offset;

header('Content-Length: ' . $byte_range);
header('Expires: ' . date('D, d M Y H:i:s', time() + 60 * 60 * 24 * $expiry) . ' GMT');

$buffer = '';
$bytes_remaining = $byte_range;

$handle = fopen($filename, 'r');
if(!$handle)
{
throw new Exception("Could not get handle for file: " .  $filename);
}
if (fseek($handle, $byte_offset, SEEK_SET) == -1)
{
throw new Exception("Could not seek to byte offset %d", $byte_offset);
}

while ($bytes_remaining > 0)
{
$chunksize_requested = min($buffer_size, $bytes_remaining);
$buffer = fread($handle, $chunksize_requested);
$chunksize_real = strlen($buffer);
if ($chunksize_real == 0)
{
break;
}
$bytes_remaining -= $chunksize_real;
echo $buffer;
flush();
}
}
1

Другие решения

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

  1. Сначала я должен убедиться, что keep-alive отключен KeepAlive Off на вашем httpd.conf

  2. Затем протестируйте его с этой конфигурацией.

  3. Тогда я бы отключил все кэширование браузера:

    заголовок («Cache-Control: нет-кеш-нет-нет-хранилище, обязательно-повторная проверка»);
    заголовок («Pragma: no-cache»);
    заголовок (‘Истекает: 0’);

  4. Финальный тест после этого.

Похоже, что проблема связана с поддержанием активности, кэшированием в браузере или даже обоими, но я не могу понять, почему он появляется только в Chrome. В крайнем случае убедитесь, что вы не используете какие-либо расширения, которые могут создать проблемы, такие как Adblock.

Надеюсь, я получу эту информацию 🙂

1

У меня была такая же проблема при попытке потоковой передачи аудио файлов. В итоге я решил свою проблему по чистой случайности.

В какой-то момент я создал сценарий, который уменьшит битрейт файлов до 128 кбит / с с помощью FFMPEG (насколько мне известно, работает и с видео). После этого при проверке в chrome я начал замечать, что все мои запросы завершаются через пару секунд, а не остаются незавершенными бесконечно, как раньше. Не уверен, что это жизнеспособно для вас, но сжатые файлы решили эту проблему, а также увеличили скорость потоковой передачи, поэтому я настоятельно рекомендую это.

0
По вопросам рекламы [email protected]