这个php项目如何点评本场观众氛围?

wen PHP项目 2

PHP项目实现“点评本场观众氛围”方案

要在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'] ?? '氛围不错~';
    }
}

触发时机

  1. 实时点评:WebSocket / Swoole 每隔 30 秒统计一次,前端实时展示。
  2. 场次结束点评:直播结束后触发一次完整分析,生成“本场氛围报告”。
  3. 定时任务:用 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,以及是直播场景还是视频播放场景,我可以给出更贴合的完整代码。

抱歉,评论功能暂时关闭!