You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP Curl请求HLS流并自定义UA嵌入HTML Video报错500求助

问题分析与修复建议

你的代码出现500错误主要是几个核心问题导致的,逐一解决如下:

  • 类方法调用错误:你直接调用了类的非静态方法getStreamChunk,但没有先实例化VideoStream类,PHP会直接抛出致命错误。
  • 重复发送HTTP头:callback函数在每次curl接收数据块时都会发送一次HTTP头,而HTTP头只能在响应开始时发送一次,重复发送会触发错误。
  • 未定义的类属性:代码中使用了$this->path但没有在类中定义这个属性,@filemtime($this->path)会产生警告,可能导致后续错误。
  • 错误的HTML嵌入方式:你把整个PHP逻辑直接写在<source>的src属性里,浏览器会将这些代码解析为URL的一部分,完全不符合HTTP请求逻辑,应该将代理逻辑单独放在一个PHP文件中,HTML通过URL引用该文件。

修正后的代码实现

第一步:创建单独的HLS代理脚本(hls-proxy.php)

<?php
class VideoStream
{
    public function callback($curl, $data)
    {
        static $headersSent = false;
        // 只发送一次HTTP头
        if (!$headersSent) {
            header("Content-type: application/x-mpegURL");
            header("Transfer-encoding: chunked");
            header("Connection: keep-alive");
            header("Cache-Control: max-age=2592000, public");
            header("Expires: " . gmdate('D, d M Y H:i:s', time() + 2592000) . ' GMT');
            // 移除未定义的$this->path相关头,如需保留请先在类中定义该属性并赋值
            $headersSent = true;
        }

        if ($data === false || $data == null) {
            $error = curl_error($curl) . " " . curl_errno($curl);
            error_log($error);
            echo $error;
            return 0;
        }

        $length = strlen($data);
        echo $data;
        ob_flush();
        flush();
        return $length;
    }

    public function getStreamChunk($hls_url)
    {
        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_URL => $hls_url,
            CURLOPT_HEADER => 0,
            CURLOPT_USERAGENT => 'mycustomagent',
            CURLOPT_FOLLOWLOCATION => 1,
            CURLOPT_WRITEFUNCTION => [$this, "callback"],
            CURLOPT_FAILONERROR => true, // 捕获HTTP错误码
        ]);

        $result = curl_exec($curl);
        if (!$result) {
            $error = curl_error($curl) . " " . curl_errno($curl);
            error_log($error);
            http_response_code(500);
            echo $error;
        }
        curl_close($curl);
    }
}

// 实例化类并调用方法
$stream = new VideoStream();
// 通过GET参数传递HLS地址,提升灵活性
$hlsUrl = $_GET['url'] ?? "https://example.com/example/186.m3u8";
$stream->getStreamChunk($hlsUrl);
?>

第二步:修改HTML页面代码

<video id='hls-video' controls>
    <source src='hls-proxy.php?url=https://example.com/example/186.m3u8' type='application/x-mpegURL'>
</video>

额外注意事项

  • 确保服务器开启了PHP的curl扩展,否则无法使用curl功能。
  • 若HLS流包含分片(.ts文件),当前代理仅转发m3u8文件,分片请求不会经过代理,可能导致授权失败。这种情况需要进一步修改代理逻辑,让所有分片请求都通过该代理转发。
  • 开启PHP错误日志(修改php.ini中的error_log配置),方便查看500错误的具体原因,快速定位问题。

内容的提问来源于stack exchange,提问作者FARIS ISMAIL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:57:40