美文网首页
修复video标签在safari中无法播放mp4视频的问题

修复video标签在safari中无法播放mp4视频的问题

作者: 有时右逝 | 来源:发表于2019-05-06 10:38 被阅读0次

前言

近期一个站长联系我,向我求救解决一个bug,该问题在网络上很多遇到,但是没有正常的解决方案。
特此记录下。

问题

该站长有一个discuz论坛,其中在帖子中发布视频时,如果添加的视频地址是其他站点的地址或者图片下的视频路径,可以正常播放。

如果使用附件中地址,则异常。

image.png

其中无法播放的地址的代码如下

<video   controls="controls" width="100%" >
                <source src="forum.php?mod=attachment{$is_archive}&aid=$aidencode" type="video/mp4"></video>

原因

safari浏览器,在打开视频的时候,他不是一次性请求全部文件的,一般首先会请求0-1字节,这个写在request header的"range"字段中:range:'bytes=0-1'


image.png

chrome也会发送range,只不过它是这样的: 'bytes=0-',表示可以一次性加载整个视频文件。

image.png

如果是想要传输视频,必须要解析range字段,然后按照range字段的要求返回对应的数据,同时response header至少要包含三个字段:"Content-Type", "Content-Range", "Content-Length"
"Content-Type"必需明确指定视频格式,有"video/mp4", "video/ogg", "video/mov"等等。
"Content-Range"格式是 "bytes <start>-<end>/<total>",其中start和end必需对应request header里的range字段,total是文件总大小,不是返回的数据长度
"Content-Length"指定返回的二进制长度

这里需要注意:所有的end是指inclusive end,意味着文件长度如果是245,返回"Content-Range"就是"bytes 0-244/245",错一点视频就放不出来了。

如果你的视频文件可以被直接访问,则以上解析工作是由nginx来处理的。你无需处理,通常可以正常播放。

如果你的视频是编码输出的,例如需要php或者java等读取二进制流,则需要手动处理。

解决

php针对range解析视频流的代码如下:

$total = filesize($filename);
        if(isset($_SERVER['HTTP_RANGE'])) {
            $range = str_replace('=','-',$_SERVER['HTTP_RANGE']);
            $range = explode('-',$range);
            if (isset($range[2]) && intval($range[2]) >0){
                $end = trim($range[2]);
            }else{
                $end = $total-1;
            }
            $start = trim($range[1]);
            $size = $end-$start+1;
            header('Content-Length:'.$size);
            header('Content-Range: bytes '.$start.'-'.$end.'/'.$total);
        } else {
            $size = $total;
            header('Content-Length:'.$size);
            header('Content-Range: bytes 0-'.($total-1).'/'.$total);
        }
        header('Accenpt-Ranges: bytes');
        header('Content-Type: video/mpeg4');
        $fp = fopen($filename,'rb+');
        fseek($fp,$start);
        while(!feof($fp)) {
            print(fread($fp,$size));
            flush();
            ob_flush();
        }
        fclose($fp);

相关文章

网友评论

      本文标题:修复video标签在safari中无法播放mp4视频的问题

      本文链接:https://www.haomeiwen.com/subject/pogloqtx.html