播放器触发了 seeked。页面也读到了 6 秒。这次跳转仍未通过我的验收。这是本轮视频实验里需要单独留下的一条结果:在 26 秒观察窗内,记录没有拿到目标画面的帧回调。我把事件和目标画面分开记录。
我在试用图映 ImgIng时实际导出了两段海浪视频,也另外准备了普通 MP4 做播放对照。本文的 seek 记录来自后者,不能直接算成图映功能的失败。我要确认的是网页里拖动进度条以后该拿什么作为完成依据。一次导出能结束,只能回答文件有没有产出,还没有回答播放器会怎样寻址。
我测了两份普通 MP4,把动作固定在一个比较早的时刻:首帧出现后再等 500 毫秒,暂停视频并将 currentTime 设为 6 秒。两份样本都长 8 秒。帧率为 25fps。本地服务的传输预算是每秒 256 KiB。每条请求开始前等待 80 毫秒。我刻意没等全片读完,想看到尚在加载时改变播放位置的结果。
我分别保存了设置的目标、seeked 到达时的 currentTime,以及帧回调携带的 mediaTime。前两项用来对照想去哪里和实际落在哪里。第三项用于检查实际回调对应的画面时间。MDN 对 seeked 的定义描述的是寻址操作结束与 seeking 状态变化,并不是为任意业务目标出具验收结果。
本轮通过条件设为 mediaTime 落在 6±0.15 秒内,也就是 5.85 到 6.15 秒。这里通过 requestVideoFrameCallback 读取帧时间。0.15 秒是这轮实验选定的容差。它不是浏览器规范要求。25fps 下相邻帧间隔约 0.04 秒。这个容差覆盖了不止一帧,因此不足以证明精确命中了某一帧。
先出现的是目标被钳位的情况。A 样本索引在文件头部、服务端忽略 Range 时,Chromium 149 两次都停在 0 秒,没有到达 6 秒。当时的 seekable 为 0,0。Firefox 151 在相同组合下两次分别落在 1.16 秒和 0.36 秒。这两次都没有到达目标位置。很快返回不代表很快完成了指定跳转。
另一种结果更容易漏掉。B 样本同样使用头部索引并忽略 Range,WebKit 26.5 测试构建触发了 seeked,currentTime 也是 6 秒,但 26 秒内没有取得符合条件的目标帧回调。我把它留在"画面未验收"一栏。记录不足以证明屏幕永远不会更新。这一项的根因还没有定位。
作为成功对照,A 样本头部索引配合支持 Range 的服务时,Chromium 两次到达目标帧用时 0.601 秒和 0.608 秒,中位数为 0.605 秒。这里从发起 seek 开始计时。它不包括此前加载到首帧的时间。这样记录以后,首帧、寻址事件和目标帧才不会被混成一个"视频加载耗时"。
配图是B样本尾部索引加支持Range的成功对照,页面记录已显示第6秒画面。它来自本地受控复现页。这张图对应自己的输入与条件,不能替代前述A片钳位和WebKit未取得目标回调的记录。图中的3.35秒是单次跳转耗时,不能抄作其他组的中位数。海浪画面旁的时间与日志配合起来才有意义。

测量在 2026 年 9 月 30 日的 macOS 26.5.2 上完成,每个普通 MP4 组合重复两次。WebKit 是测试构建,不能据此宣称正式 Safari 一定如此。图片素材来自 דוד שי 的 Wikimedia Commons 海浪,按 CC BY-SA 4.0 使用并做了截取、缩放和转码。非本人拍摄。
排查自己的播放器时,我会先保存目标时间和操作前的 seekable。seeked 时刻的实际位置也要留下。需要验证目标画面时就追加帧回调的 mediaTime,并预先写清允许误差和观察时长。位置被钳回去时先记录早期可寻址范围。位置已到却没有目标帧证据时仍保留未通过状态。下载完成后可以另做一轮对照。早期操作的失败记录也应保留,才能区分两种时机下的表现。