PHP 输出视频流 在线视频读取 隐藏真实播放地址 兼容ios 设备 UC浏览器等

废话不多说 直接上代码 这个是支持在线读取远程视频文件的,分段读取 已测试支持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();
?>

 

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值