You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

复用video元素时如何清除videojs-contrib-eme遗留的视频状态?

解决方案:无副作用重置Video元素状态以兼容DRM与360视频切换

核心思路

针对DRM播放后残留的mediaKeys状态影响Three.js纹理渲染的问题,我们需要分场景精准清理状态:仅在切换到360视频时临时清除DRM相关状态,同时确保后续DRM视频能重新初始化mediaKeys,避免副作用。


具体实现步骤

1. 封装统一的视频切换函数

将分散的视频源设置逻辑整合,在切换前根据目标视频类型做针对性清理:

// 封装视频切换逻辑,确保状态清理与插件生命周期同步
const switchVideoSource = async (source, videoType) => {
  const player = playerRef.current;
  if (!player) return;

  // 先暂停播放器,避免状态混乱
  player.pause();

  if (videoType === '360') {
    // 清理DRM状态:仅当当前存在mediaKeys时执行
    const videoEl = player.el().querySelector('video');
    if (videoEl.mediaKeys) {
      // 保存当前eme插件实例,清除后重新初始化
      const emeInstance = player.eme();
      await videoEl.setMediaKeys(null);
      // 重新初始化eme插件,保证后续DRM视频能正常加载
      emeInstance.dispose();
      player.eme();
    }

    // 初始化VR插件(若未激活)
    if (!player.vrPlugin) {
      player.vrPlugin();
    }
  } else {
    // 非360视频:销毁VR插件(若存在)
    if (player.vrPlugin) {
      player.vrPlugin().dispose();
    }

    // DRM视频:确保eme插件已激活
    if (source.keySystems && !player.eme) {
      player.eme();
    }
  }

  // 设置视频源并加载
  const srcConfig = source.keySystems 
    ? { src: source.url, keySystems: source.keySystems }
    : source.url;
  
  player.src(srcConfig);
  player.load();
};

2. 优化VR插件的视频纹理初始化

在VR插件中销毁旧纹理并重新创建,确保使用干净的视频元素状态:

// VR插件内的_initializeVideoTexture方法修改
_initializeVideoTexture() {
  const videoEl = this.player.el().querySelector('video');
  
  // 销毁旧纹理,避免残留状态
  if (this.videoTexture) {
    this.videoTexture.dispose();
  }

  // 创建新的视频纹理,强制更新状态
  this.videoTexture = new THREE.VideoTexture(videoEl);
  this.videoTexture.needsUpdate = true;

  // 监听视频元数据加载事件,确保纹理正确更新
  videoEl.addEventListener('loadedmetadata', () => {
    this.videoTexture.needsUpdate = true;
  });
}

3. 组件卸载时的完整清理

确保播放器和插件资源完全释放,避免内存泄漏:

useEffect(() => {
  const player = playerRef.current;

  return () => {
    if (player) {
      // 销毁所有插件实例
      if (player.vrPlugin) player.vrPlugin().dispose();
      if (player.eme) player.eme().dispose();
      // 销毁video.js播放器
      player.dispose();
      playerRef.current = null;
    }
  };
}, []);

为什么这个方案有效

  • 精准清理:仅在切换到360视频时清除mediaKeys,避免不必要的状态修改。
  • 无副作用:清除mediaKeys后立即重新初始化eme插件,确保后续DRM视频能正常重新获取密钥。
  • 状态同步:封装切换逻辑,确保插件生命周期与视频源切换同步,避免异步操作导致的状态不一致。
  • 纹理重置:VR插件中销毁旧纹理并重新创建,彻底避免DRM残留状态对Three.js渲染的影响。

内容的提问来源于stack exchange,提问作者Ion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:05:25