播放报表
播放报表把用户活动日志聚合成可运营的趋势、排行与下钻视图,面向需要看「谁在看、看什么、什么时候看、耗了多少流量」的站长与运营者。

能做什么
- 在 8 种时间预设之间一键切换,或自定义起止时间
- 用 5 档粒度看趋势,长跨度自动降级,避免一次拉太多数据点
- 看 6 张概览卡,每张都带与上一周期的环比
- 看播放、流量、并发三条趋势线与两张时段热力图
- 查活跃用户榜、热门内容、不活跃用户榜、设备/客户端分布
- 点进单个用户,看他的播放规律与最近 50 次明细
- 一键导出当前视图为 CSV
数据从哪来
报表只有一个数据源:用户活动日志。所有图表都在查询时实时聚合,没有为报表单独建预聚合表——这意味着报表口径永远和明细一致,但超大时间范围的查询会更慢,可以用时间粒度(按天 / 按周 / 按月)来缓解。
表里每条记录带:用户、事件类型、时间、session_id、client_ip、user_agent、媒体标识、duration_ms、bytes_delta、position_sec / runtime_sec、result / reason、extras。
时区固定为 Asia/Shanghai
所有分桶与「今天/昨天/昨晚」的边界都按东八区计算,页面上不提供时区切换。
日志由客户端的 Emby 三段式上报写入(Sessions/Playing → Progress → Stopped),流量字节由 play-agent 按实际写给客户端的字节计量后上报,不在前端估算。
统计维度
| 维度 | 说明 |
|---|---|
| 时间 | 按所选粒度分桶;热力图按「日期 × 小时」 |
| 用户 | 活跃榜、不活跃榜、单用户下钻、人均观看 |
| 媒体 | 热门内容、媒体类型偏好、按媒体类型筛选 |
| 会话 | 按 session_id 统计同时在线播放数与峰值并发 |
| 客户端与设备平台 | 由 user_agent 解析出客户端与平台分布 |
这些维度没有
- 没有节点维度:不能按 play-agent 节点或播放入口拆分统计。
- 没有地域维度:表里有
client_ip,但只做展示,没有 IP 归属地聚合。 - 没有播放成功率与错误分布:表里有
result/reason字段,报表未使用它们。
时间范围与粒度
8 种时间预设
| 预设 | 范围 |
|---|---|
| 昨晚 21-00 | 昨晚 21:00 至今晨 00:00 |
| 今天 | 今日 00:00 起 |
| 昨天 | 昨日全天 |
| 近 24 小时 | 从当前时刻往前 24 小时 |
| 近 7 天 | 从当前时刻往前 7 天 |
| 近 30 天 | 从当前时刻往前 30 天 |
| 近 90 天 | 从当前时刻往前 90 天 |
| 自定义 | 自行指定起止时间 |
另有两项筛选可叠加:媒体类型与单个用户。
5 档粒度与自动降级
| 粒度 | 值 |
|---|---|
| 半小时 | halfHour |
| 小时 | hour |
| 天 | day |
| 周 | week |
| 月 | month |
粒度不是任选的,服务端按时间跨度自动收敛:
| 时间跨度 | 实际生效粒度 |
|---|---|
| 小于 1 天 | 强制半小时 |
| 正好 1 天 | 强制小时 |
| 大于 1 天 | 保留你的选择,但半小时降为小时 |
传入无法识别的粒度值时回落到 hour。跨度超过 1 天时,界面上的「按半小时」选项是禁用状态;接口返回的 granularity 是实际生效值,页面按它渲染横轴。
6 张概览卡
每张卡都显示当前值与上一周期的环比变化率。上一周期定义为「与当前窗口等长、紧邻在前」的一段时间——例如选近 7 天,环比对象就是再往前的 7 天。
| 卡片 | 含义 |
|---|---|
| 活跃用户 | 窗口内产生过播放的去重用户数 |
| 播放次数 | 窗口内的播放事件总数 |
| 总观看时长 | 累计观看时长 |
| 总流量 | 累计写出字节数 |
| 人均观看 | 总观看时长 ÷ 活跃用户 |
| 峰值并发 | 窗口内同时在线播放会话数的峰值 |
8 类图表
图表基于 echarts(^6.1.0)自封装为 Line / Bar / Heatmap 三类组件,统一带骨架屏与空态。热力图分两张,所以页面上共 9 个图表区块。
| # | 图表 | 内容 |
|---|---|---|
| 1 | 播放趋势 | 三系列折线:活跃用户、播放次数、观看时长(分钟) |
| 2 | 流量使用趋势 | 折线并标注峰值点与该峰值所在时间桶 |
| 3 | 同时在线播放 | 折线,按 session_id 统计,标注峰值;粒度可能与主粒度不同,以接口返回为准 |
| 4 | 观看时段热力图(按播放次数) | 日期 × 小时 |
| 5 | 观看时段热力图(按观看时长) | 日期 × 小时 |
| 6 | 活跃用户榜 | 取前 20,可切换三种排序:按观看时长 / 按播放次数 / 按流量 |
| 7 | 热门内容 | 窗口内播放最多的条目 |
| 8 | 不活跃用户榜单 | 每页数量可选 10 / 20 / 50 / 100 |
| 9 | 设备 / 客户端分布 | 客户端与平台占比 |
3 个下钻抽屉
| 抽屉 | 入口 | 内容 |
|---|---|---|
| 单用户分析 | 活跃用户榜 / 不活跃用户榜点用户名 | 累计观看、活跃天数、平均完成率、占全站比例、每月播放规律、24 小时活跃分布(播放次数)、星期分布(观看时长)、媒体类型偏好、平台占比、最近 50 次播放明细(含播放进度) |
| 内容观看用户明细 | 热门内容点条目 | 看过这个条目的用户列表 |
| 设备使用用户明细 | 设备/客户端分布点某项 | 用这个客户端或平台的用户列表 |
单用户抽屉有独立的分析范围下拉(近 30 天 / 近 90 天 / 近半年 / 近一年),不受主报表时间预设限制;抽屉标题上会同时标出主报表当前的筛选范围,便于对照。
导出 CSV
导出完全在浏览器前端生成,不请求服务端导出接口。
| 项 | 值 |
|---|---|
| 格式 | CSV,带 UTF-8 BOM(用表格软件打开中文不乱码) |
| 文件名 | playback-report-{from}-{to}-{granularity}.csv,日期取 YYYY-MM-DD |
| 内容 | 筛选范围、时间粒度、媒体类型 + 6 项概览的「当前值 / 上一周期 / 变化 %」 + 完整 timeline 明细(时间点、活跃用户、播放次数、观看时长 ms、字节) |
只有 CSV
没有 Excel(.xlsx)导出,没有服务端导出端点,也没有定时邮件报表。导出的数据量等于当前时间范围内的 timeline 桶数,长跨度请先调粗粒度。
数据保留与清理
报表能看多久,取决于活动日志保留多久。
| 项 | 值 |
|---|---|
| 配置键 | user.activity_log.retention_days |
| 取值范围 | 7 – 3650 天(前端兜底值;实际 min / max / default 由后端接口返回) |
| 接口默认值 | 90 天 |
| 配置入口 | 系统配置 → 常用设置 → 用户活动日志保留期,快捷值 30 / 90 / 180 / 365 / 730 天 |
| 清理执行 | 每日调度任务「用户活动日志清理」按当前阈值删除更早的事件 |
改完保留期不会立刻删数据,要等下一次清理任务运行。延长保留期能让报表看到更长的月度、年度规律,缩短则节省磁盘。
历史默认值变过
数据库迁移 V232 把该项初始默认设为 90 天,V242 改为 365 天;管理接口返回的 default 仍是 90。你看到的实际值以页面上显示的「当前值」为准。
权限
- 菜单键是
reports,网关规则/api/auth/admin/reports/要求reports或user权限。 reports在权限判定表里,但委派 UI 未开放——不能把这个页面单独委派给非管理员账号。可委派的 8 个 key 里没有它。
相关接口
GET /api/auth/admin/reports/overview
GET /api/auth/admin/reports/timeline
GET /api/auth/admin/reports/concurrent
GET /api/auth/admin/reports/heatmap
GET /api/auth/admin/reports/top-users
GET /api/auth/admin/reports/top-media
GET /api/auth/admin/reports/inactive-users
GET /api/auth/admin/reports/devices
GET /api/auth/admin/reports/user/{userId}
GET /api/auth/admin/reports/media-watchers
GET /api/auth/admin/reports/device-users
GET /api/auth/admin/activity-log/retention