通过php直接输出的文件通常不被html5的<video>标签支持,尤其是ios设备。为了完美支持html5的视频播放,php必须支持byte-range请求。因为html5播放视频之前会发送一个只需文件少数字节的请求,确认服务端是否支持byte-range请求,支持才会继续发送请求剩余的文件数据。
具体的问题就是?byte-range ,相信遇到这个问题的朋友也在网上搜索到了许多相关的问题,接下来下面是整理后的代码,经测试苹果端可支持播放,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?php $localfile = "test.mp4"; $size = filesize($localfile); $start = 0; $end = $size - 1; $length = $size; header("Accept-Ranges: 0-$size"); header("Content-Type: video/mp4"); $ranges_arr = array(); if (isset($_SERVER['HTTP_RANGE'])) { if (!preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/i', $_SERVER['HTTP_RANGE'])) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); } $ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6)); foreach ($ranges as $range) { $parts = explode('-', $range); $ranges_arr[] = array($parts[0],$parts[1]); } $ranges = $ranges_arr[0]; if($ranges[0]==''){ if($ranges[1]!=''){ //Range: bytes=-n 表示取文件末尾的n个字节 $length = (int)$ranges[1]; $start = $size - $length; }else{ //Range: bytes=- 这种形式不合法 header('HTTP/1.1 416 Requested Range Not Satisfiable'); } }else{ $start = (int)$ranges[0]; if($ranges[1]!=''){ //Range: bytes=n-m 表示从文件的n偏移量读到m偏移量 $end = (int)$ranges[1]; } //Range: bytes=n- 表示从文件的n偏移量读到末尾 $length = $end - $start + 1; } header('HTTP/1.1 206 PARTIAL CONTENT'); } header("Content-Range: bytes {$start}-{$end}/{$size}"); header("Content-Length: $length"); $buffer = 8096; $file = fopen($localfile, 'rb'); if($file){ fseek($file, $start); while (!feof($file) && ($p = ftell($file)) <= $end){ if ($p + $buffer > $end) { $buffer = $end - $p + 1; } set_time_limit(0); echo fread($file, $buffer); flush(); } fclose($file); } die; ?> |
将代码中的 视频地址更换成你自己本地的视频地址,然后就可以跑起来了。如果有问题请留言指出不足之处,谢谢!
注意:该代码仅支持本地文件流的读取和输出!不支持url?形式的文件。