判断弱网还是格式不支持需结合video.error.code、networkState及请求行为:code=2且networkState=0优先网络探测,code=4则验证canPlayType;iOS需监听stalled/waiting;preload="metadata"依赖服务端faststart;MSE切换需控制分片与缓冲水位;手动选清晰度须动态校验canPlayType并降级回退。

video.error.code 怎么判断是弱网还是格式不支持
直接读 video.error.code 不够,必须结合 video.networkState 和请求行为才能区分。常见错误中:MEDIA_ERR_NETWORK(值为2)大概率是弱网或服务不可达,但 MEDIA_ERR_SRC_NOT_SUPPORTED(值为4)才是真·格式不兼容。别只监听 onerror,它可能被冒泡事件干扰;改用 addEventListener('error', e => {...}) 绑定在 video 元素本身。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 若
video.networkState === 0(NETWORK_EMPTY)且video.error.code === 2,优先走网络探测:用fetch(url, { method: 'HEAD', signal: abortSignal })测连通性,超时设为 1500ms - 若
video.error.code === 4,检查video.canPlayType('video/mp4; codecs="av1"')返回值,空字符串就跳过该 source - iOS Safari 下
video.error常为 null,需额外监听stalled和waiting事件持续超 2s 视为弱网信号
preload="metadata" 在弱网下为什么反而更慢
因为服务端没配 Accept-Ranges: bytes,浏览器拿不到 moov box 就得下载前几 MB 甚至整个文件才能解析出时长——这在弱网下比 preload="none" 还耗流量、更卡。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 服务端必须加
ffmpeg -c copy -movflags +faststart处理 MP4,否则preload="metadata"没意义 - HTML 中补
<link rel="preload" href="video.mp4" as="video">,注意as="video"不能省,否则 Chrome 当普通资源处理 - 移动端别批量设
preload,用IntersectionObserver监听视口可见后再调video.load()
怎么用 MSE 实现弱网下的码率无缝切换
原生 <video> 标签不支持运行时换源,必须用 MediaSource 手动喂数据。关键不是“换 URL”,而是控制分片加载节奏和缓冲水位。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 分片用 fMP4,每段 4 秒,各码率版本关键帧对齐(用
ffmpeg -g 120统一 GOP) - 监听
video.buffered.end(0) < video.currentTime + 3且video.readyState < 4→ 立即降码率;反之,缓冲 > 12 秒可试探升码率 - 切换前先
sourceBuffer.abort()清空旧数据,再appendBuffer()新分片,避免解码器卡死 - 引入 8 秒滞留窗口:
Date.now() - lastSwitchTime > 8000才允许下次切换,防抖
用户手动选清晰度时,怎么避免格式无效导致白屏
用户点“1080p”按钮,结果加载的是 WebM/AV1,而当前设备不支持——白屏+无报错是最差体验。不能只靠 canPlayType() 静态判断,得动态验证。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 每个清晰度选项绑定真实 source 地址和格式标识,如
{ label: "1080p (MP4/H.264)", src: "1080_h264.mp4", type: "video/mp4" } - 点击后先
const canPlay = video.canPlayType(item.type + '; codecs="..."),返回"probably"才执行video.src = item.src - 若
canPlay为空,直接禁用该选项并提示“当前设备不支持此格式”,不触发加载 - 所有 source 切换都走
video.load()+canplay事件回调,失败则回退到上一个可用项,不依赖error事件
弱网降级最易被忽略的点:不是策略没写全,而是把“自动切换”当成黑盒,没暴露可控入口。用户感知到卡顿时,第一反应不是等,而是想“我能不能做点什么”。所以手动清晰度开关、复制地址、离线下载这三个按钮,必须常驻,且状态实时同步——哪怕自动逻辑跑得再稳,也要让用户觉得“我在掌控”。



















