hl-api-changelog/changelogs/2026-07/16_notice_grassland_guide_4k_playback_buffering.md
2026-07-16 16:31:51 +08:00

6.2 KiB

草原指南 4K 原片播放缓冲优化通知

日期2026-07-16

前端仓库:mmg/hl-ui

影响页面:草原指南 H5 详情/播放页

本次后端接口、字段和 OSS 地址均无变化

1. 问题与诊断结论

草原指南详情直接播放后端返回的 OSS 原始 MP4。正式环境真实 4K 样本的媒体参数为:

  • 文件约 451.74 MiB,时长约 95 秒。
  • 分辨率 3812 × 216060 fps
  • H.264 Main Profile,Level 5.2
  • 平均码率约 40.20 Mbps
  • 1x 播放时短时峰值约 72.98 Mbps
  • 2x 播放时平均网络消耗约 80.40 Mbps;短时峰值约 142.17 Mbps

正式 OSS 已支持 HTTP Range,请求返回 206 Partial Content。同一诊断环境连续读取 OSS Range 的平均速度约 230.52 Mbps,高于该视频 2x 播放的短时峰值。因此目前没有证据表明 Java 服务或 OSS Range 能力是主要瓶颈;但该结果不代表每个用户到 OSS 的实时链路都能达到相同速度。

现已确认 1x 也会偶发卡顿。结合 1x 接近 73 Mbps 的短时峰值,更可能是用户链路瞬时波动与浏览器前向缓冲较浅共同造成:即使平均网速高于视频平均码率,只要短时间下载速度低于瞬时消耗速度,缓冲仍可能耗尽。因此首次 1x 播放和卡顿恢复也必须执行缓冲水位保护,不能只处理 2x

此外,4K 60 fps2x 下相当于设备需要承担接近 120 fps 的解码节奏。部分设备即使网络充足,也可能因硬件解码能力不足出现掉帧;前端需要把“等待网络缓冲”和“设备解码掉帧”分别记录。

2. 前端处理要求

2.1 保持原生 Range 播放

  • 继续直接使用接口返回的 videoUrl 作为 <video src>
  • 设置 preload="auto",允许浏览器提前加载媒体数据。
  • 不要使用 fetch/axios 把完整 MP4 下载为 Blob 后再播放,避免一次性占用数百 MiB 内存并破坏原生 Range 调度。
  • 不要改写 OSS 域名,不转成 HLS/M3U8,不接直播播放器。
  • 本轮不降低码率、不转码、不新增清晰度档位。

2.2 计算真实前向缓冲

不能只读取 video.buffered.end(video.buffered.length - 1)。应找到包含 currentTime 的 buffered 区间,再计算:

function getBufferAhead(video) {
  const currentTime = video.currentTime

  for (let index = 0; index < video.buffered.length; index += 1) {
    const start = video.buffered.start(index)
    const end = video.buffered.end(index)

    if (currentTime >= start && currentTime <= end) {
      return Math.max(0, end - currentTime)
    }
  }

  return 0
}

2.3 1x 与倍速播放缓冲策略

  • 用户首次点击 1x 播放时,若前向缓冲不足 8 秒,先显示“正在缓冲”;达到 8 秒后再开始播放。
  • 1x 播放过程中前向缓冲低于 3 秒时进入缓冲状态,恢复到 810 秒后继续播放。
  • 用户选择 2x 时,若前向缓冲不足 15 秒,先保持暂停并显示“正在缓冲”,达到 15 秒后再以 2x 播放。
  • 2x 播放过程中前向缓冲低于 5 秒时进入缓冲状态,恢复到 1215 秒后继续播放。
  • 原生播放器触发 waitingstalled 时,无论当前倍速是多少,都进入统一缓冲流程并按当前 playbackRate 对应的恢复水位继续播放。
  • 用户主动暂停、拖动进度或离开页面时取消自动恢复,避免播放器违背用户操作。
  • preload="auto" 只是浏览器提示,不能单独保证缓冲量;必须以 video.buffered 的实际结果作为判断依据。

阈值是针对当前约 40 Mbps 的 4K 原片给出的首轮参数。前端应按播放倍速集中定义为常量,便于根据真机数据调整,不要散落魔法值。

2.4 记录卡顿证据

至少监听并记录以下事件和状态:

  • 事件:loadstartloadedmetadatacanplaycanplaythroughprogresswaitingstalledplayingseekingseekederror
  • 状态:currentTimeplaybackRate、前向缓冲秒数、readyStatenetworkState
  • 浏览器支持时记录 getVideoPlaybackQuality()droppedVideoFramestotalVideoFrames

日志不得记录完整带签名 URL、Token 或其他凭证。建议只记录 videoId、事件时间和上述播放指标。

判断口径:

  • 出现 waiting/stalled,同时前向缓冲接近 0:网络或缓冲调度不足。
  • 前向缓冲充足、没有 waiting,但 droppedVideoFrames 持续上升:设备解码能力不足。

3. 接口契约

播放接口保持不变:

GET /admin/grassland-guide/public/videos/{videoId}/play

前端继续使用:

字段 类型 说明
videoId string 视频业务 ID
videoUrl string OSS 原始 MP4 地址,直接交给原生 <video>
durationSeconds integer 后端从素材解析的时长
effectiveCoverUrl string 生效封面

雪花 ID 必须按字符串处理。本次不增加缓冲、码率或清晰度字段,前端不得等待后端返回这些字段后才处理播放。

相关接口说明见:

4. 前端验收清单

  • <video> 使用接口原始 videoUrl,并设置 preload="auto"
  • 没有将完整 MP4 下载为 Blob。
  • 首次 1x 播放前按真实 buffered 结果预缓冲,播放中有低水位保护。
  • 2x 播放前使用更高的预缓冲与恢复水位。
  • waiting/stalled1x 和倍速播放下均进入统一缓冲恢复流程。
  • 用户暂停、拖动和离开页面时不会被自动恢复播放。
  • 能区分并记录缓冲耗尽与设备解码掉帧。
  • 使用正式 4K 样本分别连续验证 1x2x,记录等待次数、累计等待时长、最小前向缓冲和掉帧数。
  • Chrome 桌面端和目标移动设备均完成验证。

若完成上述缓冲策略后,多个地区和设备仍普遍出现“前向缓冲耗尽”,再单独评估 OSS 前置 CDN Range 缓存或 OSS 传输加速;该基础设施调整会新增费用,不属于本次前端通知范围。