PHP 输出视频流 在线视频读取 隐藏真实播放地址 兼容ios 设备 UC浏览器等
废话不多说直接上代码这个是支持在线读取远程视频文件的,分段读取已测试支持ios及iosuc浏览器,代码中的算法还可以优化,需要的朋友请自行修改,视频地址可能会失效,到时候换成你需要的就行了。该带码经过测试,在2h2g的服务器上支持多人在线观看,同时不消化内存(具体多少人自行测试吧。免得说我忽悠你)。这里小小的说明一下代码中是通过curl携带请求头Range:bytes={$start}-{$end
废话不多说 直接上代码 这个是支持在线读取远程视频文件的,分段读取 已测试支持ios 及ios uc浏览器,代码中的算法还可以优化,需要的朋友 请自行修改,视频地址可能会失效,到时候换成你需要的就行了。
该带码经过测试,在2h2g 的服务器上支持多人在线观看,同时不消化内存(具体多少人自行测试吧。免得说我忽悠你)。
这里小小的说明一下 代码中是通过 curl 携带请求头 Range:bytes={$start}-{$end} 去分段读取视频流的,而并非一次性读取,这样服务器内存会炸掉。同时在输出视频流的前提下 header 要对,否则浏览器无法正确读取,这里无法正确读取主要是ios uc 浏览器标准严格,一旦有一个错了就会播放不出来。
每次加载大小为5M 支持随意快进,当然加载速度快慢取决于你的服务器,我用的是国外的服务器做的测试
如果您需要的是 读取本地视频文件的方法可以查看我的另外一篇博文
https://blog.csdn.net/qq_40729514/article/details/104194963
本代码为原创,转载请注明版权,请珍惜作者劳动成果,拥抱开源!
如果我的内容对您有所帮助,请点赞支持,谢谢!
<?php
#作者:APan
#时间:2020-09-15
#文章地址:https://blog.csdn.net/qq_40729514
#转载请注明版权,尊重作者成果
ini_set('memory_limit', '1024M'); //修改脚本的最大运行内存
set_time_limit(600); //设置超时限制为 10分钟
//输出视频流
function outPutStream($videoUrl) {
if(!$videoUrl){
header('HTTP/1.1 500 Internal Server Error');
echo "Error: Video cannot be played !";
exit();
}
//获取视频大小
$header_array = get_headers($videoUrl, true);
$sizeTemp = $header_array['Content-Length'];
if (is_array($sizeTemp)) {
$size = $sizeTemp[count($sizeTemp) - 1];
} else {
$size = $sizeTemp;
}
//初始参数
$start = 0;
$end = $size - 1;
$length = $size;
$buffer = 1024 * 1024 * 5; // 输出的流大小 5m
//计算 Range
$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];
$start = (int)$ranges[0];
if ($ranges[1] != '') {
$end = (int)$ranges[1];
}
$length = min($end - $start + 1, $buffer);
$end = $start + $length - 1;
}else{
// php 文件第一次浏览器请求不会携带 RANGE 为了提升加载速度 默认请求 1 个字节的数据
$start=0;
$end=1;
$length=2;
}
//添加 Range 分段请求
$header = array("Range:bytes={$start}-{$end}");
#发起请求
$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, $videoUrl);
curl_setopt($ch2, CURLOPT_TIMEOUT, 60);
curl_setopt($ch2, CURLOPT_HTTPHEADER, $header);
//设置读取的缓存区大小
curl_setopt($ch2, CURLOPT_BUFFERSIZE, $buffer);
// 关闭安全认证
curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch2, CURLOPT_SSL_VERIFYHOST, false);
//追踪返回302状态码,继续抓取
curl_setopt($ch2, CURLOPT_HEADER, false);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch2, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($ch2, CURLOPT_NOBODY, false);
curl_setopt($ch2, CURLOPT_REFERER, $videoUrl);
//模拟来路
curl_setopt($ch2, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 Edg/85.0.564.44");
$content = curl_exec($ch2);
curl_close($ch2);
#设置响应头
header('HTTP/1.1 206 PARTIAL CONTENT');
header("Accept-Ranges: bytes");
header("Connection: keep-alive");
header("Content-Type: video/mp4");
header("Access-Control-Allow-Origin: *");
//为了兼容 ios UC这类浏览器 这里加个判断 UC的 Content-Range 是 起始值-总大小减一
if($end!=1){
$end=$size-1;
}
header("Content-Range: bytes {$start}-{$end}/{$size}");
//设置流的实际大小
header("Content-Length: ".strlen($content));
//清空缓存区
ob_clean();
//输出视频流
echo $content;
//销毁内存
unset($content);
}
#输出视频流 视频地址可能失效,您可以换成你的来测试
outPutStream("https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4");
die();
?>
更多推荐
所有评论(0)