本文目录导读:

- 方案一:第三方云平台(最推荐,成本最低、最稳定)
- 方案二:自建服务器 + Nginx-RTMP 模块(中小规模,适合内网或开发环境)
- 方案三:WebRTC 推流到自建服务器(低延迟,现代方案)
- 方案四:纯 PHP 尝试推流(极不推荐,仅供了解)
- 总结与建议
在PHP项目中实现直播推流,通常遵循一个核心原则:PHP本身不擅长处理长时间、高并发的流媒体数据,因此PHP的角色通常是作为“控制层”或“业务调度层”,而真正的推流工作由专门的流媒体服务器(如Nginx + RTMP、SRS、ZLMediaKit)或第三方云平台完成。
下面是几种主流且可行的实现方案,按推荐度从高到低排列:
第三方云平台(最推荐,成本最低、最稳定)
这是企业级项目最常用的方式,PHP只负责生成推流地址(鉴权)和调用API,推流由客户端(OBS、手机APP、浏览器)直接完成。
流程:
- PHP后端:调用腾讯云/阿里云/声网等平台的API,生成一路“推流地址”和“播流地址”,存入数据库,通常包含
rtmp://publish.com/live/streamName?txSecret=xxx格式。 - 客户端(前端):从PHP后端获取推流地址,如果是OBS,直接填入地址;如果是Web,使用
WebRTC或Flv.js+MediaRecorder推流。 - 云平台:负责接收RTMP/WebRTC流,进行转码、分发。
- 播放器:PHP输出播放地址(HLS/FLV/WebRTC)给前端。
PHP代码示例(以腾讯云为例):
<?php
// 假设使用腾讯云云直播 (CSS)
require_once 'vendor/autoload.php'; // 引入SDK
function generatePushUrl($streamName, $key, $domain = 'yourpushdomain.com') {
$appName = 'live';
$txTime = strtoupper(dechex(strtotime('+1 day'))); // 过期时间
$txSecret = md5($key . $streamName . $txTime);
return "rtmp://{$domain}/{$appName}/{$streamName}?txSecret={$txSecret}&txTime={$txTime}";
}
// 使用
$pushUrl = generatePushUrl('stream_123', 'your_secret_key');
echo $pushUrl; // 返回RTMP地址给前端
适用场景: 任何需要快速上线、稳定可靠的直播项目,缺点是有流量费用。
自建服务器 + Nginx-RTMP 模块(中小规模,适合内网或开发环境)
在服务器上搭建nginx-rtmp-module,PHP通过执行系统命令或FFmpeg进行推流。
环境搭建:
# 安装 Nginx 及 RTMP 模块(以 Ubuntu 为例) sudo apt install nginx libnginx-mod-rtmp
Nginx配置(/etc/nginx/nginx.conf):
rtmp {
server {
listen 1935; # RTMP默认端口
chunk_size 4096;
application live { # 应用名,推拉流时使用
live on;
record off;
}
}
}
PHP实现推流:
PHP通过 exec() 或 proc_open() 调用 ffmpeg 将本地文件或摄像头流转发给Nginx-RTMP,注意:这会导致PHP进程长时间阻塞,因此必须使用异步方式,
<?php
// 方案A:后台执行FFmpeg(不推荐,会产生僵尸进程)
$streamUrl = 'rtmp://你自己的服务器IP/live/stream123';
$inputFile = '/tmp/input_video.mp4'; // 循环推一个视频文件
$ffmpegCmd = "ffmpeg -re -i {$inputFile} -c:v libx264 -f flv {$streamUrl} > /dev/null 2>&1 &";
exec($ffmpegCmd, $output, $returnVar);
echo "推流进程已启动(状态码:$returnVar)";
// 方案B(推荐):使用消息队列 + 守护进程
// 1. PHP 将推流任务发布到 Redis 队列: "push_task:{stream_id}"
// 2. 一个独立的 PHP 脚本或 Go 进程(worker)从队列中读取任务,运行FFmpeg
// 这样PHP请求瞬间返回,不做耗时操作。
适用场景: 学习测试、内网监控直播、对成本敏感但能接受服务器资源消耗的小项目。
WebRTC 推流到自建服务器(低延迟,现代方案)
利用SRS或ZLMediaKit等支持WebRTC的流媒体服务器,PHP作为信令服务器。
流程:
- PHP WebSocket Server(如Workerman/Swoole):处理信令(offer/answer/ICE)。
- 客户端浏览器:获取麦克风/摄像头(
getUserMedia),创建RTCPeerConnection。 - PHP将客户端的SDP转发给流媒体服务器,建立P2P连接。
- 服务器将WebRTC流转为RTMP或HLS分发。
PHP + Workerman 信令伪代码:
use Workerman\Worker;
$ws_worker = new Worker('websocket://0.0.0.0:8080');
$ws_worker->onMessage = function($connection, $data) {
$msg = json_decode($data, true);
if ($msg['type'] == 'offer') {
// 转发给流媒体服务器指定的端口
$mediaServer = stream_socket_client('tcp://127.0.0.1:9000');
fwrite($mediaServer, json_encode(['stream_id' => $msg['id'], 'sdp' => $msg['sdp']]));
}
// ...
};
适用场景: 需要毫秒级延迟的互动直播(教育、直播带货PK),但开发难度较大。
纯 PHP 尝试推流(极不推荐,仅供了解)
PHP可以通过解析FLV格式、塞入RTMP协议包来推流,但几乎不可用。
// 使用第三方库如 php-rtmp // 这种方式性能极差,内存泄漏严重,没有实际生产价值。
总结与建议
| 需求 | 推荐方案 | PHP角色 |
|---|---|---|
| 快速上线,不想管服务器 | 云平台(推荐) | 生成推流地址,调用API |
| 内网/监控/教学演示 | Nginx-RTMP | 调用FFmpeg后台推流 |
| 毫秒级延迟、Web端互动 | ZLMediaKit + WebSocket | 信令调度 + 业务处理 |
| 高性能自建流媒体 | SRS + PHP守护进程 | 业务管理,不参与流数据处理 |
关键避坑提示:
- 绝对不要在PHP的HTTP请求(
fpm或apache module)中直接执行ffmpeg推流并等待它结束,这会阻塞整个PHP进程,导致超时。 - 推荐使用 消息队列(Redis/Beanstalkd)+ 独立的Producer/Consumer架构,PHP只负责推送任务,Worker进程负责长时间推流。
- 如果需要从摄像头或屏幕推流(Web端),请使用前端JS的
WebRTC或Flv.js,PHP只负责提供规则。