本文目录导读:

在PHP项目中实现直播录制与回放功能,通常需要结合流媒体服务器(如Nginx-RTMP、SRS、ZLMediaKit)和前端播放器(如Video.js、LivePlayer)来完成,以下是完整的实现方案和技术选型指南。
整体架构
直播推流 → 流媒体服务器 → 录制模块 → 文件存储 → PHP API → 前端播放
↓
实时转码
核心组件选型
流媒体服务器推荐
| 服务器 | 适合场景 | 特点 |
|---|---|---|
| SRS | 推荐首选 | 高性能、支持HLS/FLV/WebRTC,内置录制功能 |
| Nginx + RTMP模块 | 轻量级需求 | 配置简单,但功能相对单一 |
| ZLMediaKit | 高并发场景 | C++开发,性能极强 |
录制方案
服务器端自动录制(推荐)
使用SRS的dvr插件或Nginx-RTMP的录制指令:
SRS配置示例:
# srs.conf
listen 1935;
max_connections 1000;
vhost __defaultVhost__ {
dvr {
enabled on;
dvr_path /usr/local/srs/record/[app]/[stream]/[2006]-[01]-[02]-[15].[05].[06].flv;
dvr_plan session; # 每个推流生成一个文件
dvr_duration 0; # 0表示持续录制直到推流结束
dvr_wait_keyframe on;
}
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
}
Nginx-RTMP录制配置:
rtmp {
server {
listen 1935;
application live {
live on;
record all;
record_path /var/record;
record_unique on;
record_suffix _%Y%m%d_%H%M%S.flv;
}
}
}
通过FFmpeg录制(灵活性高)
// PHP调用FFmpeg录制
$cmd = "ffmpeg -i rtmp://localhost/live/{stream_id} -c copy -f flv /var/record/{stream_id}_".time().".flv";
exec($cmd . " > /dev/null 2>&1 &");
PHP后端实现
数据库设计
CREATE TABLE `live_records` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`room_id` int(11) NOT NULL COMMENT '直播间ID',
`stream_id` varchar(100) NOT NULL COMMENT '流标识', varchar(255) DEFAULT NULL COMMENT '录制标题',
`start_time` datetime NOT NULL COMMENT '开始录制时间',
`end_time` datetime DEFAULT NULL COMMENT '结束录制时间',
`duration` int(11) DEFAULT '0' COMMENT '时长(秒)',
`file_path` varchar(500) DEFAULT NULL COMMENT '录制文件路径',
`status` tinyint(4) DEFAULT '0' COMMENT '0录制中 1已完成',
`file_size` bigint(20) DEFAULT '0' COMMENT '文件大小(bytes)',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_stream` (`stream_id`),
KEY `idx_room` (`room_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
录制控制API
class RecordController {
// 开始录制
public function startRecord($roomId, $streamId) {
// 调用系统命令或API通知录制服务器
$cmd = "curl -X POST http://127.0.0.1:1985/api/v1/dvr/start -d '{
\"vhost\": \"__defaultVhost__\",
\"app\": \"live\",
\"stream\": \"{$streamId}\"
}'";
$result = exec($cmd);
// 记录到数据库
DB::table('live_records')->insert([
'room_id' => $roomId,
'stream_id' => $streamId,
'start_time' => date('Y-m-d H:i:s'),
'status' => 0
]);
}
// 停止录制
public function stopRecord($streamId) {
$cmd = "curl -X POST http://127.0.0.1:1985/api/v1/dvr/stop -d '{
\"vhost\": \"__defaultVhost__\",
\"app\": \"live\",
\"stream\": \"{$streamId}\"
}'";
exec($cmd);
// 更新记录
$record = DB::table('live_records')->where('stream_id', $streamId)
->where('status', 0)->first();
if ($record) {
$endTime = date('Y-m-d H:i:s');
DB::table('live_records')->where('id', $record->id)->update([
'end_time' => $endTime,
'duration' => strtotime($endTime) - strtotime($record->start_time),
'status' => 1,
'file_path' => "/record/{$streamId}.flv"
]);
}
}
}
回放列表API
// 获取回放列表
public function getRecordList($roomId, $page = 1, $limit = 20) {
$list = DB::table('live_records')
->where('room_id', $roomId)
->where('status', 1)
->orderBy('start_time', 'desc')
->paginate($limit);
return response()->json([
'code' => 0,
'data' => $list,
'message' => 'success'
]);
}
// 获取单个录制详情
public function getRecordDetail($recordId) {
$record = DB::table('live_records')->find($recordId);
return response()->json([
'code' => 0,
'data' => [
'id' => $record->id,
'title' => $record->title,
'start_time' => $record->start_time,
'duration' => $this->formatDuration($record->duration),
'file_url' => $this->getFileUrl($record->file_path),
'status' => $record->status
]
]);
}
前端播放实现
播放器选择
<!-- 使用Video.js播放HLS -->
<link href="https://vjs.zencdn.net/7.20.3/video-js.css" rel="stylesheet" />
<script src="https://vjs.zencdn.net/7.20.3/video.min.js"></script>
<video id="record-player" class="video-js vjs-default-skin" controls preload="auto" width="640" height="360">
<source src="https://your-domain.com/record/stream_id.m3u8" type="application/x-mpegURL">
</video>
<script>
var player = videojs('record-player');
</script>
直播回放点播
// 动态切换回放
function playRecord(recordId) {
fetch(`/api/record/detail?id=${recordId}`)
.then(response => response.json())
.then(data => {
if (data.code === 0) {
player.src({
src: data.data.file_url,
type: 'application/x-mpegURL'
});
player.play();
}
});
}
高级功能
录制文件转码
// 使用FFmpeg将flv转mp4
public function convertToMp4($inputFile, $outputFile) {
$cmd = "ffmpeg -i {$inputFile} -c copy -movflags +faststart {$outputFile} 2>&1";
exec($cmd, $output, $returnVar);
if ($returnVar === 0) {
return true;
}
return false;
}
云端存储集成
// 使用阿里云OSS
use OSS\OssClient;
public function uploadToOss($localFile, $ossKey) {
$client = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
$result = $client->uploadFile($bucket, $ossKey, $localFile);
return $result['oss-request-url'];
}
断点续传
// 分段上传
public function chunkUpload($file, $chunkIndex, $totalChunks) {
$tempPath = storage_path('chunks/' . $file['unique_id']);
file_put_contents($tempPath . '.' . $chunkIndex, file_get_contents($file['tmp_name']));
if ($chunkIndex == $totalChunks - 1) {
$finalFile = storage_path('records/' . $file['unique_id'] . '.mp4');
for ($i = 0; $i < $totalChunks; $i++) {
file_put_contents($finalFile, file_get_contents($tempPath . '.' . $i), FILE_APPEND);
unlink($tempPath . '.' . $i);
}
}
}
部署建议
服务器配置优化
# Nginx配置
server {
listen 80;
server_name live.example.com;
# 视频文件缓存
location /record {
root /var/www/records;
expires 7d;
add_header Cache-Control "public, immutable";
# 支持断点续传
add_header Accept-Ranges bytes;
}
# 直播流代理
location /live {
flv_live on;
chunked_transfer_encoding on;
add_header 'Access-Control-Allow-Origin' '*';
root /tmp;
}
}
高性能传输
// 使用分片读取大文件
public function streamVideo($filePath) {
header('Content-Type: video/mp4');
header('Content-Length: ' . filesize($filePath));
$fp = fopen($filePath, 'rb');
while (!feof($fp)) {
echo fread($fp, 8192);
ob_flush();
flush();
}
fclose($fp);
}
常见问题与解决方案
录制文件损坏
- 原因: 推流异常中断
- 解决: 启用
dvr_wait_keyframe参数,使用ffmpeg修复
回放卡顿
- 解决:
- 使用HLS分片播放
- 部署CDN加速
- 调整
dvr_duration为10秒分片
存储空间不足
- 解决:
- 自动清理规则
- 使用对象存储OSS/COS
- 设置录制时长限制
完整的PHP直播录制与回放方案需要以下组件配合:
- 流媒体服务器: SRS(推荐)或Nginx-RTMP
- 录制存储: 本地服务器或云端OSS
- PHP后端: 实现录制控制和回放管理
- 前端播放: Video.js或HLS.js
- 转码服务: FFmpeg转换格式
- CDN加速: 提升播放体验
对于中小型项目,推荐使用SRS + FFmpeg + 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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播