libpag icon indicating copy to clipboard operation
libpag copied to clipboard

Web 内存泄露-求解:Electron web 使用 setComposition 去切换 PAG,每次播放完不会释放内存,导致内存逐渐变大,内存泄露,然后页面白屏,应用就不能使用了

Open Wn-1231 opened this issue 11 months ago • 3 comments

【版本信息】

libpag SDK 版本:4.2.84 ffavc SDK:1.0.2

chrome版本:108.0.5359.215 electron版本: 22.3.27

【平台信息】

Web 浏览器

【预期的表现】

播放完动画,能正常释放内存

【实际的情况】

内存泄露严重,多次频繁调用 setComposition 会内存一直增加,导致泄露,页面白屏,无法使用

【Demo及附件】

  • 应用刚打开内存 200MB 渲染进程占用内存

  • 疯狂播放 PAG 后到 800MB => 1000MB ,超出 1G 后内存泄露白屏

  • 链接:https://pica.zhimg.com/v2-51541d7799dd1bbde755bbe845ca07df.png 渲染进程占用内存

  • 视频链接:https://zhstatic.zhihu.com/vip-fe/live/06cdabf5b00c5329e882f568b00732a2.mov

方案一 代码,也是上图使用代码

  const initialize = async (buffer: ArrayBuffer) => {
      console.log('initialize');
      try {
        if (timerRef.current) {
          clearTimeout(timerRef.current);
          timerRef.current = null;
        }

        // 重置状态
        isAnimationEndedRef.current = false;

        const { pag, ffavc } = await PAGInitializer.getInstance().getRuntime();

        if (isRegisterSoftwareDecoderFactory) {
          pag.registerSoftwareDecoderFactory(ffavc);
        }

        // 加载新的 PAGFile
        const newPagFile = await pag.PAGFile.load(buffer);
        pagFileRef.current = newPagFile;

        const canvas = canvasRef.current!;

        // 如果 pagView 不存在,则创建新的实例
        if (!pagViewRef.current) {
          console.log('创建新的实例');
          canvas.width = newPagFile.width();
          canvas.height = newPagFile.height();

          const pagViewInstance = await pag.PAGView.init(newPagFile, canvas, {
            firstFrame: false,
            useCanvas2D: true,
            useScale: false,
          });

          if (pagViewInstance) {
            pagViewRef.current = pagViewInstance;
            pagViewRef.current.removeListener(
              'onAnimationEnd',
              onAnimationEndHandler,
            );
            pagViewRef.current.addListener(
              'onAnimationEnd',
              onAnimationEndHandler,
            );
          }
          pagViewRef.current?.setRepeatCount(loop ? 0 : 1);
        } else {
          console.log('切换动画');
          // 如果 pagView 已存在,使用 setComposition 切换动画
          pagViewRef.current.pause();
          await pagViewRef.current.stop();
          await pagViewRef.current.setComposition(newPagFile);
          pagViewRef.current?.setRepeatCount(loop ? 0 : 1);
          pagViewRef.current?.setProgress(0);
        }

        if (autoplay) {
          await pagViewRef.current?.play();
        }

        initialized?.();

        // 设置超时计时器
        timerRef.current = setTimeout(() => {
          if (!isAnimationEndedRef.current) {
            console.log('Animation ended by timeout');
            onAnimationEndHandler();
          }
        }, timeout);
      } catch (error: any) {
        logger.error('动画资源加载失败', error);
      }
    };

Wn-1231 avatar Feb 27 '25 13:02 Wn-1231

该问题能否上传一个可复现问题的demo,我用pag-web中的demo多次切换pag文件没有出现内存持续增长的问题 https://github.com/libpag/pag-web/blob/main/pages/set-composition.html

jinwuwu001 avatar May 27 '25 08:05 jinwuwu001

该问题能否上传一个可复现问题的演示,我用pag-web中的演示多次切换pag文件没有出现内存持续增长的问题 https://github.com/libpag/pag-web/blob/main/pages/set-composition.html

我在 Electron 也用的是 set-composition. 方式切换的 pag ,确实存在泄露,demo 我们看下

Wn-1231 avatar May 28 '25 09:05 Wn-1231

似乎是 Blob URL 泄漏

cbbfcd avatar Nov 19 '25 11:11 cbbfcd