php搭建直播推流系统需协同流媒体服务器实现四大功能:一、基于时间戳与密钥生成带签名的鉴权推流url;二、调用ffmpeg命令行执行本地推流并管理进程;三、通过http回调接口校验推流合法性;四、使用jwt签发与校验带载荷的安全token。

如果您希望使用PHP搭建直播推流系统,需通过PHP后端与流媒体服务器(如SRS、Nginx-rtmp、ZLMediaKit)协同完成推流地址生成、流名签发及访问鉴权。以下是实现该功能的具体方法:
一、基于时间戳与密钥的URL鉴权推流地址生成
该方法利用服务端动态拼接含有效期和签名的RTMP/HTTP-FLV推流URL,防止未授权推流。核心是构造形如rtmp://server/app/stream?sign=xxx&ts=171xxxxxx的带参地址,流媒体服务器校验签名与时间戳合法性。
1、在PHP中定义密钥常量:define('STREAM_SECRET_KEY', 'aB3#kL9mQp2R');
2、获取当前时间戳并计算过期时间(例如5分钟):$ts = time(); $expire = $ts + 300;
3、拼接待签名字符串:$strToSign = "stream={$streamName}&app={$appName}&ts={$ts}&expire={$expire}";
4、使用HMAC-SHA256生成签名:$sign = hash_hmac('sha256', $strToSign, STREAM_SECRET_KEY);
5、组合最终推流地址:$pushUrl = "rtmp://192.168.1.100/live/{$streamName}?sign={$sign}&ts={$ts}&expire={$expire}";
二、通过PHP调用FFmpeg命令行执行本地推流
该方法适用于后台触发推流任务,例如用户点击“开始直播”后,PHP生成配置并调起FFmpeg进程将本地视频或摄像头画面推送至流媒体服务器。
1、确认服务器已安装FFmpeg且具备执行权限:exec('ffmpeg -version', $output, $return); if ($return !== 0) die("FFmpeg未就绪");
2、构造推流命令字符串,包含分辨率、码率、关键帧间隔等参数:$cmd = "ffmpeg -f v4l2 -i /dev/video0 -vf scale=1280:720 -c:v libx264 -b:v 1500k -g 50 -c:a aac -b:a 128k -f flv '{$pushUrl}' 2>/dev/null &";
3、使用proc_open安全执行命令并捕获PID:$process = proc_open($cmd, [], $pipes, '/tmp', null, ['bypass_shell' => true]);
4、将进程PID写入数据库或Redis,用于后续停止控制:file_put_contents("/tmp/push_{$streamName}.pid", (string)proc_get_status($process)['pid']);
三、流媒体服务器回调鉴权:PHP接收HTTP GET请求验证推流合法性
当流媒体服务器(如SRS)收到推流请求时,可配置其向PHP接口发起HTTP GET回调,携带stream、app、clientip等参数,由PHP返回200表示允许,非200拒绝。
1、在SRS配置文件中启用http_hooks,设置on_publish为PHP脚本地址:on_publish http://yourdomain.com/auth/publish.php;
2、在publish.php中获取GET参数并校验来源IP白名单:$clientIp = $_SERVER['REMOTE_ADDR']; $allowedIps = ['192.168.1.100', '10.0.0.5']; if (!in_array($clientIp, $allowedIps)) { http_response_code(403); exit; }
3、解析URL参数中的stream名称,检查是否符合命名规范(如仅含字母数字下划线):$stream = $_GET['stream'] ?? ''; if (!preg_match('/^[a-zA-Z0-9_]{4,32}$/', $stream)) { http_response_code(400); exit; }
4、查询数据库确认该stream是否已被占用或处于禁用状态:$stmt = $pdo->prepare("SELECT status FROM streams WHERE name = ?"); $stmt->execute([$stream]); $row = $stmt->fetch(); if (!$row || $row['status'] !== 'active') { http_response_code(404); exit; }
5、返回HTTP 200响应,SRS即允许推流建立:http_response_code(200); echo 'ok';
四、JWT方式生成带载荷的推流Token并校验
该方法使用JSON Web Token封装用户ID、流名、过期时间等信息,由PHP签发Token,流媒体服务器通过内置JWT模块或外部脚本验证,提升安全性与可扩展性。
1、安装firebase/php-jwt库:composer require firebase/php-jwt
2、构建Token载荷数组,包含必要声明与自定义字段:$payload = ['uid' => 12345, 'stream' => 'live_001', 'iat' => time(), 'exp' => time() + 3600, 'iss' => 'php-stream-auth'];
3、使用私钥签名生成Token:$jwt = \Firebase\JWT\JWT::encode($payload, file_get_contents('/path/to/private.key'), 'RS256');
4、拼接含Token的推流地址:$pushUrl = "rtmp://192.168.1.100/live/live_001?token={$jwt}";
5、在流媒体服务器侧(如ZLMediaKit)配置JWT鉴权参数,指定公钥路径及需校验的claim字段:jwt: { enable: true, public_key: "/etc/zlmediakit/public.pem", require_claims: ["uid","stream"] }
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











