根据hls.js 完成直播流HLS(M3U8 格式)播放

useLiveStream.js

       

useLiveStream.js

  • 该文件包含了获取直播流 URL、初始化视频播放器、销毁播放器等相关逻辑。
  • createVideoElement:该函数创建一个新的视频元素并设置相关属性。
  • initHls:通过 HLS.js 初始化直播流,绑定到 video 元素,处理直播流解析及播放。
  • destroyHls:销毁播放器实例,清理相关资源。
import { ref, nextTick } from 'vue';
import Hls from 'hls.js';

// 用于存储直播流信息
const liveHlsUrl = ref(null);
const isLoading = ref(false);
const isSuccess = ref(false);
let hls = null;
let videoElement = null;

// 创建视频元素
const createVideoElement = () => {
  const video = document.createElement('video');
  video.style.width = '100%';
  video.style.aspectRatio = '16 / 9';
  video.style.position = 'absolute';
  video.style.top = '50%';
  video.style.transform = 'translate(0, -50%)';
  video.style.zIndex = '2';
  video.style.objectFit = 'fill';
  video.autoplay = true;
  video.muted = true;
  video.loop = true;
  video.setAttribute('x5-video-player-type', 'h5');
  video.setAttribute('x5-video-player-fullscreen', 'true');
  video.setAttribute('playsinline', '');
  video.setAttribute('webkit-playsinline', '');
  video.setAttribute('x5-playsinline', 'true');
  return video;
};

// 初始化直播流播放器
const initHls = async (videoContainer, url) => {
  await nextTick();

  if (!videoContainer || !url) return;
  
  isLoading.value = true;

  // 移除所有现有的视频元素,防止重复创建
  const existingVideos = videoContainer.querySelectorAll('video');
  existingVideos.forEach((video) => video.remove());

  // 创建新的 video 元素并插入
  videoElement = createVideoElement();
  videoContainer.insertBefore(videoElement, videoContainer.firstChild);

  if (Hls.isSupported()) {
    hls = new Hls({
      debug: true,
      maxBufferLength: 30,
      maxMaxBufferLength: 60,
      maxBufferSize: 60 * 1000 * 1000,
      maxBufferHole: 0.5,
      lowLatencyMode: true,
    });

    hls.attachMedia(videoElement);
    
    // 当视频元素绑定成功时,加载视频源
    hls.on(Hls.Events.MEDIA_ATTACHED, () => {
      console.log('视频元素已绑定');
      hls.loadSource(url);
    });

    // 直播流解析成功
    hls.on(Hls.Events.MANIFEST_PARSED, () => {
      console.log('直播流解析成功');
      isSuccess.value = true;
      isLoading.value = false;
      videoElement.play().catch((err) => {
        console.error('自动播放失败:', err);
      });
    });

    // 处理错误事件
    hls.on(Hls.Events.ERROR, (event, data) => {
      console.error('直播流解析失败:', data);
      isSuccess.value = false;
      isLoading.value = false;
    });
  } else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
    // 直接使用 `videoElement.src` 进行播放(适用于不支持 HLS.js 的浏览器)
    videoElement.src = url;
  }
};

// 销毁 HLS 播放器
const destroyHls = () => {
  if (hls) {
    hls.destroy();
    hls = null;
  }
  if (videoElement) {
    videoElement = null;
  }
};

export {
  liveHlsUrl,
  isLoading,
  isSuccess,
  initHls,
  destroyHls,
};

主组件

  • 在主组件中, 获取直播流的 URL后,调用 initHls 初始化播放器。
  • 在组件卸载时调用 destroyHls 清理资源。        

 

 <div ref="videoContainer" class="video-container">
      <view class="cover-img">
        <image :src="currentLive?.coverImg" style="width:100%;height:100%" mode="aspectFit"></image>
      </view>

      <view class="video-loading">
        <u-loading-icon textSize="24px" v-if="isLoading" />
      </view>
    </div>


import { initHls, destroyHls, liveHlsUrl, isLoading, isSuccess } from './useLiveStream.js';

// 销毁播放器
onUnmounted(() => {
  destroyHls();
});
 initHls(videoContainer.value, liveHlsUrl.value); // 初始化播放器

使用js的好处在于 类似一个类 不需要再在js外创建很多变量了 也可以在不同的组件完成不同的展示效果

