VOD 深度剖析 第 10 篇:QoE 指标 —— 如何衡量用户真实的观看感受
QoE 与 QoS 的区别、六大核心指标(VST、RBR、VSF、EBVS、VPF、平均码率)、数据管道、多维度下钻、故障排查案例,以及自建还是采购的抉择。
这是 VOD 流媒体深度剖析 系列的第 10 篇。
QoE 与 QoS:两个常被混淆的术语
| 缩写 | 全称 | 定义 | 视角 |
|---|---|---|---|
| QoS | Quality of Service(服务质量) | 客观的网络/基础设施性能(带宽、丢包、延迟) | 网络工程 / 运维 |
| QoE | Quality of Experience(体验质量) | 用户主观感知的质量 | 产品 / 用户研究 |
QoS 说的是”我在以 10 Mbps 交付内容”。QoE 说的是”用户真的能流畅观看、不卡顿吗?”
同样的 QoS,因播放器实现、ABR 策略和编码参数不同,可能产生截然不同的 QoE。
我们关心的是 QoE。 运营一个视频平台却没有 QoE 数据,就像管理高速公路系统却不监测交通拥堵。
六大核心 QoE 指标
1. 视频启动时间(VST)
定义:从用户按下播放到首帧渲染出来所经过的秒数。
目标值:
- 移动端短视频:P50 < 300ms,P95 < 800ms
- 长视频 VOD:P50 < 1s,P95 < 2s
最敏感的指标。 用户无法容忍 2 秒的黑屏。
2. 卡顿率(RBR)
定义:rebuffer_time / (rebuffer_time + play_time)
示例:用户观看了 60 秒,累计卡顿 3 秒。RBR = 3/(60+3) = 4.8%。
目标值:< 0.5%(优秀),< 1%(可接受)。
直接影响留存:Conviva 的研究表明,RBR 每上升 1%,观看时长就会下降 2–5%。
3. 视频启动失败(VSF)
定义:用户触发了播放,但首帧始终未能渲染(由于 404、CORS、DRM 错误等原因)。
目标值:< 1%
Conviva 进一步将其细分:
- VSF-T(技术性):因技术原因失败 —— 计入 QoE 失败
- VSF-B(业务性):因业务原因失败(未订阅、地域封锁)—— 不计入 QoE
4. 启动前退出(EBVS)
定义:用户触发了播放,但在首帧出现之前主动离开 —— 不是错误,只是没耐心。
目标值:< 3%
与 VST 强相关。启动越慢 → EBVS 越高 → 留存越差。
5. 视频播放失败(VPF)
定义:播放过程中崩溃(解码错误、证书过期、CDN 流中断)。
目标值:< 0.5%
6. 平均码率
定义:实际播放过程中各码率档位按时间加权的平均值。
用途:衡量用户实际看到的画质是否可接受。如果 70% 的用户平均只有 480p,可能意味着:
- 网络状况普遍较差
- ABR 算法过于保守
- 高码率档位没有被转码出来
辅助指标
| 指标 | 说明 |
|---|---|
| 卡顿频率 | 每分钟播放中的卡顿事件数(目标:< 0.1/分钟) |
| 码率切换 | 画质切换的次数和幅度(越稳定越好) |
| 视频完播率 | 看完整个视频的用户占比(业务指标) |
| 密钥解码耗时 | 获取 DRM 许可证所需时间 |
| 首字节时间 | 从 CDN 收到首个字节所需时间 |
Conviva 的 SPI:一个综合指数
SPI(Streaming Performance Index,流媒体性能指数):Conviva 的综合 KPI,代表体验”良好或非常好”的会话占比。
一个会话被判定为”良好”,需要同时满足:
- 无 VSF-T 或 VPF-T 错误
- 无卡顿或卡顿极少(CIRR 低于阈值)
- 平均码率达到屏幕尺寸对应的画质门槛
- 视频启动时间在可接受范围内
- 用户在退出前没有等待过久
单一指标可能产生误导(例如 RBR 很低但码率极低)。SPI 提供了一个整体视角。
多维度下钻
绝不要只看”整体 RBR”。始终要按维度切分:
| 维度 | 示例 |
|---|---|
| 地理 | 国家 / 州省 / 城市 / ISP |
| 设备 | 操作系统版本、机型、芯片组、屏幕尺寸 |
| 网络 | WiFi / 4G / 5G、吞吐量区间 |
| CDN | 服务商、PoP、Shield |
| 内容 | 标题、分辨率档位、编码格式、时长 |
| 时间 | 小时、天、周 |
| 用户 | 新/老用户、付费/免费、地区 |
标准排查流程:
Overall RBR spiked to 2% → cause unknown
↓ Drill by CDN → CDN-A RBR 5%, CDN-B RBR 0.3%
↓ Drill CDN-A by region → Mumbai RBR 12%
↓ Drill Mumbai by time → 19:00-22:00 peak spike
→ Conclusion: CDN-A Mumbai PoP degraded during evening peak
→ Action: Route India traffic to CDN-B
数据管道:从客户端到看板
典型架构
┌──────────────┐
│ Client SDK │
│ (iOS/Android/ │── HTTPS batch POST every 5-10s
│ Web) │ (events JSON)
└──────────────┘
│
▼
┌──────────────┐
│ Ingestion │ nginx / ALB / API Gateway / CloudFront
│ (Edge) │ with rate limiting + auth
└──────────────┘
│
▼
┌──────────────┐
│ Kafka │ Persistent message queue
│ Topic: qoe │ Partitioned by day
└──────────────┘
│
├─────────────────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Flink / Spark │ │ ClickHouse / │ Real-time data warehouse
│ Streaming │ │ BigQuery │
│ (aggregation) │ │ │
└──────────────┘ └──────────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Alerting │ │ BI Dashboard │ Grafana, Tableau, Looker
│ (PagerDuty) │ │ │
└──────────────┘ └──────────────┘
事件结构
每个事件都包含:
{
"event": "video_rebuffer_start",
"session_id": "uuid-...",
"user_id": "u-12345",
"video_id": "ep-789",
"timestamp": 1715084800123,
"player_version": "2.3.4",
"device": {
"os": "iOS",
"os_version": "17.4",
"model": "iPhone 15 Pro"
},
"network": {
"type": "cellular",
"carrier": "Verizon",
"effective_type": "4g"
},
"cdn": "cloudfront",
"bitrate": 2500000,
"buffer_level_sec": 0.8,
"position_sec": 45.2
}
批量上报 vs 实时上报
不要每个事件都发一个 HTTP 请求(10 万 DAU × 每用户 100 个事件 = 每天 1000 万次请求)。
批量策略:累积 10 秒或 50 个事件,再发送一次 POST。
真实故障排查案例
案例 1:整体 VST 飙升
Monday 9 AM: VST P50 jumped from 400ms to 1.2s
│
├── Drill by OS → Android VST spiked to 2s, iOS normal
│
├── Drill by app version → v3.4.5 all 2s, v3.4.4 normal
│
├── Check changelog → v3.4.5 introduced a new player library
│
└── Action: Emergency hotfix / rollback to v3.4.4
案例 2:单个剧集卡顿
New show Episode 3: RBR anomalously high at 5%
│
├── Drill by CDN → All CDNs high (not a CDN issue)
│
├── Check segments → One segment is 20 MB (others are 2 MB)
│
├── Check encoding log → 10-second action scene caused bitrate spike
│
└── Fix: Re-transcode with MaxBitrate cap on peak bitrate
案例 3:区域转化率下降
India new-user first-hour completion rate dropped from 30% to 15%
│
├── Drill by VST → India VST P50 rose from 0.8s to 3s
│
├── Drill by CDN → CDN-A edge node latency elevated in India
│
├── Ping test → CDN-A Mumbai PoP latency 400ms for 4 hours
│
└── Action: Route India traffic to CDN-B, escalate to CDN-A support
自建还是采购:Mux、Conviva,还是自研?
托管服务
| 服务 | 优势 |
|---|---|
| Mux | 对开发者友好、集成简单、约 $1.25/1K 会话 |
| Conviva | 企业级、功能最全面、也最贵 |
| Datadog RUM | 与 APM 集成在同一平台 |
| NPAW (YOUBORA) | 在欧洲市场实力强劲 |
优点:数小时即可集成、开箱即用的看板、零维护。 缺点:规模上来后昂贵、数据存放在第三方、可定制性有限。
自研
优点:完全可定制、数据可与业务指标(订单、留存)关联、规模化后成本更优。 缺点:开发/维护成本高、多平台 SDK 一致性难以保证。
常见的演进路径
- 早期阶段:采购 Mux —— 快速获得可用的看板
- 规模化阶段:自建管道 + 保留 Mux 作为对比基准
客户端 SDK 最佳实践
不要拖慢播放
QoE SDK 本身绝不能拖累体验:
- 在独立的低优先级线程上上报
- 网络失败:静默重试,绝不阻塞 UI
- SDK 崩溃绝不能拖垮整个 App
离线补偿
用户可能在离线状态下看完视频。恢复联网后:
- 离线期间事件写入本地 SQLite/文件
- 恢复连接后按 FIFO 顺序批量上传
时钟对齐
设备时钟可能不准确:
- 以服务器时间戳(HTTP
Date头)作为基准 - 事件携带相对时间(相对会话开始的
delta_ms)
规模化采样
超大规模下,100% 上报成本过高:
- 关键错误事件:始终 100% 上报
- 普通事件:按 10–30% 采样
- 按 user_id 做哈希,确保对单个用户全采或全不采(保留会话完整性以便分析)
必备看板
看板 1:全局概览
- DAU、总播放会话数
- VST P50 / P95
- RBR、VSF、VPF
- SPI(综合评分)
- Top 10 国家下钻
看板 2:CDN 健康度
- 各 CDN 的 RBR、VST、错误率
- CDN 对比面板(同一时间窗口)
- CDN 边缘节点地图
看板 3:内容质量
- 新标题上线首 24 小时的质量指标
- 各标题的完播率和 RBR
- 异常标题告警
看板 4:设备与版本
- 各 App 版本的错误率
- 各操作系统版本的 VST
- 各设备机型的 RBR
QoE 优化闭环
QoE 数据不是用来被动观察的 —— 它驱动工程决策:
Data reveals problem
│
▼
Locate root cause
(CDN? Encoding? ABR?)
│
▼
Try fix + A/B test
│
▼
Verify QoE improved
│
▼
Ship to 100% + keep monitoring
每周 QoE 复盘是每个成熟视频团队的标准做法。
关键要点
- QoE 衡量的是用户主观感知的体验,而非网络指标。
- 六大核心指标:VST / RBR / VSF / EBVS / VPF / 平均码率。
- Conviva 的 SPI 是一个综合的”良好体验会话占比”指标。
- 数据必须按多个维度切分 —— 单一的全局数字无法定位问题。
- 标准管道:客户端 SDK -> Kafka -> Flink/ClickHouse -> BI。
- 早期阶段从 Mux/Conviva 起步;规模足够时再转向自研。
- QoE 数据驱动决策 —— 每周复盘。
上一篇: 第 9 篇:视频播放器
下一篇: 第 11 篇:端到端工作流
参考资料
- VMAF — perceptual video quality metric — Netflix / GitHub
- hls.js — GitHub