PHP实现WebM视频流在Safari浏览器无法播放的问题排查
问题描述
我尝试通过PHP实现.webm格式视频的流式播放,但在Safari浏览器中显示空白播放器,其他浏览器可正常播放。
以下是Safari发起的所有请求及其请求和响应头的截图:
已尝试的解决方法
经调研了解到,当服务器不支持Range请求头时会出现Safari播放问题。
我已通过执行curl --range 0-99 http://localhost/video/play.php -o /dev/null测试,结果显示服务器支持自定义范围请求。
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 100 100 100 0 0 2889 0 --:--:-- --:--:-- --:--:-- 3571
参考了关于iOS上资源加载失败的相关解决方案。
测试结果
localhost/video/play.php (with webm file)- 仅在Chrome中可正常播放localhost/video/play.php (with mp4 file)- 在Chrome和Safari中均可正常播放localhost/video/test.mp4- 在Chrome和Safari中均可正常播放localhost/video/test.webm- 在Chrome和Safari中均可正常播放
目录结构
video ├── play.php (index file, passes the video file to the VideoStream.php) ├── VideoStream.php (The class for php streaming) ├── test.mp4 └── test.webm
文件内容
Play.php
<?php include "VideoStream.php"; // $filePath = './test.mp4'; $filePath = './test.webm'; $stream = new VideoStream($filePath); $stream->start();
VideoStream.php
<?php /** * Description of VideoStream * * @author Rana * @link http://codesamplez.com/programming/php-html5-video-streaming-tutorial */ class VideoStream { private $path = ""; private $extension = ""; private $stream = ""; private $buffer = 102400; private $start = -1; private $end = -1; private $size = 0; function __construct($filePath) { $this->path = $filePath; $this->extension = pathinfo($filePath)['extension']; } /** * Open stream */ private function open() { if (!($this->stream = fopen($this->path, 'rb'))) { die('Could not open stream for reading'); } } /** * Set proper header to serve the video content */ private function setHeader() { ob_get_clean(); $this->start = 0; $this->size = filesize($this->path); $this->end = $this->size - 1; header("Content-Type: video/" . $this->extension); header("Cache-Control: max-age=2592000, public"); header("Expires: " . gmdate('D, d M Y H:i:s', time() + 2592000) . ' GMT'); header("Last-Modified: " . gmdate('D, d M Y H:i:s', @filemtime($this->path)) . ' GMT'); header("Accept-Ranges: 0-" . $this->end); if (isset($_SERVER['HTTP_RANGE'])) { $c_start = $this->start; $c_end = $this->end; list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); if (strpos($range, ',') !== false) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $this->start-$this->end/$this->size"); exit; } if ($range == '-') { $c_start = $this->size - substr($range, 1); } else { $range = explode('-', $range); $c_start = $range[0]; $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end; } $c_end = ($c_end > $this->end) ? $this->end : $c_end; if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $this->start-$this->end/$this->size"); exit; } $this->start = $c_start; $this->end = $c_end; $length = $this->end - $this->start + 1; fseek($this->stream, $this->start); header('HTTP/1.1 206 Partial Content'); header("Content-Length: " . $length); header("Content-Range: bytes $this->start-$this->end/" . $this->size); } else { header("Content-Length: " . $this->size); } } /** * close curretly opened stream */ private function end() { fclose($this->stream); exit; } /** * perform the streaming of calculated range */ private function stream() { $i = $this->start; set_time_limit(0); while (!feof($this->stream) && $i <= $this->end) { $bytesToRead = $this->buffer; if (($i + $bytesToRead) > $this->end) { $bytesToRead = $this->end - $i + 1; } $data = fread($this->stream, $bytesToRead); echo $data; flush(); $i += $bytesToRead; } } /** * Start streaming video content */ function start() { $this->open(); $this->setHeader(); $this->stream(); $this->end(); } }
NGINX配置
我使用的是NGINX,不确定是否会导致问题,附上/video/路径的配置:
location /video/ { alias /var/www/video/; index index.html; error_page 404 /usr/share/nginx/html/index.html; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass video:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param PATH_INFO $fastcgi_path_info; } try_files $uri $uri/ /index.php$is_args$args /index.php =404; autoindex on; }
编辑:仍在寻找解决方案。
内容的提问来源于stack exchange,提问作者Gabriel Atanasov
相关产品推荐
相关产品推荐




