弱网下自动降码率需提前探测、分层响应与状态保持:结合video.error.code、networkState及stalled/waiting行为判断问题类型,按兼容性排序<source>,预加载低清源,MSE切换时abort旧buffer并append新分片,同时提供手动回退选项。

弱网下自动降码率不是“等卡住了再换”,而是靠提前探测、分层响应和状态保持来实现平滑过渡。核心在于区分“真不支持”和“暂时加载慢”,再按需切换源或分片。
先判断是网络问题还是格式问题
只看 video.error.code 容易误判。必须结合 networkState 和行为信号:
-
code === 2(NETWORK_ERR)且 networkState === 0:大概率是连不通或超时,优先用
fetch(url, { method: 'HEAD', signal: AbortSignal.timeout(1500) })快速验证 URL 是否可达 -
code === 4(SRC_NOT_SUPPORTED):说明浏览器根本不认识这个编码或容器,直接跳过该
<source>,试下一个 - iOS Safari 常不抛 error,要监听
stalled或连续waiting超 2s,视为弱网信号
多层降级策略要写进 HTML 结构
别等 JS 运行完才开始加载,<video> 的 <source> 顺序本身就是第一道防线:
- 按兼容性+带宽友好度排列:比如
av1.webm(高效但兼容差)→vp9.webm(中等)→h264.mp4(通用) - 服务端 MP4 必须加
faststart(ffmpeg -c copy -movflags +faststart),否则preload="metadata"在弱网下反而更慢 - 配合
<link rel="preload" href="low.mp4" as="video">提前拉取低清备用源,避免临切时白屏
运行时动态切换要保状态、控节奏
原生 <video> 换 src 会中断播放,真正平滑切换得靠 MSE 或精细控制:
立即学习“前端免费学习笔记(深入)”;
- 手动切换前,记下
currentTime和paused状态;替换后调load(),等canplay再恢复 - 用
navigator.connection.effectiveType(如'2g'或'slow-2g')主动触发降级,提示“已切换至流畅模式” - 如果用 MSE,监听
buffered.end(0) < currentTime + 3且readyState < 4,立即 abort 当前 sourceBuffer 并加载低码率分片
给用户留出口,也留信任感
所有自动降级后,都该提供可操作的回退路径:
- 显示“手动选择清晰度”按钮,列出当前可用源(标注格式,如“MP4(H.264)”)
- 每个选项旁加“复制地址”,方便用户外链验证或调试
- 避免隐藏式降级——用户感知不到变化时,容易误以为是 bug



















