You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过PHP实现视频流代理转发?跨地域流媒体加速方案咨询

PHP实现视频流式代理方案

没问题,这个需求用PHP的流式代理就能完美解决——不需要在服务器B上存储任何视频文件,直接把视频源A的内容分块实时转发给用户。下面是具体的实现思路、代码示例和关键注意事项:

核心实现思路

  1. 用户向服务器B的代理脚本发起请求,携带视频源A的地址(或脚本内置指定)
  2. 服务器B通过cURL向视频源A发起请求,不缓存完整视频,而是实时获取分块数据
  3. 将视频源A的响应头(如视频类型、长度、分片支持等)转发给用户浏览器,确保播放器能正常处理
  4. 把从A获取的每一段数据立刻输出给用户,同时禁用PHP输出缓冲,实现实时流式传输

完整代码示例

创建一个名为video-proxy.php的脚本,放在服务器B的Web根目录下:

<?php
// 彻底禁用输出缓冲,保证实时分块传输
ob_end_clean();
ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
ini_set('max_execution_time', 0); // 取消脚本执行时间限制,适配长视频传输

// --------------------------
// 安全配置:仅允许指定域名的视频源
// --------------------------
$allowedVideoDomains = ['your-target-video-site.com']; // 替换为视频源A的域名
$targetVideoUrl = $_GET['video_url'] ?? '';

// 验证请求的视频源合法性
if (empty($targetVideoUrl)) {
    http_response_code(400);
    echo "Missing video URL parameter";
    exit;
}

$parsedUrl = parse_url($targetVideoUrl);
if (!isset($parsedUrl['host']) || !in_array($parsedUrl['host'], $allowedVideoDomains)) {
    http_response_code(403);
    echo "Forbidden: Unauthorized video source";
    exit;
}

// --------------------------
// 初始化cURL请求视频源A
// --------------------------
$curlHandle = curl_init($targetVideoUrl);

// 设置cURL选项:流式输出、跟随重定向、获取响应头
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, false);
curl_setopt($curlHandle, CURLOPT_HEADER, true);
curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, true); // 建议保持true,若遇证书问题可临时改为false

// 自定义回调函数:实时处理并转发数据
curl_setopt($curlHandle, CURLOPT_WRITEFUNCTION, function($curl, $data) {
    static $isHeaderSent = false;

    if (!$isHeaderSent) {
        // 分离响应头和内容
        $headerEndPosition = strpos($data, "\r\n\r\n");
        if ($headerEndPosition !== false) {
            // 提取并转发合法响应头
            $rawHeaders = substr($data, 0, $headerEndPosition);
            foreach (explode("\r\n", $rawHeaders) as $headerLine) {
                $headerLine = trim($headerLine);
                if (empty($headerLine)) continue;

                // 跳过可能干扰流式传输的头
                if (stripos($headerLine, 'Transfer-Encoding') === 0 
                    || stripos($headerLine, 'Content-Encoding') === 0
                    || stripos($headerLine, 'Connection') === 0) {
                    continue;
                }

                header($headerLine);
            }

            // 输出头部后的第一块内容
            echo substr($data, $headerEndPosition + 4);
            $isHeaderSent = true;
        }
    } else {
        // 实时输出视频内容分块
        echo $data;
        flush(); // 强制刷新输出缓冲区
        ob_flush();
    }

    return strlen($data);
});

// 执行cURL请求
curl_exec($curlHandle);

// 处理请求错误
if (curl_errno($curlHandle)) {
    if (!headers_sent()) {
        http_response_code(500);
    }
    echo "Proxy Error: " . curl_error($curlHandle);
}

curl_close($curlHandle);
exit;
?>

关键细节说明

  • 禁用输出缓冲:这是实现流式传输的核心,必须关闭PHP的输出缓冲,否则数据会被缓存到服务器内存中,无法实时转发给用户。
  • 响应头处理:转发视频源的Content-TypeContent-LengthAccept-Ranges等头信息,让浏览器能识别视频格式、支持进度条和快进快退。
  • 安全限制:一定要通过$allowedVideoDomains限制允许的视频源,防止你的服务器被滥用为通用代理。
  • 支持Range请求:cURL会自动处理浏览器发送的Range请求(比如用户拖动进度条),并从视频源获取对应分块,脚本只需转发即可。

部署注意事项

  1. 服务器配置:确保服务器B的PHP允许修改max_execution_time,且Web服务器(Apache/Nginx)没有额外的输出缓冲配置(比如Nginx的proxy_buffering要关闭)。
  2. 带宽要求:服务器B的带宽要足够支撑视频流传输,建议选择和视频源A同区域的服务器,确保跨区域传输速度更快。
  3. HTTPS支持:如果视频源A是HTTPS,服务器B需要配置有效的SSL证书,否则浏览器可能会阻止请求。

内容的提问来源于stack exchange,提问作者Giorgi Tsertsvadze

火山引擎 最新活动