收藏
回答

createWorker开启useExperimentalWorker在iOS真机卡顿

框架类型 问题类型 API/组件名称 终端类型 微信版本 基础库版本
小程序 Bug createWorker 微信iOS客户端 8.0.44 3.2.1

API名称: wx.createWorker 开启useExperimentalWorker

手机信息: iphone13pro iOS 17.1.1

微信版本:8.0.44

基础库: 3.2.1

现象:在使用xr-frame时,获取了相机的yBuffer,uvBuffer后,传递到worker进行压缩,压缩完成后返回主线程发送请求。 在android真机上正常,在iOS真机上非常卡顿。将useExperimentalWorker关闭恢复正常。

// index
function createNewWorker() {
  const worker = wx.createWorker('workers/index.js', {
    useExperimentalWorker: true
  })
  return worker;
}

this.worker = createNewWorker();

// 监听worker被系统回收事件
this.worker.onProcessKilled(() => {
  // 重新创建一个worker
  this.worker = createNewWorker()
})

const ArRawData = this.arSystem.getARRawData();
const uvBuffer = ArRawData.uvBuffer;
const yBuffer = ArRawData.yBuffer;
const width = ArRawData.width;
const height = ArRawData.height;
const scaleFactor = wx.getSystemInfoSync().pixelRatio;

this.worker.postMessage({
  type: 'yuv',
  data: {
    width,
    height,
    scaleFactor,
    yBuffer,
    uvBuffer,
  }
})

// worker
import {
  encode
} from 'base64-arraybuffer/index';

function downscaleYUV(yData, uvData, originalWidth, originalHeight, scaleFactor) {
  const newWidth = Math.floor(originalWidth / scaleFactor);
  const newHeight = Math.floor(originalHeight / scaleFactor);

  const newYData = new Uint8Array(newWidth * newHeight);
  const newUVData = new Uint8Array(newWidth / 2 * newHeight / 2 * 2);

  for (let y = 0; y < newHeight; y++) {
    for (let x = 0; x < newWidth; x++) {
      const originalX = x * scaleFactor;
      const originalY = y * scaleFactor;

      const newYIndex = y * newWidth + x;
      const originalYIndex = originalY * originalWidth + originalX;

      newYData[newYIndex] = yData[originalYIndex];

      // For UV channel
      const originalUVIndex = Math.floor(originalY / 2) * Math.floor(originalWidth / 2) + Math.floor(originalX / 2);
      const newUVIndex = Math.floor(y / 2) * Math.floor(newWidth / 2) + Math.floor(x / 2);

      newUVData[newUVIndex * 2] = uvData[originalUVIndex * 2];
      newUVData[newUVIndex * 2 + 1] = uvData[originalUVIndex * 2 + 1];
    }
  }

  return {
    newYData,
    newUVData,
    newWidth,
    newHeight
  };
}

worker.onMessage(function (res) {
  switch(res.type) {
    case 'yuv': {
      const { width, height, yBuffer, uvBuffer, scaleFactor } = res.data;
      const { newYData, newUVData, newWidth, newHeight } = downscaleYUV(
        new Uint8Array(yBuffer),
        new Uint8Array(uvBuffer),
        width,
        height,
        scaleFactor
      );

      worker.postMessage({
        type: 'yuv_result',
        data: {
          scaleFactor,
          yBuffer: encode(newYData),
          uvBuffer: encode(newUVData),
        }
      })
    }
  }
})


回答关注问题邀请回答
收藏

1 个回答

  • 杜瑞
    杜瑞
    03-13

    你好,这个问题有解决吗,我这边也是ios开启了试验worker,worker内部做了视频解码,但是解码后的YUV通过postMessage给主线程渲染就延迟特别大,一帧视频YUV post需要几秒钟

    03-13
    有用
    回复 2
    • 文辉
      文辉
      04-21
      有方案不<br />postMessage中传arrayBuffer 非常慢,有大数据的需求很难整<br /><br /><br />1. 小游戏提供了一个现在提供 wx.createSharedArrayBuffer 处理,小程序真机ios用不了,不能获取达到 sharedArrayBuffer<br />2. Transferable Object 没有效果<br />3. WebAssembly.Memory 也不行, worker.postMessage 后 只是复制了一个空对象
      04-21
      回复
    • 文辉
      文辉
      04-21
      又测试了 wx.createSharedArrayBuffer 在 未开启 useExperimentalWorker 时 可以使用,但是不开启useExperimentalWorker 时,jsCore 没有开启 JIT wasm运行效率极其低
      04-21
      回复
登录 后发表内容