本文目录导读:

针对PHP处理直播流的问题,需要先明确一点:PHP本身并不适合直接处理高并发、低延迟的实时流媒体数据(如RTMP、HLS)。 PHP通常作为业务逻辑层和API网关,负责控制、调度、鉴权,而核心的流媒体转发、转码工作由专业的流媒体服务器(如Nginx-RTMP、SRS、FFmpeg)完成。
以下是PHP处理直播流的典型架构和实现方案:
核心架构:PHP vs 流媒体服务器
- 流媒体服务器(核心):负责接收推流、转码、分发。
- 常用:
Nginx + nginx-rtmp-module,SRS (Simple-RTMP-Server),Live555,Node-Media-Server
- 常用:
- PHP API服务(辅助):负责业务逻辑。
- 生成推流/播放地址(鉴权Token)。
- 管理直播间状态(创建、结束、禁播)。
- 处理回调(推流开始/结束、录制完成等)。
- 对接数据库和用户系统。
常见场景与PHP处理方式
场景1:生成和管理推流/播放地址(最常用)
这是PHP最擅长的领域,你不会让PHP直接推流,而是让它根据规则生成带有效期的URL,控制谁能推流、谁能观看。
流程:
- 用户请求创建直播间。
- PHP生成一个唯一的流名称(
StreamKey),并将其与AppName、用户ID、过期时间关联存入Redis/MySQL。 - PHP返回一个推流地址给主播端(如OBS):
rtmp://your-domain.com/live/{stream_key}?token={hash}。 - PHP返回一个播放地址给观众端(如Video.js):
http://your-domain.com/live/{stream_key}.flv或hls/stream_key.m3u8。
PHP代码示例(生成推流Token鉴权):
<?php
// 生成推流令牌,用于简单的防盗链
function generateStreamToken($userId, $streamKey, $expireTime) {
$secret = 'your_very_secret_key_123!'; // 与流媒体服务器配置的密钥一致
$data = $userId . $streamKey . $expireTime;
$hash = hash_hmac('sha256', $data, $secret);
return [
'push_url' => "rtmp://live.yourdomain.com/live/{$streamKey}?token={$hash}&expire={$expireTime}",
'play_url' => [
'flv' => "http://play.yourdomain.com/live/{$streamKey}.flv",
'hls' => "http://play.yourdomain.com/live/{$streamKey}.m3u8"
]
];
}
// 假设用户创建直播间
$userId = 12345;
$streamKey = uniqid('stream_', true); // 随机且唯一的流名
$expire = time() + 7200; // 2小时有效
$urls = generateStreamToken($userId, $streamKey, $expire);
echo json_encode($urls);
?>
关键配置(Nginx-RTMP):
# nginx.conf
rtmp {
server {
listen 1935;
application live {
live on;
record off;
# -- 鉴权(关键) --
# 当推流时,Nginx会请求PHP的API检查Token
on_publish http://your-api.com/auth/publish.php;
# 录制、转码等...
hls on;
hls_path /tmp/hls;
}
}
}
PHP鉴权回调脚本(auth/publish.php):
<?php
// 假设请求是这个:http://your-api.com/auth/publish.php?name=stream_key&token=xxx&expire=xxx
$streamKey = $_GET['name'] ?? '';
$token = $_GET['token'] ?? '';
$expire = $_GET['expire'] ?? 0;
// 1. 检查时间是否过期
if ($expire < time()) {
header('HTTP/1.0 403 Forbidden');
echo "Token expired";
exit;
}
// 2. 验证哈希
$secret = 'your_very_secret_key_123!';
$userInfo = getUserIdFromStreamKey($streamKey); // 从数据库获取
$expectedHash = hash_hmac('sha256', $userInfo['id'] . $streamKey . $expire, $secret);
if (!hash_equals($expectedHash, $token)) {
header('HTTP/1.0 403 Forbidden');
echo "Invalid token";
exit;
}
// 3. 验证成功,允许推流
header('HTTP/1.0 200 OK');
echo "Authenticated";
exit;
?>
场景2:监听流状态回调(推流/断流事件)
流媒体服务器(如Nginx-RTMP、SRS)支持在推流开始、结束、录制完成时,通过HTTP通知我们的PHP服务。
Nginx配置:
application live {
live on;
# 推流开始回调
on_publish http://your-api.com/callback/stream_start;
# 推流结束回调
on_publish_done http://your-api.com/callback/stream_end;
# 录制完成回调
on_record_done http://your-api.com/callback/record_done;
}
PHP回调处理(stream_end.php):
<?php
// 收到推流结束通知
$streamKey = $_POST['name'] ?? '';
$clientId = $_POST['clientid'] ?? '';
// 1. 更新数据库:将该直播间状态设为“已结束”或“离线”
$db->update('live_rooms', ['status' => 'offline', 'end_time' => date('Y-m-d H:i:s')], "stream_key = '$streamKey'");
// 2. 可以清理临时文件或发送WebSocket通知
// sendWebSocketNotification($streamKey, 'stream_ended');
echo "OK";
?>
场景3:处理录制文件(转码、存档、截图)
流媒体服务器可以自动录制直播流为FLV或MP4文件,PHP可以用于:
-
接收录制完成回调:处理并存储文件信息到数据库。
-
后台异步处理:使用
exec()或proc_open()调用FFmpeg进行视频截图、转码为小文件、生成水印等。<?php // 收到录制完成回调 $inputFile = '/path/to/recorded/stream-12345.flv'; $outputThumb = '/path/to/thumbs/stream-12345.jpg'; // 注意:主进程不要阻塞,建议使用消息队列 $cmd = "ffmpeg -i $inputFile -ss 00:00:10 -vframes 1 $outputThumb 2>&1"; exec($cmd, $output, $returnCode); if ($returnCode === 0) { // 保存截图路径到数据库 } ?>
重要限制与解决方案
| 限制 | 说明 | 解决方案 |
|---|---|---|
| 内存/时间 | PHP有max_execution_time和内存限制,不适合处理长时间流的转码。 |
使用exec()调用外部命令(FFmpeg),或用消息队列(RabbitMQ/Redis)异步处理。 |
| 并发 | PHP-FPM处理大量流媒体连接(如几千个观看者)会耗尽资源。 | 播放端不要直接连PHP,直接连Nginx/HLS/CDN,PHP只处理API请求。 |
| WebSocket/RTMP | PHP原生不支持低延迟的WebSocket或RTMP协议。 | 使用Swoole/Workerman(PHP常驻内存)或直接在流媒体服务器(Nginx-RTMP)配置。 |
推荐工作流程总结
主播(OBS)
|
| (推送RTMP流,带Token)
V
流媒体服务器 (Nginx-RTMP / SRS) <--- 推流回调通知 ---> PHP API服务
| (鉴权、记录状态、发通知)
| (自动HLS切片 / FLV分发)
V
CDN / 直接访问
|
| (HTTP-FLV / HLS)
V
观众 (Video.js / VLC)
实际生产建议
- 不要用PHP处理裸流数据:PHP的长连接、二进制数据处理能力弱。
- 使用成熟的流媒体方案:
- 推流:OBS、RTMP SDK(移动端直接用)。
- 服务器:推荐
SRS或Nginx-RTMP(社区版够用)。 - 播放器:
Vue/React使用Video.js或flv.js (HTTP-FLV)。
- PHP的定位:写好RESTful API,做好鉴权 (推流Token, 播放Referer/时间戳) 和回调 (Webhook)。
- 大并发考虑:在PHP和流媒体服务器之间加一层消息队列(如Kafka/RabbitMQ)来缓冲回调请求,防止高频回调打挂PHP。
如果你能提供更具体的场景(是搭建一个完整的直播系统,还是处理某个特定流?),我可以给出更精确的代码或配置示例。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播