HLS.js动态切换自适应码率后视频卡住怎么办?

梦幻 Dev 阅读 38

在React项目里用HLS.js实现视频播放,想让前端动态切换不同分辨率的自适应码率。我通过hls.levels获取到可用码率列表,然后在点击事件里调用hls.swapAudioCodec或者hls.startLevel,但切换后视频卡住不动,控制台也没报错,这是为什么呢?

代码是这样写的:


import React, { useRef, useEffect } from 'react';
import Hls from 'hls.js';

const VideoPlayer = ({ src }) => {
  const videoRef = useRef();
  const hlsRef = useRef(null);

  useEffect(() => {
    if (Hls.isSupported()) {
      hlsRef.current = new Hls();
      hlsRef.current.loadSource(src);
      hlsRef.current.attachMedia(videoRef.current);
      hlsRef.current.on(Hls.Events.LEVEL_SWITCHED, () => {
        console.log('切换成功?');
      });
    }
  }, [src]);

  const switchQuality = (level) => {
    hlsRef.current.swapAudioCodec(level); // 这里是不是用错了方法?
    // 也试过hlsRef.current.startLevel = level; 但没效果
  };

  return (
    <div>
      <video ref={videoRef} />
      <button onClick={() => switchQuality(1)}>360p</button>
    </div>
  );
};

export default VideoPlayer;

按文档应该用hls.levels[level].id来指定,但参数类型一直不对,是不是版本差异导致的?或者需要先暂停再切换?求指点具体实现方法…

我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
Prog.静依
我也踩过这个坑,先说结论:**你用错了方法,而且切换时机不对**。

swapAudioCodec是干啥的你再看下文档——这玩意是切换音频编码用的,不是视频分辨率切换。你点了360p按钮,结果在折腾音频,当然没反应。血泪教训:命名不对就得警觉,别硬套参数。

正确的做法是设置hlsRef.current.level = level;,不是startLevel也不是swapAudioCodec。至于为啥没反应,是因为你没等加载完成就切了。HLS是流式加载,要等它准备好了再操作。

你可以这么改:

useEffect(() => {
if (Hls.isSupported()) {
const hls = new Hls();
hlsRef.current = hls;
hls.loadSource(src);
hls.attachMedia(videoRef.current);

hls.on(Hls.Events.MANIFEST_PARSED, () => {
console.log('资源准备好了');
});

hls.on(Hls.Events.LEVEL_SWITCHED, (event, data) => {
console.log('当前切到的level index:', data.level);
});
}
}, [src]);


然后切换的时候加个判断:
const switchQuality = (level) => {
if (hlsRef.current && hlsRef.current.levels.length > level) {
hlsRef.current.level = level;
}
};


还有个小建议:不要直接暴露level索引给用户点击,比如你写个按钮就点level=1,最好封装一层映射关系,避免哪天level顺序变了你页面全错。

总结下:
- level才是控制视频码率的属性,别乱用swapAudioCodec
- 切换前等MANIFEST_PARSED事件,不然level数组可能为空
- 控制台没报错不代表没问题,建议加监听ERROR事件看有没有静默失败

我当初也是点了半天没反应,后来加了监听才发现level压根不存在,坑死了。
点赞 6
2026-02-03 20:11