记录视频观看进度思路

再理想化的业务场景,也不可能满足所有用户的需求。在做视频观看进度统计时,最终统计的数据仅仅也只是相对准确。

我们可以采用打点合并法,监听 video 的 timeupdate 事件,再定义 throttle 函数对回调函数进行节流,控制在每 1000 ms 录点记录一次。假设某片段总时长为 90 分钟,正常的观看行为应该是从 0 分钟到 90 分钟。

1
const SNIPPET = [[0, 1], [1, 2], [2, 3], ...[89, 90]];

再设想几种快进快退的场景。

1
2
3
4
let scene_a = [[0, 1], [1, 10], [10, 11], [11, 12], ...[89, 90]]
let scene_b = [...[12, 13], [13, 20], [20, 21], ...[40, 41], [42, 49], [49, 50], ...[89, 90]]
let scene_c = [...[30, 31], [31, 11], [11, 12], ...[89, 90]]
let scene_d = [...,[30, 31], [31, 32], [32, 33], [33, 28], [28, 31], [31, 32]]

观察这部分数据,我们或许可以得到一些基本规律:正常行为下单个块的精度不会超过 1,如果某个块的精度大于 1 或者小于 0,就可以判断此处发生了快进或者快退的行为。

如果要强调行为数据,我们需要对无效块进行过滤,也就是抛弃掉代表快进或快退行为的块,只保留基本的行为数据。

BEFORE

1
2
3
4
scene_a = [[0, 1], [10, 11], [11, 12], ...[89, 90]]
scene_b = [...[12, 13],  [20, 21], ...[40, 41], [49, 50], ...[89, 90]]
scene_c = [...[30, 31], [11, 12], ...[89, 90]]
scene_d = [...,[30, 31], [31, 32], [32, 33], [31, 32]]

接下来将行为数据进行去重合并,让整个链路进度清晰一点。

AFTER

1
2
3
4
scene_a = [[0, 1], [10, 12], ...[89, 90]]
scene_b = [...[12, 13],  [20, 21], ...[40, 41], [49, 50], ...[89, 90]]
scene_c = [...[30, 31], [11, 12], ...[89, 90]]
scene_d = [...,[30, 33]]

最终对清洗后的数据进行一次合并,即可得到一段相对观看时间。

1
2
3
4
const getWatchProgress = (progressData) => {
  const currentTotal = progressData.reduce((acc, next) => acc + (next[1] - next[0]), 0);
  return `${(currentTotal / total / 0.01).toFixed(1)}` > 97 ? '100%' : `${currentTotal || 0}%`;
};