PHP项目实现“点评本场观众氛围”方案
要在PHP项目中实现观众氛围点评功能,核心是收集数据 → 分析/生成评价 → 展示,下面给你一套完整可落地的思路。

整体架构
观众行为数据采集 → 数据存储 → 氛围评分算法 → 生成点评文案 → 前端展示
数据采集维度
需要先定义哪些行为能反映“氛围”:
| 维度 | 数据来源 | 权重示例 |
|---|---|---|
| 弹幕/评论数量 | 实时消息表 | 30% |
| 点赞/礼物数 | 互动记录 | 25% |
| 在线人数峰值 | 会话统计 | 20% |
| 互动频次(人均) | 计算得出 | 15% |
| 情绪倾向(关键词) | 弹幕情感分析 | 10% |
数据库设计
-- 互动事件表
CREATE TABLE audience_events (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
room_id INT NOT NULL,
user_id INT NOT NULL,
event_type ENUM('danmaku','like','gift','enter','share') NOT NULL,
content TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_room_time (room_id, created_at)
);
-- 氛围点评结果表
CREATE TABLE atmosphere_reports (
id INT PRIMARY KEY AUTO_INCREMENT,
room_id INT NOT NULL,
session_id VARCHAR(64) NOT NULL,
score TINYINT, -- 0-100
level VARCHAR(20), -- 冷清/一般/活跃/火爆
comment TEXT, -- 点评文案
metrics JSON, -- 原始指标快照
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
核心评分算法(PHP)
<?php
class AtmosphereAnalyzer
{
public function analyze(int $roomId, string $sessionStart, string $sessionEnd): array
{
$db = Database::getInstance();
// 1. 拉取本场数据
$sql = "SELECT event_type, COUNT(*) AS cnt, COUNT(DISTINCT user_id) AS users
FROM audience_events
WHERE room_id = ? AND created_at BETWEEN ? AND ?
GROUP BY event_type";
$rows = $db->query($sql, [$roomId, $sessionStart, $sessionEnd]);
$stats = ['danmaku'=>0,'like'=>0,'gift'=>0,'enter'=>0,'share'=>0,
'unique_users'=>0];
foreach ($rows as $r) {
$stats[$r['event_type']] = (int)$r['cnt'];
}
// 2. 计算人均互动
$uniqueUsers = $db->queryScalar(
"SELECT COUNT(DISTINCT user_id) FROM audience_events
WHERE room_id=? AND created_at BETWEEN ? AND ?",
[$roomId, $sessionStart, $sessionEnd]
) ?: 1;
$stats['unique_users'] = $uniqueUsers;
$totalInteractions = $stats['danmaku'] + $stats['like'] + $stats['gift'];
$perUser = $totalInteractions / $uniqueUsers;
// 3. 分项打分(每项满分100)
$scoreDanmaku = $this->normalize($stats['danmaku'], 500, 5000);
$scoreLike = $this->normalize($stats['like'], 200, 3000);
$scorePerUser = $this->normalize($perUser, 1, 10);
$scoreGift = $this->normalize($stats['gift'], 10, 200);
// 4. 加权总分
$score = (int) round(
$scoreDanmaku * 0.35 +
$scoreLike * 0.25 +
$scorePerUser * 0.20 +
$scoreGift * 0.20
);
// 5. 定级 + 生成点评
$level = $this->level($score);
$comment = $this->generateComment($level, $stats, $perUser);
// 6. 落库
$db->insert('atmosphere_reports', [
'room_id' => $roomId,
'session_id' => md5($sessionStart.$sessionEnd),
'score' => $score,
'level' => $level,
'comment' => $comment,
'metrics' => json_encode($stats),
]);
return compact('score','level','comment','stats');
}
// 归一化:把任意区间映射到 0-100
private function normalize(float $value, float $min, float $max): float
{
if ($value <= $min) return 0;
if ($value >= $max) return 100;
return ($value - $min) / ($max - $min) * 100;
}
private function level(int $score): string
{
return match(true) {
$score >= 85 => '火爆',
$score >= 65 => '活跃',
$score >= 40 => '一般',
default => '冷清',
};
}
private function generateComment(string $level, array $stats, float $perUser): string
{
$templates = [
'火爆' => "全场气氛炸裂!弹幕和礼物刷不停,人均互动 %.1f 次,这是本场的高光时刻 🔥",
'活跃' => "观众参与度很高,评论区热闹非凡,整体氛围非常不错 👍",
'一般' => "气氛尚可,部分观众积极互动,整体表现中规中矩。",
'冷清' => "本场较为安静,互动较少,建议主播多引导观众参与~",
];
$tpl = $templates[$level];
return str_contains($tpl, '%')
? sprintf($tpl, $perUser)
: $tpl;
}
}
进阶:接入 AI 生成更自然的点评
如果想点评更“像人话”,可接入大模型:
class AiCommentGenerator
{
public function generate(array $stats, int $score): string
{
$prompt = "根据以下直播间数据,用一句话点评本场观众氛围(活泼口语化,30字内):
弹幕数:{$stats['danmaku']}
点赞数:{$stats['like']}
礼物数:{$stats['gift']}
在线人数:{$stats['unique_users']}
综合评分:{$score}/100";
$resp = $this->callLLM($prompt); // 调用 OpenAI/通义等
return trim($resp);
}
private function callLLM(string $prompt): string
{
$ch = curl_init('https://api.openai.com/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . getenv('OPENAI_KEY'),
],
CURLOPT_POSTFIELDS => json_encode([
'model' => 'gpt-4o-mini',
'messages' => [['role'=>'user','content'=>$prompt]],
'temperature' => 0.8,
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
return $result['choices'][0]['message']['content'] ?? '氛围不错~';
}
}
触发时机
- 实时点评:WebSocket / Swoole 每隔 30 秒统计一次,前端实时展示。
- 场次结束点评:直播结束后触发一次完整分析,生成“本场氛围报告”。
- 定时任务:用
crontab或 Laravel Scheduler 批量跑。
// Laravel 示例
Schedule::call(fn() => (new AtmosphereAnalyzer())->analyze(
$roomId, now()->subHour(), now()
))->everyThirtySeconds();
优化建议
- 防刷:同一用户短时间大量弹幕要降权,避免刷屏拉高评分。
- 情感分析:对弹幕做正向/负向关键词匹配,负向多时不只看数量。
- 动态阈值:不同房间基数不同,
normalize的 min/max 可按房间历史均值动态调整。 - 缓存:Redis 缓存 5 分钟统计结果,减轻数据库压力。
- 可视化:用 ECharts 画氛围曲线,比文字点评更直观。
最小可用版本(MVP)
如果只是先跑通流程,可以直接用一个函数:
function commentAtmosphere(int $danmaku, int $likes, int $users): string {
$perUser = $users > 0 ? ($danmaku + $likes) / $users : 0;
$score = min(100, ($danmaku/50) + ($likes/30) + ($perUser*5));
return match(true) {
$score >= 80 => "🔥 氛围火爆,观众超活跃!",
$score >= 50 => "👍 氛围不错,互动积极。",
$score >= 20 => "🙂 氛围一般,还有提升空间。",
default => "😴 氛围较冷清,需要引导互动。",
};
}
如果你告诉我你用的是原生PHP / ThinkPHP / Laravel,以及是直播场景还是视频播放场景,我可以给出更贴合的完整代码。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播