修復(fù)video標(biāo)簽在safari中無法播放mp4視頻的問題

前言

近期一個站長聯(lián)系我,向我求救解決一個bug,該問題在網(wǎng)絡(luò)上很多遇到,但是沒有正常的解決方案。
特此記錄下。

問題

該站長有一個discuz論壇,其中在帖子中發(fā)布視頻時,如果添加的視頻地址是其他站點的地址或者圖片下的視頻路徑,可以正常播放。

如果使用附件中地址,則異常。

image.png

其中無法播放的地址的代碼如下

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

原因

safari瀏覽器,在打開視頻的時候,他不是一次性請求全部文件的,一般首先會請求0-1字節(jié),這個寫在request header的"range"字段中:range:'bytes=0-1'


image.png

chrome也會發(fā)送range,只不過它是這樣的: 'bytes=0-',表示可以一次性加載整個視頻文件。

image.png

如果是想要傳輸視頻,必須要解析range字段,然后按照range字段的要求返回對應(yīng)的數(shù)據(jù),同時response header至少要包含三個字段:"Content-Type", "Content-Range", "Content-Length"
"Content-Type"必需明確指定視頻格式,有"video/mp4", "video/ogg", "video/mov"等等。
"Content-Range"格式是 "bytes <start>-<end>/<total>",其中start和end必需對應(yīng)request header里的range字段,total是文件總大小,不是返回的數(shù)據(jù)長度
"Content-Length"指定返回的二進(jìn)制長度

這里需要注意:所有的end是指inclusive end,意味著文件長度如果是245,返回"Content-Range"就是"bytes 0-244/245",錯一點視頻就放不出來了。

如果你的視頻文件可以被直接訪問,則以上解析工作是由nginx來處理的。你無需處理,通??梢哉2シ?。

如果你的視頻是編碼輸出的,例如需要php或者java等讀取二進(jìn)制流,則需要手動處理。

解決

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);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容