<think>好的,我现在需要解决用户关于xgplayer中hls.js组件销毁的问题。首先,我得回忆一下xgplayer的基本结构以及它如何集成hls.js。xgplayer是一个基于HTML5的视频播放器,支持多种流媒体协议,包括HLS,而hls.js是一个用于在浏览器中播放HLS流的JavaScript库。在xgplayer中,hls.js应该被用作一个插件或组件来处理HLS流的解析和播放。 用户的问题是询问如何销毁hls.js下的组件,这可能涉及到在不需要播放器时正确释放资源,避免内存泄漏或其他问题。我需要先了解xgplayer和hls.js的生命周期管理。通常,销毁组件需要调用特定的方法或遵循一定的步骤来确保所有事件监听器、定时器、媒体元素等都被正确清理。 首先,我应该查阅xgplayer的官方文档,看看是否有关于销毁hls.js组件的说明。如果文档中提到,可以直接参考。如果没有,可能需要查看源码或社区讨论。例如,xgplayer可能提供了一个destroy方法,用于销毁整个播放器实例,这时候hls.js组件也应该被自动销毁。但用户可能希望单独销毁hls.js组件,或者在特定情况下手动管理。 接下来,考虑hls.js本身的销毁方法。hls.js库有一个destroy()方法,用于停止加载、断开媒体元素、移除事件监听器等。因此,在xgplayer中,当使用hls.js作为播放引擎时,可能需要先获取hls.js的实例,然后调用其destroy方法。 但如何获取这个实例呢?在xgplayer中,可能通过player实例的某个属性或方法获取hls.js的实例。例如,player.hls 或者 player.tech_.hls 这样的属性。这需要查看xgplayer的源码或文档确认。如果无法直接获取,可能需要通过事件监听或者在初始化时保存hls实例的引用。 另外,需要考虑销毁的顺序。如果在销毁hls.js组件之前,先销毁了播放器的DOM元素或相关的video元素,可能会导致错误。正确的步骤应该是先停止播放,调用hls.js的destroy方法,然后再处理播放器的销毁。 可能的步骤总结如下: 1. 停止当前播放。 2. 调用hls.js实例的destroy方法。 3. 销毁xgplayer实例,确保移除所有事件监听器和DOM元素。 还需要考虑异常情况,比如hls.js实例可能不存在(如果播放器尚未初始化或已经销毁过),这时候需要做判断以避免错误。 此外,是否有xgplayer提供的API可以直接处理这个问题?例如,player.destroy()是否会自动销毁hls.js组件?如果是的话,用户可能不需要手动销毁,但有时候手动销毁可以更细粒度地控制资源释放。 最后,测试代码示例可能会有帮助。用户可能需要看到如何在实际代码中实现销毁过程,包括获取hls实例、调用destroy、处理播放器销毁等步骤。同时需要提醒注意事项,比如确保在组件卸载或页面关闭时执行销毁,避免内存泄漏。</think>在xgPlayer中销毁hls.js组件的完整流程如下: 1. **获取hls实例** ```javascript const hls = player.hls; // 或 player.tech_.hls根据xgPlayer版本不同) ``` 2. **销毁hls.js组件** ```javascript if (hls) { hls.destroy(); // 调用hls.js原生销毁方法 player.hls = null; // 解除引用 } ``` 3. **销毁播放器实例** ```javascript player.destroy(); // 触发xgPlayer内置清理流程 ``` **关键步骤说明:** 1. **停止播放流媒体** - 调用`player.pause()`停止播放 - 执行`player.src('')`清空视频源 2. **断开媒体元素绑定** ```javascript const mediaElement = player.tech_.el(); hls.detachMedia(); // 显式解绑DOM元素 ``` 3. **清除事件监听** - hls.js内部会自动移除监听器 - 手动移除自定义事件监听: ```javascript hls.off(Hls.Events.ERROR, customErrorHandler); ``` **注意事项:** 1. **销毁顺序** - 先销毁hls.js实例再销毁player - 避免先移除DOM元素导致hls报错 2. **内存泄漏预防** - 检查定时器:`hls.timer`等属性需置null - 释放buffer内存:`hls.stopLoad()`终止分段加载 3. **异常处理** ```javascript try { hls.destroy(); } catch (e) { console.warn('HLS销毁异常', e); } finally { player.hls = null; } ``` **完整示例代码:** ```javascript function destroyPlayer() { if (!player) return; // 停止播放 player.pause(); player.src(''); // 销毁hls组件 if (player.hls) { try { player.hls.destroy(); player.hls.detachMedia(); } catch (e) { console.error(e); } player.hls = null; } // 销毁播放器 player.destroy(); player = null; } ``` **典型应用场景:** 1. 单页应用路由切换时 2. 视频源切换(HLS -> MP4) 3. 播放器容器DOM被移除前 4. 异常恢复时的重新初始化 建议在组件卸载生命周期(如React的useEffect return)中执行销毁操作,确保资源完全释放。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值