HLS.js 播放时为什么总在切换清晰度后卡住?
我用 HLS.js 做了一个支持多码率切换的播放器,但每次手动切换清晰度(比如从 720p 切到 1080p)之后,视频就会卡住几秒甚至直接黑屏。控制台没报错,network 里看到新的 m3u8 和 ts 文件其实已经加载了,就是画面不动。
我试过调用 hls.loadLevel 后再手动触发 video.play(),但还是不行。是不是我哪里配置漏了?下面是我初始化 HLS 的代码:
const hls = new Hls({
enableWorker: true,
maxBufferLength: 30,
liveSyncDurationCount: 3
});
hls.loadSource('https://example.com/master.m3u8');
hls.attachMedia(videoElement);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
// 切换到最高清晰度
hls.currentLevel = hls.levels.length - 1;
});
先说解决方案,把你初始化 HLS 的代码改成这样:
关键点说下:
第一,你直接在
MANIFEST_PARSED里设currentLevel,这时候缓冲区还没建立好,容易出问题。建议等视频开始播放后再切换。第二,切换清晰度时最好先
stopLoad()再startLoad(),不然旧的 ts 分片请求可能还在队列里,新的请求排队等着,就卡住了。第三,HLS.js 默认有 ABR 自动码率切换,你手动切完它可能又给你切回去。如果你要做纯手动切换,需要监听
FRAG_LOAD_EMERGENCY_ABORTED这类事件,或者干脆用hls.autoLevelEnabled = false把自动切换关掉。另外你说的黑屏问题,大概率是缓冲区 gap 造成的,可以加个监听:
最后吐槽一句,HLS.js 这套 API 设计得确实有点反人类,
currentLevel、nextLevel、loadLevel这几个属性名字看着都差不多,文档还写得跟天书一样,踩坑太正常了。