【问题标题】:PHP serve MP4 - Chrome "Provisional headers are shown/request is not finished yet" bugPHP 服务 MP4 - Chrome“临时标头已显示/请求尚未完成”错误
【发布时间】:2014-11-16 12:41:57
【问题描述】:

我想在允许他们观看视频之前检查用户的订阅,为此我使用 PHP 与 Stripe 交互以检查用户的订阅,而不是使用 PHP script 将 MP4 提供给浏览器

第一次在 Google Chrome 中播放视频时效果很好(使用 HTML5 播放器)... 但是当我关闭视频并再次播放时,视频不再播放......我也不能重新加载当前页面。就像服务器停止工作一样。

当我检查第一个视频请求(播放的那个)时,在“时间”选项卡中我看到:“注意:请求尚未完成!” (截图如下)

当我检查第二个视频请求(那个没有播放)时,在标题选项卡中显示“[警告标志] 显示临时标题”(下面的屏幕截图)

在 Safari 或 Firefox 中一切正常

有人知道发生了什么吗?再次播放视频的唯一方法是关闭当前选项卡,再次进入该站点。重新加载不起作用!

【问题讨论】:

  • 文件是本地的吗?如果是 - 您如何提供文件?
  • 我觉得奇怪的是Range 标头。在您的情况下,它是 bytes=0-Content-Range 标头的典型格式是 bytes 0-499/1234,这意味着文件的前 500 字节大小为 1234 字节。这就是为什么我要问您如何提供文件,因为您需要支持文件的可恢复下载/流式传输。查看更多信息:stackoverflow.com/a/4451376/1412896
  • 文档内容范围在这里:w3.org/Protocols/rfc2616/rfc2616-sec14.html
  • 还有一个对您解释 Chrome 行为有帮助的答案:stackoverflow.com/a/18745164/1412896 抱歉向您抛出信息,只是想提供帮助 :)
  • 范围由 chrome 作为对视频的第一个请求发送到服务器。 Content-Range 是来自服务器的标头响应吗?它不能解决我的问题,但无论如何谢谢:)

标签: php google-chrome http-headers video-streaming stripe-payments


【解决方案1】:

我建议您使用以下功能,而不是您当前的“流式传输脚本”。如果您传递 $filename_output,它将作为下载文件提供文件,否则它将流式传输!

它应该适用于所有浏览器。

serveFile('/where/my/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();
    }
}

【讨论】:

  • 其实我发现的答案更好,最通用。出于某种原因,没有人关心 Content-Range 标头。
【解决方案2】:

嗯,我当然是一个有趣的问题。而且真的很难在这里确定根本原因。但如果我是你的情况,我会检查两件事。

  1. 首先,我会确保在 httpd.conf 上将 keep-alive 设置为关闭 KeepAlive Off

  2. 然后使用此配置对其进行测试。

  3. 然后我会禁用所有浏览器缓存:

    header('Cache-Control: no-cache, no-store, must-revalidate'); header('Pragma: no-cache'); header('Expires: 0');

  4. 之后的最终测试。

问题似乎与保持活动或浏览器缓存或两者兼而有之,但我不明白为什么它只出现在 chrome 中。作为最后的手段,请确保您没有使用任何可能造成问题的扩展程序,例如 Adblock。

希望我能让你了解这些信息 :)

【讨论】:

    【解决方案3】:

    我在尝试流式传输音频文件时遇到了同样的问题。我最终完全巧合地解决了我的问题。

    我在某个时候创建​​了一个脚本,可以使用 FFMPEG 将文件的比特率降低到 128kbps(据我所知,也适用于视频)。之后在 chrome 中进行检查时,我开始注意到我的所有请求都在几秒钟后完成,而不是像以前那样无限期地保持不完整。不确定这对您是否可行,但压缩文件解决了这个问题并提高了流媒体速度,所以我强烈推荐这个。

    【讨论】:

      猜你喜欢
      • 2019-09-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 2020-10-25
      • 1970-01-01
      • 1970-01-01
      • 2019-12-24
      相关资源
      最近更新 更多