前言
近期一個站長聯(lián)系我,向我求救解決一個bug凄诞,該問題在網(wǎng)絡上很多遇到圆雁,但是沒有正常的解決方案。
特此記錄下帆谍。
問題
該站長有一個discuz論壇摸柄,其中在帖子中發(fā)布視頻時,如果添加的視頻地址是其他站點的地址或者圖片下的視頻路徑既忆,可以正常播放。
如果使用附件中地址嗦玖,則異常患雇。
其中無法播放的地址的代碼如下
<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'
chrome也會發(fā)送range器瘪,只不過它是這樣的: 'bytes=0-'翠储,表示可以一次性加載整個視頻文件绘雁。
如果是想要傳輸視頻,必須要解析range字段援所,然后按照range字段的要求返回對應的數(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必需對應request header里的range字段,total是文件總大小滔岳,不是返回的數(shù)據(jù)長度
"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);