UNPKG

trtc-sdk-v5

Version:
1 lines 64.8 kB
var __defProp=Object.defineProperty,__defProps=Object.defineProperties,__getOwnPropDescs=Object.getOwnPropertyDescriptors,__getOwnPropSymbols=Object.getOwnPropertySymbols,__hasOwnProp=Object.prototype.hasOwnProperty,__propIsEnum=Object.prototype.propertyIsEnumerable,__defNormalProp=(e,r,t)=>r in e?__defProp(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t,__spreadValues=(e,r)=>{for(var t in r||(r={}))__hasOwnProp.call(r,t)&&__defNormalProp(e,t,r[t]);if(__getOwnPropSymbols)for(var t of __getOwnPropSymbols(r))__propIsEnum.call(r,t)&&__defNormalProp(e,t,r[t]);return e},__spreadProps=(e,r)=>__defProps(e,__getOwnPropDescs(r)),__publicField=(e,r,t)=>__defNormalProp(e,"symbol"!=typeof r?r+"":r,t),layoutProperty={x:{required:!0,type:"number"},y:{required:!0,type:"number"},width:{required:!0,type:"number",notLessThanZero:!0,min:1,max:3840},height:{required:!0,type:"number",notLessThanZero:!0,min:1,max:3840},zIndex:{required:!0,type:"number"},fillMode:{required:!1,type:"string"},mirror:{required:!1,type:"boolean"},rotation:{required:!1,type:"number"},hidden:{required:!1,type:"boolean"}},canvasValidateRule=(e,r=!1)=>({type:"object",required:r,properties:{canvasColor:{required:!1,type:["string",CanvasGradient,CanvasPattern]},width:{required:!0,type:"number",notLessThanZero:!0,min:1,max:3840},height:{required:!0,type:"number",notLessThanZero:!0,min:1,max:3840},frameRate:{required:!1,type:"number",notLessThanZero:!0,min:1,max:60}},validate(r,t,a){const{RtcError:n,ErrorCode:s,ErrorCodeDictionary:i}=e.errorModule;if(!r)return;const{width:o,height:c}=r;if(o&&c&&o*c>8294400)throw new n({code:s.INVALID_PARAMETER,message:"The mix resolution cannot be set higher than 3840 * 2160."})}}),viewValidateRule=e=>({required:!1,type:["string",HTMLElement,null],validate(r,t,a){const{RtcError:n,ErrorCode:s,ErrorCodeDictionary:i}=e.errorModule;if(e.utils.isString(r)){if(!document.getElementById(r))throw new n({code:s.INVALID_PARAMETER,extraCode:i.INVALID_ELEMENT_ID,fnName:a,messageParams:{key:t}})}}}),layoutValidateRule=(e,r=!0)=>({type:"object",required:r,properties:__spreadValues({},layoutProperty),validate(r,t,a){const{RtcError:n,ErrorCode:s,ErrorCodeDictionary:i}=e.errorModule;if(r){if(r.fillMode&&!["contain","cover","fill"].includes(r.fillMode))throw new n({code:s.INVALID_PARAMETER,extraCode:i.INVALID_PARAMETER_TYPE,message:"The fillMode parameter must be 'contain', 'cover' or 'fill'",fnName:a});if(r.rotation&&![0,90,180,270].includes(r.rotation))throw new n({code:s.INVALID_PARAMETER,extraCode:i.INVALID_PARAMETER_TYPE,message:"The rotation parameter must be 0, 90, 180 or 270",fnName:a})}}}),cameraValidateRule=e=>({type:"array",required:!1,arrayItem:{type:"object",properties:{id:{required:!0,type:"string"},cameraId:{required:!1,type:"string"},videoTrack:{required:!1,instanceof:MediaStreamTrack},profile:{required:!1,type:["string","object"],properties:{width:{type:"number"},height:{type:"number"},frameRate:{type:"number"},bitrate:{type:"number"}}},layout:__spreadValues({},layoutValidateRule(e))}}}),screenValidateRule=e=>({type:"array",required:!1,arrayItem:{type:"object",properties:{id:{required:!0,type:"string"},profile:{required:!1,type:["string","object"],properties:{width:{type:"number"},height:{type:"number"},frameRate:{type:"number"},bitrate:{type:"number"}}},captureElement:{required:!1,type:HTMLElement},preferDisplaySurface:{required:!1,type:"string"},layout:__spreadValues({},layoutValidateRule(e))},validate(r,t,a){const{RtcError:n,ErrorCode:s,ErrorCodeDictionary:i}=e.errorModule;if(!e.rtcDectection.isScreenCaptureApiAvailable())throw new n({code:s.ENV_NOT_SUPPORTED,fnName:a,extraCode:i.NOT_SUPPORTED_SCREEN_SHARE})}}}),textValidateRule=e=>({type:"array",required:!1,arrayItem:{type:"object",properties:{id:{required:!0,type:"string"},content:{required:!0,type:"string"},font:{required:!1,type:"string"},color:{required:!1,type:["string",CanvasGradient,CanvasPattern]},layout:__spreadValues({},layoutValidateRule(e))}}}),imageValidateRule=e=>({type:"array",required:!1,arrayItem:{type:"object",properties:{id:{required:!0,type:"string"},url:{required:!0,type:"string"},layout:__spreadValues({},layoutValidateRule(e))}}}),videoValidateRule=e=>({type:"array",required:!1,arrayItem:{type:"object",properties:{id:{required:!0,type:"string"},url:{required:!0,type:"string"},layout:__spreadValues({},layoutValidateRule(e))}}});function startValidateRule(e){return{name:"VideoMixerOptions",type:"object",required:!0,allowEmpty:!1,properties:{view:__spreadValues({},viewValidateRule(e)),canvasInfo:__spreadValues({},canvasValidateRule(e,!0)),camera:__spreadValues({},cameraValidateRule(e)),screen:__spreadValues({},screenValidateRule(e)),text:__spreadValues({},textValidateRule(e)),image:__spreadValues({},imageValidateRule(e)),video:__spreadValues({},videoValidateRule(e))},validate(r,t,a,n){const{RtcError:s,ErrorCode:i,ErrorCodeDictionary:o}=e.errorModule;if(e.environment.isMobile())throw new s({code:i.ENV_NOT_SUPPORTED,message:"VideoMixer is not supported on mobile devices currently"});const{onScreenShareStop:c}=r;if(c&&!e.utils.isFunction(c))throw new s({code:i.INVALID_PARAMETER,extraCode:o.INVALID_PARAMETER_TYPE,fnName:a,messageParams:{key:"onScreenShareStop",value:typeof c,rule:{type:"Function"}}})}}}function updateValidateRule(e){return{name:"VideoMixerOptions",type:"object",required:!1,allowEmpty:!1,properties:{view:__spreadValues({},viewValidateRule(e)),canvasInfo:__spreadValues({},canvasValidateRule(e)),camera:__spreadValues({},cameraValidateRule(e)),screen:__spreadValues({},screenValidateRule(e)),text:__spreadValues({},textValidateRule(e)),image:__spreadValues({},imageValidateRule(e)),video:__spreadValues({},videoValidateRule(e))}}}function stopValidateRule(e){return{name:"StopVideoMixerOptions",required:!1}}var mix_render_worker_default='// video-effect/video-mixer/src/mix-render-worker.ts\nfunction isRotate90Or270(rotation) {\n  return rotation === 90 || rotation === 270;\n}\nfunction calculateCanvasDrawParams(srcW, srcH, dstW, dstH, fit, swapWH = false) {\n  if (swapWH) [dstW, dstH] = [dstH, dstW];\n  const res = { sWidth: srcW, sHeight: srcH, dWidth: dstW, dHeight: dstH, sx: 0, sy: 0, dx: 0, dy: 0 };\n  if (srcW === 0 || srcH === 0) return res;\n  switch (fit) {\n    case void 0:\n    case "fill":\n      break;\n    case "contain": {\n      const ratio = Math.min(dstW / srcW, dstH / srcH);\n      res.dWidth = srcW * ratio;\n      res.dHeight = srcH * ratio;\n      res.dx = (dstW - res.dWidth) / 2;\n      res.dy = (dstH - res.dHeight) / 2;\n      break;\n    }\n    case "cover": {\n      const ratio = Math.max(dstW / srcW, dstH / srcH);\n      const newSrcW = dstW / ratio;\n      const newSrcH = dstH / ratio;\n      res.sx = (srcW - newSrcW) / 2;\n      res.sy = (srcH - newSrcH) / 2;\n      res.sWidth = newSrcW;\n      res.sHeight = newSrcH;\n      break;\n    }\n  }\n  return res;\n}\nvar drawParamsCache = /* @__PURE__ */ new Map();\nfunction getCachedDrawParams(id, srcW, srcH, dstW, dstH, fillMode, swapWH = false) {\n  const key = `${srcW},${srcH},${dstW},${dstH},${fillMode},${swapWH}`;\n  const cached = drawParamsCache.get(id);\n  if (cached && cached.key === key) {\n    return cached.params;\n  }\n  const params = calculateCanvasDrawParams(srcW, srcH, dstW, dstH, fillMode, swapWH);\n  drawParamsCache.set(id, { key, params });\n  return params;\n}\nfunction workerLog(level, message) {\n  self.postMessage({ type: "log", level, message });\n}\nvar throttleLogTimestamps = /* @__PURE__ */ new Map();\nvar THROTTLE_LOG_MAX_ENTRIES = 50;\nvar THROTTLE_LOG_EXPIRY_MS = 3e4;\nfunction throttledLog(key, level, message, interval = 2e3) {\n  const now = performance.now();\n  if (throttleLogTimestamps.size > THROTTLE_LOG_MAX_ENTRIES) {\n    for (const [k, ts] of throttleLogTimestamps) {\n      if (now - ts > THROTTLE_LOG_EXPIRY_MS) {\n        throttleLogTimestamps.delete(k);\n      }\n    }\n    if (throttleLogTimestamps.size > THROTTLE_LOG_MAX_ENTRIES) {\n      workerLog("warn", `[Worker] throttledLog: map size (${throttleLogTimestamps.size}) still exceeds ${THROTTLE_LOG_MAX_ENTRIES} after eviction, possible dynamic key misuse`);\n    }\n  }\n  const last = throttleLogTimestamps.get(key) || 0;\n  if (now - last >= interval) {\n    throttleLogTimestamps.set(key, now);\n    workerLog(level, message);\n    return true;\n  }\n  return false;\n}\nvar canvas = null;\nvar ctx = null;\nvar layouts = [];\nvar latestFrames = /* @__PURE__ */ new Map();\nvar backgroundColor = "black";\nvar backgroundImage = null;\nvar fps = 15;\nvar renderIntervalId = null;\nvar renderLoopStarted = false;\nvar totalFrames = 0;\nvar dropFrames = 0;\nvar isRendering = false;\nvar dropByBackpressure = 0;\nvar dropByRendering = 0;\nvar dropByCanvasSize = 0;\nvar dropByWriteFail = 0;\nvar dropByOther = 0;\nvar isBackpressure = false;\nvar backpressureStartTime = 0;\nvar backpressureTotalDrops = 0;\nvar isCanvasSizeZero = false;\nvar consecutiveWriteFailures = 0;\nvar trackGeneratorWriter = null;\nvar trackGeneratorFailCount = 0;\nvar TRACK_GENERATOR_FAIL_THRESHOLD = 30;\nvar isFirstFrame = true;\nvar healthLogIntervalId = null;\nvar lastHealthLogTime = 0;\nvar lastHealthLogFrames = 0;\nvar streamControllers = /* @__PURE__ */ new Map();\nvar imageSources = /* @__PURE__ */ new Map();\nasync function handleAddImageSource(id, src, animated, mimeType) {\n  const existingState = imageSources.get(id);\n  if (existingState && existingState.src === src) {\n    workerLog("info", `[Worker] handleAddImageSource: skipping duplicate for ${id} (same src)`);\n    return;\n  }\n  handleRemoveImageSource(id);\n  const state = {\n    id,\n    src,\n    animated,\n    currentFrameIndex: 0,\n    frameCount: 0,\n    repetitionCount: 0,\n    loaded: false,\n    completed: false,\n    consecutiveErrors: 0,\n    loopCount: 0\n  };\n  const abortController = new AbortController();\n  state.abortController = abortController;\n  imageSources.set(id, state);\n  try {\n    const response = await fetch(src, { signal: abortController.signal });\n    if (animated && typeof self.ImageDecoder !== "undefined" && mimeType) {\n      const arrayBuffer = await response.arrayBuffer();\n      const ImageDecoderClass = self.ImageDecoder;\n      const decoder = new ImageDecoderClass({ data: arrayBuffer, type: mimeType });\n      state.decoder = decoder;\n      state.completed = true;\n      await decoder.tracks.ready;\n      const track = decoder.tracks.selectedTrack;\n      state.frameCount = track.frameCount;\n      state.repetitionCount = track.repetitionCount;\n      workerLog("info", `[Worker] ImageDecoder ready for ${id}: frameCount=${state.frameCount}, repetitionCount=${state.repetitionCount}, dataMode=arrayBuffer`);\n      decodeAndDisplayFrame(state);\n    } else {\n      const blob = await response.blob();\n      const bitmap = await createImageBitmap(blob);\n      const prev = latestFrames.get(id);\n      if (prev && "close" in prev.frame && typeof prev.frame.close === "function") {\n        try {\n          prev.frame.close();\n        } catch (e) {\n        }\n      }\n      latestFrames.set(id, { id, frame: bitmap, width: bitmap.width, height: bitmap.height });\n      self.postMessage({\n        type: "imageSourceLoaded",\n        id,\n        width: bitmap.width,\n        height: bitmap.height\n      });\n    }\n  } catch (err) {\n    if (err.name === "AbortError") return;\n    workerLog("warn", `[Worker] ImageSource load failed for ${id}: ${err.message || err}`);\n    self.postMessage({\n      type: "imageSourceError",\n      id,\n      message: err.message || String(err)\n    });\n  }\n}\nasync function decodeAndDisplayFrame(state) {\n  if (!state.decoder || !imageSources.has(state.id)) return;\n  try {\n    const result = await state.decoder.decode({ frameIndex: state.currentFrameIndex });\n    const videoFrame = result.image;\n    state.consecutiveErrors = 0;\n    const prev = latestFrames.get(state.id);\n    if (prev && "close" in prev.frame && typeof prev.frame.close === "function") {\n      try {\n        prev.frame.close();\n      } catch (e) {\n      }\n    }\n    latestFrames.set(state.id, {\n      id: state.id,\n      frame: videoFrame,\n      width: videoFrame.displayWidth,\n      height: videoFrame.displayHeight\n    });\n    if (!state.loaded) {\n      state.loaded = true;\n      self.postMessage({\n        type: "imageSourceLoaded",\n        id: state.id,\n        width: videoFrame.displayWidth,\n        height: videoFrame.displayHeight\n      });\n    }\n    const durationMs = (videoFrame.duration || 1e5) / 1e3;\n    state.currentFrameIndex++;\n    if (state.currentFrameIndex >= state.frameCount) {\n      if (state.repetitionCount === Infinity) {\n        state.currentFrameIndex = 0;\n        state.loopCount++;\n        if (state.loopCount === 1 || state.loopCount % 10 === 0) {\n        }\n      } else if (!state.completed) {\n        state.currentFrameIndex = 0;\n        state.loopCount++;\n      } else if (state.repetitionCount > 0) {\n        state.repetitionCount--;\n        state.currentFrameIndex = 0;\n        state.loopCount++;\n      } else {\n        return;\n      }\n    }\n    if (imageSources.has(state.id)) {\n      state.timerId = setTimeout(() => decodeAndDisplayFrame(state), durationMs);\n    }\n  } catch (err) {\n    if (err.name === "AbortError") return;\n    state.consecutiveErrors++;\n    const errMsg = err.message || String(err);\n    const errName = err.name || "Error";\n    workerLog("warn", `[Worker] ImageDecoder decode failed for ${state.id} frame ${state.currentFrameIndex}: [${errName}] ${errMsg} (consecutive=${state.consecutiveErrors})`);\n    if (state.consecutiveErrors >= 3) {\n      workerLog("error", `[Worker] ImageSource ${state.id} stopped: ${state.consecutiveErrors} consecutive decode errors`);\n      return;\n    }\n    if (!imageSources.has(state.id)) return;\n    if (errName === "RangeError") {\n      state.currentFrameIndex = 0;\n    } else {\n      state.currentFrameIndex++;\n      if (state.frameCount > 0 && state.currentFrameIndex >= state.frameCount) {\n        state.currentFrameIndex = 0;\n      }\n    }\n    state.timerId = setTimeout(() => decodeAndDisplayFrame(state), 100);\n  }\n}\nfunction handleRemoveImageSource(id) {\n  const state = imageSources.get(id);\n  if (!state) return;\n  if (state.abortController) {\n    try {\n      state.abortController.abort();\n    } catch (e) {\n    }\n  }\n  if (state.timerId) {\n    clearTimeout(state.timerId);\n    state.timerId = void 0;\n  }\n  if (state.decoder) {\n    try {\n      state.decoder.close();\n    } catch (e) {\n    }\n    state.decoder = void 0;\n  }\n  const frameData = latestFrames.get(id);\n  if (frameData) {\n    if ("close" in frameData.frame && typeof frameData.frame.close === "function") {\n      try {\n        frameData.frame.close();\n      } catch (e) {\n      }\n    }\n    latestFrames.delete(id);\n  }\n  imageSources.delete(id);\n}\nfunction handleUpdateImageSource(id, src, animated, mimeType) {\n  handleRemoveImageSource(id);\n  handleAddImageSource(id, src, animated, mimeType);\n}\nfunction drawFrame(layout, frame) {\n  if (!ctx || layout.hidden) return;\n  const swapWH = isRotate90Or270(layout.rotation);\n  const srcW = frame.width;\n  const srcH = frame.height;\n  const rotation = layout.rotation || 0;\n  if (swapWH) {\n    const mixSrcW = srcH;\n    const mixSrcH = srcW;\n    const opt = getCachedDrawParams(\n      layout.id,\n      mixSrcW,\n      mixSrcH,\n      layout.width,\n      layout.height,\n      layout.fillMode,\n      swapWH\n    );\n    const needsTransform = !!layout.mirror || rotation !== 0;\n    ctx.save();\n    ctx.translate(layout.x + opt.dx, layout.y + opt.dy);\n    ctx.scale(opt.dWidth / opt.sWidth, opt.dHeight / opt.sHeight);\n    ctx.translate(-opt.sx, -opt.sy);\n    if (rotation === 90) {\n      if (layout.mirror) {\n        ctx.scale(-1, 1);\n      } else {\n        ctx.translate(srcH, 0);\n      }\n      ctx.rotate(Math.PI / 2);\n      ctx.scale(srcW / srcH, srcH / srcW);\n    } else {\n      if (layout.mirror) {\n        ctx.scale(-1, 1);\n        ctx.translate(-srcH, srcW);\n      } else {\n        ctx.translate(0, srcW);\n      }\n      ctx.rotate(3 * Math.PI / 2);\n      ctx.scale(srcW / srcH, srcH / srcW);\n    }\n    ctx.drawImage(frame.frame, 0, 0, srcH, srcW);\n    ctx.restore();\n  } else {\n    const opt = getCachedDrawParams(\n      layout.id,\n      srcW,\n      srcH,\n      layout.width,\n      layout.height,\n      layout.fillMode,\n      false\n    );\n    const dw = opt.dWidth;\n    const dh = opt.dHeight;\n    const needsTransform = !!layout.mirror || rotation !== 0;\n    if (needsTransform) {\n      ctx.save();\n      ctx.translate(layout.x, layout.y);\n      if (layout.mirror) {\n        ctx.scale(-1, 1);\n        ctx.translate(-dw, 0);\n      }\n      if (rotation === 180) {\n        ctx.translate(dw, dh);\n        ctx.rotate(Math.PI);\n      }\n      ctx.drawImage(frame.frame, opt.sx, opt.sy, opt.sWidth, opt.sHeight, opt.dx, opt.dy, dw, dh);\n      ctx.restore();\n    } else {\n      ctx.drawImage(\n        frame.frame,\n        opt.sx,\n        opt.sy,\n        opt.sWidth,\n        opt.sHeight,\n        layout.x + opt.dx,\n        layout.y + opt.dy,\n        dw,\n        dh\n      );\n    }\n  }\n}\nfunction render() {\n  if (!canvas || !ctx) {\n    dropFrames++;\n    dropByOther++;\n    return;\n  }\n  if (isRendering) {\n    dropFrames++;\n    dropByRendering++;\n    return;\n  }\n  isRendering = true;\n  try {\n    if (backgroundImage) {\n      ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);\n    } else {\n      ctx.fillStyle = backgroundColor;\n      ctx.fillRect(0, 0, canvas.width, canvas.height);\n    }\n    let drawnCount = 0;\n    let missedIds = null;\n    for (const layout of layouts) {\n      if (layout.hidden) continue;\n      const frame = latestFrames.get(layout.id);\n      if (!frame) {\n        if (!missedIds) missedIds = [];\n        missedIds.push(layout.id);\n        continue;\n      }\n      drawFrame(layout, frame);\n      drawnCount++;\n    }\n    if (missedIds && missedIds.length > 0) {\n      throttledLog("frameMiss", "debug", `[Worker] render: missed frames for layouts=[${missedIds.join(",")}], drawn=${drawnCount}, latestFrames keys=[${[...latestFrames.keys()].join(",")}], layouts=[${layouts.map((l) => l.id).join(",")}], streamControllers=[${[...streamControllers.keys()].join(",")}]`, 3e3);\n    }\n    if (trackGeneratorWriter) {\n      if (trackGeneratorWriter.desiredSize === null || trackGeneratorWriter.desiredSize <= 0) {\n        dropFrames++;\n        dropByBackpressure++;\n        if (!isBackpressure) {\n          isBackpressure = true;\n          backpressureStartTime = performance.now();\n          backpressureTotalDrops = 0;\n        }\n        backpressureTotalDrops++;\n        throttledLog("backpressure", "warn", `[Worker] Writer backpressure, skipping frames. desiredSize=${trackGeneratorWriter.desiredSize}, dropFrames=${dropFrames}`);\n      } else {\n        if (isBackpressure) {\n          const duration = ((performance.now() - backpressureStartTime) / 1e3).toFixed(1);\n          workerLog("info", `[Worker] Writer backpressure recovered. duration=${duration}s, droppedDuringBackpressure=${backpressureTotalDrops}`);\n          isBackpressure = false;\n          backpressureStartTime = 0;\n          backpressureTotalDrops = 0;\n        }\n        if (canvas.width <= 0 || canvas.height <= 0) {\n          dropFrames++;\n          dropByCanvasSize++;\n          if (!isCanvasSizeZero) {\n            isCanvasSizeZero = true;\n            workerLog("warn", `[Worker] Canvas size is 0 (${canvas.width}x${canvas.height}), skipping VideoFrame creation`);\n          }\n        } else {\n          if (isCanvasSizeZero) {\n            isCanvasSizeZero = false;\n            workerLog("info", `[Worker] Canvas size recovered to ${canvas.width}x${canvas.height}`);\n          }\n          let frame = null;\n          try {\n            frame = new VideoFrame(canvas, { timestamp: performance.now() * 1e3 });\n            const frameWidth = frame.displayWidth;\n            const frameHeight = frame.displayHeight;\n            trackGeneratorWriter.write(frame);\n            totalFrames++;\n            trackGeneratorFailCount = 0;\n            if (consecutiveWriteFailures > 0) {\n              workerLog("info", `[Worker] VideoFrame write recovered after ${consecutiveWriteFailures} consecutive failures`);\n              consecutiveWriteFailures = 0;\n            }\n            if (isFirstFrame) {\n              isFirstFrame = false;\n              workerLog("info", `[Worker] TrackGenerator First VideoFrame written successfully, width=${frameWidth}, height=${frameHeight}`);\n            }\n          } catch (err) {\n            if (frame) {\n              try {\n                frame.close();\n              } catch (e) {\n              }\n            }\n            dropFrames++;\n            dropByWriteFail++;\n            trackGeneratorFailCount++;\n            consecutiveWriteFailures++;\n            if (consecutiveWriteFailures <= 3) {\n              workerLog("warn", `[Worker] VideoFrame write failed: ${err.message || err}, failCount=${trackGeneratorFailCount}`);\n            } else {\n              throttledLog("writeFail", "warn", `[Worker] VideoFrame write still failing: ${err.message || err}, consecutiveFailures=${consecutiveWriteFailures}, failCount=${trackGeneratorFailCount}`);\n            }\n            if (trackGeneratorFailCount >= TRACK_GENERATOR_FAIL_THRESHOLD) {\n              workerLog("error", `[Worker] TrackGenerator failed ${trackGeneratorFailCount} times, requesting degradation`);\n              self.postMessage({ type: "trackGeneratorFailed", failCount: trackGeneratorFailCount });\n            }\n          }\n        }\n      }\n    } else {\n      if (!renderLoopStarted) {\n        return;\n      }\n      dropFrames++;\n      dropByOther++;\n      workerLog("error", "[Worker] No TrackGenerator writer available, cannot output frames");\n      stopRenderLoop();\n      self.postMessage({ type: "error", message: "No TrackGenerator writer available, rendering stopped" });\n      return;\n    }\n  } catch (err) {\n    dropFrames++;\n    dropByOther++;\n    throttledLog("renderError", "error", `[Worker] Render error: ${err.message || err}`);\n  } finally {\n    isRendering = false;\n  }\n}\nfunction startRenderLoop() {\n  stopRenderLoop();\n  if (fps <= 0) return;\n  const interval = 1e3 / fps;\n  renderIntervalId = setInterval(render, interval);\n  renderLoopStarted = true;\n  lastHealthLogTime = performance.now();\n  lastHealthLogFrames = totalFrames;\n  dropByBackpressure = 0;\n  dropByRendering = 0;\n  dropByCanvasSize = 0;\n  dropByWriteFail = 0;\n  dropByOther = 0;\n}\nfunction stopRenderLoop() {\n  if (renderIntervalId !== null) {\n    clearInterval(renderIntervalId);\n    renderIntervalId = null;\n  }\n  renderLoopStarted = false;\n  throttleLogTimestamps.clear();\n}\nfunction closeFrames() {\n  latestFrames.forEach((frameData) => {\n    try {\n      if ("close" in frameData.frame && typeof frameData.frame.close === "function") {\n        frameData.frame.close();\n      }\n    } catch (e) {\n    }\n  });\n  latestFrames.clear();\n}\nfunction abortAllStreams() {\n  clearAllStreamStallTimers();\n  streamControllers.forEach((controller, id) => {\n    try {\n      controller.abort();\n    } catch (e) {\n    }\n  });\n  streamControllers.clear();\n}\nvar streamFirstFrameReceived = /* @__PURE__ */ new Map();\nvar STREAM_STALL_TIMEOUT_MS = 3e3;\nvar streamStallTimers = /* @__PURE__ */ new Map();\nfunction clearStreamStallTimer(id) {\n  const timer = streamStallTimers.get(id);\n  if (timer) {\n    clearTimeout(timer);\n    streamStallTimers.delete(id);\n  }\n}\nfunction clearAllStreamStallTimers() {\n  streamStallTimers.forEach((timer) => {\n    clearTimeout(timer);\n  });\n  streamStallTimers.clear();\n}\nfunction startReadableStreamPipeline(id, readable) {\n  const existing = streamControllers.get(id);\n  if (existing) {\n    workerLog("debug", `[Worker] startReadableStreamPipeline(${id}): aborting existing pipeline`);\n    try {\n      existing.abort();\n    } catch (e) {\n    }\n    streamControllers.delete(id);\n  }\n  const abortController = new AbortController();\n  streamControllers.set(id, abortController);\n  streamFirstFrameReceived.set(id, false);\n  clearStreamStallTimer(id);\n  const stallTimer = setTimeout(() => {\n    streamStallTimers.delete(id);\n    if (!streamFirstFrameReceived.get(id)) {\n      workerLog("warn", `[Worker] ReadableStream(${id}): no frames received within ${STREAM_STALL_TIMEOUT_MS}ms, reporting streamStalled`);\n      self.postMessage({\n        type: "streamStalled",\n        id,\n        stallDuration: STREAM_STALL_TIMEOUT_MS\n      });\n    }\n  }, STREAM_STALL_TIMEOUT_MS);\n  streamStallTimers.set(id, stallTimer);\n  workerLog("debug", `[Worker] startReadableStreamPipeline(${id}): pipeline created, stall timer started (${STREAM_STALL_TIMEOUT_MS}ms), waiting for frames...`);\n  const writable = new WritableStream({\n    write(frame) {\n      if (!streamFirstFrameReceived.get(id)) {\n        streamFirstFrameReceived.set(id, true);\n        clearStreamStallTimer(id);\n        workerLog("info", `[Worker] ReadableStream(${id}): first frame received, ${frame.displayWidth}x${frame.displayHeight}, latestFrames.size=${latestFrames.size}, stall timer cancelled`);\n      }\n      const prev = latestFrames.get(id);\n      if (prev) {\n        try {\n          if ("close" in prev.frame && typeof prev.frame.close === "function") {\n            prev.frame.close();\n          }\n        } catch (e) {\n        }\n      }\n      latestFrames.set(id, {\n        id,\n        frame,\n        width: frame.displayWidth,\n        height: frame.displayHeight\n      });\n    },\n    close() {\n      workerLog("info", `[Worker] ReadableStream(${id}): stream closed normally`);\n      clearStreamStallTimer(id);\n      streamControllers.delete(id);\n      streamFirstFrameReceived.delete(id);\n    },\n    abort() {\n      workerLog("debug", `[Worker] ReadableStream(${id}): stream aborted`);\n      clearStreamStallTimer(id);\n      streamControllers.delete(id);\n      streamFirstFrameReceived.delete(id);\n    }\n  });\n  readable.pipeTo(writable, { signal: abortController.signal }).catch((err) => {\n    if (err.name === "AbortError") {\n      workerLog("debug", `[Worker] ReadableStream(${id}): pipeTo aborted (expected)`);\n      return;\n    }\n    workerLog("warn", `[Worker] ReadableStream(${id}): pipeTo error: ${err.message || err}`);\n    clearStreamStallTimer(id);\n    streamControllers.delete(id);\n    streamFirstFrameReceived.delete(id);\n    self.postMessage({\n      type: "streamError",\n      id,\n      message: `ReadableStream pipeline error: ${err.message || err}`\n    });\n  });\n}\nfunction removeReadableStreamPipeline(id) {\n  const hadController = streamControllers.has(id);\n  const hadFrame = latestFrames.has(id);\n  const controller = streamControllers.get(id);\n  if (controller) {\n    try {\n      controller.abort();\n    } catch (e) {\n    }\n    streamControllers.delete(id);\n  }\n  const frameData = latestFrames.get(id);\n  if (frameData) {\n    try {\n      if ("close" in frameData.frame && typeof frameData.frame.close === "function") {\n        frameData.frame.close();\n      }\n    } catch (e) {\n    }\n    latestFrames.delete(id);\n  }\n  clearStreamStallTimer(id);\n  streamFirstFrameReceived.delete(id);\n  workerLog("debug", `[Worker] removeReadableStreamPipeline(${id}): hadController=${hadController}, hadFrame=${hadFrame}, remaining latestFrames=[${[...latestFrames.keys()].join(",")}]`);\n}\nfunction closeTrackGeneratorWriter() {\n  if (trackGeneratorWriter) {\n    try {\n      trackGeneratorWriter.close();\n    } catch (e) {\n    }\n    trackGeneratorWriter = null;\n  }\n}\nfunction startHealthLog() {\n  stopHealthLog();\n  lastHealthLogTime = performance.now();\n  lastHealthLogFrames = totalFrames;\n  healthLogIntervalId = setInterval(() => {\n    const now = performance.now();\n    const elapsed = (now - lastHealthLogTime) / 1e3;\n    if (elapsed <= 0) return;\n    const framesDelta = totalFrames - lastHealthLogFrames;\n    const actualFps = framesDelta / elapsed;\n    const writerInfo = trackGeneratorWriter ? `desiredSize=${trackGeneratorWriter.desiredSize}` : "no writer";\n    const periodDrops = dropByBackpressure + dropByRendering + dropByCanvasSize + dropByWriteFail + dropByOther;\n    if (renderLoopStarted && Math.ceil(actualFps) < 5 || periodDrops > 0) {\n      let msg = `[Worker] Health: totalFrames=${totalFrames}, dropFrames=${dropFrames}, fps=${actualFps.toFixed(1)}, ${writerInfo}`;\n      if (periodDrops > 0) {\n        const parts = [];\n        if (dropByBackpressure > 0) parts.push(`backpressure=${dropByBackpressure}`);\n        if (dropByRendering > 0) parts.push(`rendering=${dropByRendering}`);\n        if (dropByCanvasSize > 0) parts.push(`canvasSize=${dropByCanvasSize}`);\n        if (dropByWriteFail > 0) parts.push(`writeFail=${dropByWriteFail}`);\n        if (dropByOther > 0) parts.push(`other=${dropByOther}`);\n        msg += `, periodDrops={${parts.join(", ")}}`;\n      }\n      const suggestions = [];\n      if (dropByBackpressure > 0) suggestions.push("reduce fps or resolution to alleviate backpressure");\n      if (dropByRendering > 0) suggestions.push("reduce fps or layout count to avoid render overlap");\n      if (dropByCanvasSize > 0) suggestions.push("check canvas dimensions configuration");\n      if (dropByWriteFail > 0) suggestions.push("check encoding parameters or TrackGenerator state");\n      if (suggestions.length > 0) {\n        msg += `. Suggestion: ${suggestions.join("; ")}`;\n      }\n      workerLog(actualFps < 5 ? "warn" : "info", msg);\n    }\n    dropByBackpressure = 0;\n    dropByRendering = 0;\n    dropByCanvasSize = 0;\n    dropByWriteFail = 0;\n    dropByOther = 0;\n    lastHealthLogTime = now;\n    lastHealthLogFrames = totalFrames;\n  }, 2e3);\n}\nfunction stopHealthLog() {\n  if (healthLogIntervalId !== null) {\n    clearInterval(healthLogIntervalId);\n    healthLogIntervalId = null;\n  }\n}\nself.onmessage = (event) => {\n  const { data } = event;\n  switch (data.type) {\n    case "init": {\n      canvas = data.canvas;\n      ctx = canvas.getContext("2d");\n      if (!ctx) {\n        self.postMessage({\n          type: "error",\n          message: "Failed to get OffscreenCanvas 2d context in Worker"\n        });\n        return;\n      }\n      if (data.width) canvas.width = data.width;\n      if (data.height) canvas.height = data.height;\n      if (data.writable) {\n        try {\n          trackGeneratorWriter = data.writable.getWriter();\n          isFirstFrame = true;\n          trackGeneratorFailCount = 0;\n          workerLog("info", `[Worker] TrackGenerator writer obtained, desiredSize=${trackGeneratorWriter.desiredSize}`);\n        } catch (err) {\n          workerLog("warn", `[Worker] Failed to get TrackGenerator writer: ${err.message || err}`);\n          trackGeneratorWriter = null;\n        }\n      }\n      startHealthLog();\n      self.postMessage({ type: "ready" });\n      break;\n    }\n    case "updateFrames": {\n      const frames = data.frames;\n      for (const frameData of frames) {\n        const prev = latestFrames.get(frameData.id);\n        if (prev) {\n          try {\n            if ("close" in prev.frame && typeof prev.frame.close === "function") {\n              prev.frame.close();\n            }\n          } catch (e) {\n          }\n        }\n        latestFrames.set(frameData.id, frameData);\n      }\n      break;\n    }\n    case "updateLayout": {\n      layouts = data.layouts.sort((a, b) => a.zIndex - b.zIndex);\n      const layoutIds = new Set(layouts.map((l) => l.id));\n      for (const key of drawParamsCache.keys()) {\n        if (!layoutIds.has(key)) {\n          drawParamsCache.delete(key);\n        }\n      }\n      break;\n    }\n    case "setFps": {\n      fps = data.fps;\n      if (renderIntervalId !== null) {\n        startRenderLoop();\n      }\n      break;\n    }\n    case "setBackground": {\n      backgroundColor = data.color || "black";\n      backgroundImage = null;\n      break;\n    }\n    case "setBackgroundImage": {\n      if (backgroundImage) {\n        backgroundImage.close();\n      }\n      backgroundImage = data.bitmap || null;\n      break;\n    }\n    case "resize": {\n      if (canvas) {\n        canvas.width = data.width;\n        canvas.height = data.height;\n      }\n      break;\n    }\n    case "start": {\n      fps = data.fps || fps;\n      startRenderLoop();\n      break;\n    }\n    case "stop": {\n      stopRenderLoop();\n      break;\n    }\n    case "closeWriter": {\n      stopRenderLoop();\n      closeTrackGeneratorWriter();\n      break;\n    }\n    case "addReadableStream": {\n      const { id, readable } = data;\n      workerLog("debug", `[Worker] received addReadableStream message: id=${id}, hasReadable=${!!readable}`);\n      startReadableStreamPipeline(id, readable);\n      break;\n    }\n    case "removeReadableStream": {\n      workerLog("debug", `[Worker] received removeReadableStream message: id=${data.id}`);\n      removeReadableStreamPipeline(data.id);\n      break;\n    }\n    case "addImageSource": {\n      const { id, src, animated, mimeType } = data;\n      handleAddImageSource(id, src, animated, mimeType);\n      break;\n    }\n    case "updateImageSource": {\n      const { id, src, animated, mimeType } = data;\n      handleUpdateImageSource(id, src, animated, mimeType);\n      break;\n    }\n    case "removeImageSource": {\n      handleRemoveImageSource(data.id);\n      break;\n    }\n    // ===== Bitmap source protocol (plugin-pre-rendered bitmaps) =====\n    // 与 addImageSource(URL) 并存:URL 路径由 Worker 内部 fetch + 支持动图;\n    // bitmap 路径用于承载插件主线程已绘制完成的静态 bitmap(如 text 源)。\n    case "addBitmapSource":\n    case "updateBitmapSource": {\n      const { id, bitmap } = data;\n      if (!bitmap) break;\n      const prev = latestFrames.get(id);\n      if (prev && prev.frame instanceof ImageBitmap && prev.frame !== bitmap) {\n        try {\n          prev.frame.close();\n        } catch (e) {\n        }\n      }\n      latestFrames.set(id, {\n        id,\n        frame: bitmap,\n        width: bitmap.width,\n        height: bitmap.height\n      });\n      break;\n    }\n    case "removeBitmapSource": {\n      const { id } = data;\n      const prev = latestFrames.get(id);\n      if (prev && prev.frame instanceof ImageBitmap) {\n        try {\n          prev.frame.close();\n        } catch (e) {\n        }\n      }\n      latestFrames.delete(id);\n      break;\n    }\n    case "destroy": {\n      stopRenderLoop();\n      stopHealthLog();\n      closeTrackGeneratorWriter();\n      abortAllStreams();\n      imageSources.forEach((_, id) => handleRemoveImageSource(id));\n      imageSources.clear();\n      closeFrames();\n      drawParamsCache.clear();\n      throttleLogTimestamps.clear();\n      if (backgroundImage) {\n        backgroundImage.close();\n        backgroundImage = null;\n      }\n      ctx = null;\n      canvas = null;\n      layouts = [];\n      self.postMessage({ type: "destroyed" });\n      self.close();\n      break;\n    }\n    default:\n      break;\n  }\n};\n';function isWorkerRendererSupported(){return"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof MediaStreamTrackGenerator&&"undefined"!=typeof MediaStreamTrackProcessor&&"undefined"!=typeof Worker}async function renderTextToBitmap(e,r,t,a){if(!r||!t)return null;const n=new OffscreenCanvas(r,t),s=n.getContext("2d");if(!s)return null;s.textBaseline="top";const i=(null==a?void 0:a.font)||"16px sans-serif",o=(null==a?void 0:a.color)||"white";s.font=i,s.fillStyle=o;const c=/(\d+(?:\.\d+)?)px/.exec(i),d=1.2*(c?parseFloat(c[1]):16),l=e.split("\n"),u=s.measureText(e),p=u.fontBoundingBoxAscent||u.actualBoundingBoxAscent||0;for(let e=0;e<l.length;e++)s.fillText(l[e],0,p+e*d);return n.transferToImageBitmap()}function createConsoleLogger(){const e=e=>r=>{try{e(r)}catch(e){}};return{info:e(e=>console.info(e)),warn:e(e=>console.warn(e)),error:e(e=>console.error(e)),debug:e(e=>console.debug?console.debug(e):console.log(e))}}var WorkerMixRenderer=class{constructor(e){var r;__publicField(this,"_workerScript"),__publicField(this,"_logger"),__publicField(this,"_worker",null),__publicField(this,"_workerUrl",null),__publicField(this,"_generator",null),__publicField(this,"_outputTrack",null),__publicField(this,"_width",0),__publicField(this,"_height",0),__publicField(this,"_fps",15),__publicField(this,"_sources",new Map),__publicField(this,"_listeners",{unrecoverable:new Set}),__publicField(this,"_destroyed",!1),__publicField(this,"_workerFatal",!1),__publicField(this,"_onWorkerMessage",e=>{if(this._destroyed)return;const r=e.data;if(r&&"object"==typeof r)switch(r.type){case"streamError":case"imageSourceError":this._logger.warn(`Worker imageSource error: id=${r.id}, ${r.message}`);break;case"imageSourceLoaded":this._logger.debug(`Worker imageSource loaded: id=${r.id}, ${r.width}x${r.height}`);break;case"log":this._forwardWorkerLog(r.level,r.message)}}),__publicField(this,"_onWorkerError",e=>{if(this._destroyed||this._workerFatal)return;this._workerFatal=!0;const r=e,t=[];r.message&&t.push(`message=${r.message}`),r.filename&&t.push(`filename=${r.filename}`),"number"==typeof r.lineno&&t.push(`lineno=${r.lineno}`),"number"==typeof r.colno&&t.push(`colno=${r.colno}`),e.type&&t.push(`eventType=${e.type}`);const a=t.length>0?t.join(", "):"worker error";try{this._logger.error(`unrecoverable: ${a}`)}catch(e){}this._emit("unrecoverable",a)}),this._workerScript=e.workerScript,this._logger=null!=(r=e.logger)?r:createConsoleLogger()}async init(e){var r;if(!isWorkerRendererSupported())throw new Error("WorkerMixRenderer: environment does not support OffscreenCanvas + MediaStreamTrackGenerator + Worker");if(this._worker)throw new Error("WorkerMixRenderer: already initialized");this._width=e.width,this._height=e.height,this._fps=null!=(r=e.fps)?r:15,this._workerUrl=URL.createObjectURL(new Blob([this._workerScript],{type:"application/javascript"})),this._worker=new Worker(this._workerUrl),this._worker.addEventListener("message",this._onWorkerMessage),this._worker.addEventListener("error",this._onWorkerError),this._worker.addEventListener("messageerror",this._onWorkerError);const t=new OffscreenCanvas(this._width||640,this._height||480);this._generator=new MediaStreamTrackGenerator({kind:"video"}),this._outputTrack=this._generator;const a=this._generator.writable,n=this._waitWorkerReady();this._worker.postMessage({type:"init",canvas:t,writable:a,width:this._width,height:this._height},[t,a]),this._worker.postMessage({type:"start",fps:this._fps}),e.backgroundColor&&this._worker.postMessage({type:"setBackground",color:e.backgroundColor}),await n}getOutputTrack(){if(!this._outputTrack)throw new Error("WorkerMixRenderer: getOutputTrack called before init");return this._outputTrack}setFps(e){!this._destroyed&&this._worker&&(this._fps=e,this._worker.postMessage({type:"setFps",fps:e}))}async destroy(){var e,r,t,a,n,s;if(!this._destroyed){this._destroyed=!0;try{null==(e=this._worker)||e.postMessage({type:"destroy"})}catch(e){}try{null==(r=this._generator)||r.stop()}catch(e){}this._generator=null,this._outputTrack=null;for(const e of this._sources.values())if(e.bitmap&&"close"in e.bitmap)try{e.bitmap.close()}catch(e){}this._sources.clear(),await new Promise(e=>setTimeout(e,0));try{null==(t=this._worker)||t.removeEventListener("message",this._onWorkerMessage),null==(a=this._worker)||a.removeEventListener("error",this._onWorkerError),null==(n=this._worker)||n.removeEventListener("messageerror",this._onWorkerError),null==(s=this._worker)||s.terminate()}catch(e){}if(this._worker=null,this._workerUrl){try{URL.revokeObjectURL(this._workerUrl)}catch(e){}this._workerUrl=null}this._listeners.unrecoverable.clear()}}addSource(e,r,t,a){if(this._destroyed||!this._worker)return;this._sources.has(e)&&this.removeSource(e);const n={kind:t,layout:__spreadProps(__spreadValues({},a),{id:e})};if("track"===t){const t=r;try{const r=new MediaStreamTrackProcessor({track:t});n.processor=r;const{readable:a}=r;this._worker.postMessage({type:"addReadableStream",id:e,readable:a},[a])}catch(r){return void this._logger.warn(`addSource(track) failed for id=${e}: ${(null==r?void 0:r.message)||r}`)}}else if("image"===t)if(r instanceof ImageBitmap){const t=r;n.bitmap=t,this._worker.postMessage({type:"addBitmapSource",id:e,bitmap:t},[t])}else{const t=r;n.isUrlImage=!0,this._worker.postMessage({type:"addImageSource",id:e,src:t.src,animated:!!t.animated,mimeType:t.mimeType})}else if("text"===t){const t=r;n.text={content:t,width:a.width,height:a.height,style:{}},this._renderTextAndSend(e,t,a.width,a.height,{},!1)}this._sources.set(e,n),this._sendLayoutSnapshot()}updateSource(e,r){var t,a,n;if(this._destroyed||!this._worker)return;const s=this._sources.get(e);if(s)if("track"===s.kind){try{null==(t=s.processor)||t.readable.cancel()}catch(e){}s.processor=null,this._worker.postMessage({type:"removeReadableStream",id:e});try{const t=new MediaStreamTrackProcessor({track:r});s.processor=t;const{readable:a}=t;this._worker.postMessage({type:"addReadableStream",id:e,readable:a},[a])}catch(r){this._logger.warn(`updateSource(track) failed for id=${e}: ${(null==r?void 0:r.message)||r}`)}}else if("image"===s.kind)if(r instanceof ImageBitmap){s.isUrlImage&&(this._worker.postMessage({type:"removeImageSource",id:e}),s.isUrlImage=!1);const t=r;s.bitmap=t,this._worker.postMessage({type:"updateBitmapSource",id:e,bitmap:t},[t])}else{const t=r;if(!s.isUrlImage&&(this._worker.postMessage({type:"removeBitmapSource",id:e}),s.bitmap)){try{s.bitmap.close()}catch(e){}s.bitmap=null}s.isUrlImage=!0,this._worker.postMessage({type:"updateImageSource",id:e,src:t.src,animated:!!t.animated,mimeType:t.mimeType})}else if("text"===s.kind){const t=r,i=null!=(n=null==(a=s.text)?void 0:a.style)?n:{};s.text={content:t,width:s.layout.width,height:s.layout.height,style:i},this._renderTextAndSend(e,t,s.layout.width,s.layout.height,i,!0)}}addTextSource(e,r,t,a){if(this._destroyed||!this._worker)return;this._sources.has(e)&&this.removeSource(e);const n={kind:"text",layout:__spreadProps(__spreadValues({},a),{id:e}),text:{content:r,width:a.width,height:a.height,style:__spreadValues({},t)}};this._sources.set(e,n),this._renderTextAndSend(e,r,a.width,a.height,__spreadValues({},t),!1),this._sendLayoutSnapshot()}updateTextSource(e,r,t){var a,n;if(this._destroyed||!this._worker)return;const s=this._sources.get(e);if(!s||"text"!==s.kind)return;const i=__spreadValues(__spreadValues({},null!=(n=null==(a=s.text)?void 0:a.style)?n:{}),t);s.text={content:r,width:s.layout.width,height:s.layout.height,style:i},this._renderTextAndSend(e,r,s.layout.width,s.layout.height,i,!0)}removeSource(e){var r;if(this._destroyed||!this._worker)return;const t=this._sources.get(e);if(t){if("track"===t.kind){try{null==(r=t.processor)||r.readable.cancel()}catch(e){}this._worker.postMessage({type:"removeReadableStream",id:e})}else"image"===t.kind&&t.isUrlImage?this._worker.postMessage({type:"removeImageSource",id:e}):this._worker.postMessage({type:"removeBitmapSource",id:e});if(t.bitmap)try{t.bitmap.close()}catch(e){}this._sources.delete(e),this._sendLayoutSnapshot()}}updateLayout(e){if(!this._destroyed&&this._worker){for(const r of e){const e=this._sources.get(r.id);if(!e)continue;const t=e.layout;e.layout=__spreadValues({},r),"text"!==e.kind||!e.text||t.width===r.width&&t.height===r.height||(e.text.width=r.width,e.text.height=r.height,this._renderTextAndSend(r.id,e.text.content,r.width,r.height,e.text.style,!0))}this._sendLayoutSnapshot()}}setBackground(e){!this._destroyed&&this._worker&&this._worker.postMessage({type:"setBackground",color:e})}setBackgroundImage(e){!this._destroyed&&this._worker&&(e?this._worker.postMessage({type:"setBackgroundImage",bitmap:e},[e]):this._worker.postMessage({type:"setBackground",color:"black"}))}resize(e,r){!this._destroyed&&this._worker&&(this._width=e,this._height=r,this._worker.postMessage({type:"resize",width:e,height:r}))}on(e,r){this._listeners[e].add(r)}off(e,r){this._listeners[e].delete(r)}_emit(e,r){for(const t of this._listeners[e])try{t(r)}catch(e){}}_sendLayoutSnapshot(){if(!this._worker)return;const e=[];for(const r of this._sources.values())e.push(__spreadValues({},r.layout));this._worker.postMessage({type:"updateLayout",layouts:e})}async _renderTextAndSend(e,r,t,a,n,s){if(!this._destroyed&&this._worker)try{const i=await renderTextToBitmap(r,t,a,n);if(!i)return;if(this._destroyed||!this._worker){try{i.close()}catch(e){}return}const o=this._sources.get(e);if(!o){try{i.close()}catch(e){}return}o.bitmap=null,this._worker.postMessage({type:s?"updateBitmapSource":"addBitmapSource",id:e,bitmap:i},[i])}catch(r){this._logger.warn(`renderText failed for id=${e}: ${(null==r?void 0:r.message)||r}`)}}_waitWorkerReady(){return new Promise((e,r)=>{if(!this._worker)return r(new Error("worker not created"));const t=this._worker,a=s=>{var i,o;"ready"===(null==(i=s.data)?void 0:i.type)?(t.removeEventListener("message",a),t.removeEventListener("error",n),e()):"error"===(null==(o=s.data)?void 0:o.type)&&(t.removeEventListener("message",a),t.removeEventListener("error",n),r(new Error(`worker init error: ${s.data.message}`)))},n=e=>{t.removeEventListener("message",a),t.removeEventListener("error",n),r(new Error(`worker error: ${e.message}`))};t.addEventListener("message",a),t.addEventListener("error",n)})}_forwardWorkerLog(e,r){const t=`${"string"==typeof r?r:JSON.stringify(r)}`;try{switch(e){case"warn":this._logger.warn(t);break;case"error":this._logger.error(t);break;case"debug":this._logger.debug(t);break;default:this._logger.info(t)}}catch(e){}}},videoMixSeq=0,_VideoMixer=class e{constructor(e){this.core=e,__publicField(this,"seq"),__publicField(this,"log"),__publicField(this,"localMixVideoTrack",null),__publicField(this,"systemAudioTrackList",{}),__publicField(this,"_mixVideoConfig"),__publicField(this,"onScreenShareStop"),__publicField(this,"eventListeners",new Map),videoMixSeq+=1,this.seq=videoMixSeq,this.log=e.log.createChild({id:`${this.getAlias()}${videoMixSeq}`}),this.log.info("created")}getName(){return e.Name}getAlias(){return"vmix"}getValidateRule(e){switch(e){case"start":return startValidateRule(this.core);case"update":return updateValidateRule(this.core);case"stop":return stopValidateRule(this.core)}}getGroup(){return"vmix"}async start(e){this.localMixVideoTrack||(this.localMixVideoTrack=new this.core.LocalMixVideoTrack(this.core.room.videoManager)),this._mixVideoConfig={canvasInfo:{width:1920,height:1080}},e=this.core.utils.deepCloneBasic(e);const{view:r,onScreenShareStop:t}=e,{syncResult:a,asyncSourcesInfo:n}=await this.parseMixOptionsSyncPhase(e);t&&(this.onScreenShareStop=t,this._mixVideoConfig.onScreenShareStop=t),this._updatePreview({view:r,track:this.localMixVideoTrack}),this.core.utils.isUndefined(r)||(this._mixVideoConfig.view=r),await this.localMixVideoTrack.startMix({enableWorkerRenderer:!0}),await this._tryAttachWorkerRenderer();const s=await this.parseMixOptionsAsyncPhase(n),i=__spreadValues(__spreadValues({},a.successOptions),s.successOptions),o=[...a.failedDetails,...s.failedDetails];a.successOptions.screen&&s.successOptions.screen&&(i.screen=[...a.successOptions.screen,...s.successOptions.screen]);const c=a.sourceCount+s.sourceCount,d=a.allFailCount+s.allFailCount;if(d>0&&d===c){const{RtcError:e,ErrorCode:r}=this.core.errorModule;throw new e({code:r.INVALID_PARAMETER,message:"all sources mix failed",data:{failedDetails:o}})}return{track:this.localMixVideoTrack.outMediaTrack,systemAudioTrackList:this.systemAudioTrackList,result:{successOptions:i,failedDetails:o}}}async _tryAttachWorkerRenderer(){if(!this.localMixVideoTrack||!this._mixVideoConfig)return;if(!isWorkerRendererSupported())return void this._setFallbackOutputTrack();const e=new WorkerMixRenderer({workerScript:mix_render_worker_default,logger:this.log});try{await this.localMixVideoTrack.attachRenderer(e)}catch(r){try{await e.destroy()}catch(e){}const t=(null==r?void 0:r.message)||String(r);this.log.info(`worker renderer attach failed, fallback to main-thread render: ${t}`),this._setFallbackOutputTrack()}}_setFallbackOutputTrack(){var e;if(!this.localMixVideoTrack)return;const r=null==(e=this.localMixVideoTrack.destination)?void 0:e.videoTrack;r&&this.localMixVideoTrack.setOutputMediaStreamTrack(r)}async update(e){const{RtcError:r,ErrorCode:t}=this.core.errorModule;if(!this.localMixVideoTrack)throw new r({code:t.INVALID_OPERATION,message:"mixTrack doesn't initialize!"});e=this.core.utils.deepCloneBasic(e);const{view:a}=e,n=await this.parseMixOptions(e);return await this._updatePreview({view:a,track:this.localMixVideoTrack,prevConfig:this._mixVideoConfig}),this.core.utils.isUndefined(a)||(this._mixVideoConfig.view=a),{track:this.localMixVideoTrack.outMediaTrack,systemAudioTrackList:this.systemAudioTrackList,result:n}}stop(){var e;this.eventListeners.forEach((e,r)=>{this.removeEventListeners(r)}),this.eventListeners.clear(),null==(e=this.localMixVideoTrack)||e.close(),this.localMixVideoTrack=null,Object.values(this.systemAudioTrackList).forEach(e=>e.stop()),this.systemAudioTrackList={},delete this.onScreenShareStop,delete this._mixVideoConfig,void 0!==this.core.room.isUsingVideoMixerInternalTrack&&(this.core.room.isUsingVideoMixerInternalTrack=!1)}isBlockingScreenSource(e){return!0!==e.useInternalTrack&&!!this.core.utils.isUndefined(e.videoTrack)}async parseMixOptionsSyncPhase(e){const r={successOptions:{},failedDetails:[],sourceCount:0,allFailCount:0};if(!this.localMixVideoTrack||!this._mixVideoConfig)return{syncResult:r,asyncSourcesInfo:{blockingScreenSources:[],imageSources:void 0,videoSources:void 0}};const{canvasInfo:t,camera:a,screen:n,text:s,image:i,video:o}=e;let c=!1;a&&(c=a.some(e=>!0===e.useInternalTrack)),!c&&n&&(c=n.some(e=>!0===e.useInternalTrack)),void 0!==this.core.room.isUsingVideoMixerInternalTrack&&(this.core.room.isUsingVideoMixerInternalTrack=c,c&&this.log.debug("isUsingVideoMixerInternalTrack",c)),t&&this.parseCanvasOptions(t);let d=[],l=[];if(n)for(const e of n)this.isBlockingScreenSource(e)?l.push(e):d.push(e);const u=[{key:"camera",options:a,parser:this.parseCameraOptions.bind(this)},{key:"screen",options:d.length>0?d:void 0,parser:this.parseScreenOptions.bind(this)},{key:"text",options:s,parser:this.parseTextOptions.bind(this)}],p=__spreadValues({},e);for(const{key:e,options:t,parser:a}of u)if(t){r.sourceCount++;const n=await a(this.localMixVideoTrack,t,this._mixVideoConfig[e]||[]);this._mixVideoConfig[e]=n.finalOptions,p[e]=n.finalOptions,n.errors.length>0&&(r.failedDetails.push(...n.errors),n.errors.length===t.length&&r.allFailCount++)}return r.successOptions=p,{syncResult:r,asyncSourcesInfo:{blockingScreenSources:l,imageSources:i,videoSources:o}}}async parseMixOptionsAsyncPhase(e){const r={successOptions:{},failedDetails:[],sourceCount:0,allFailCount:0};if(!this.localMixVideoTrack||!this._mixVideoConfig)return r;const{blockingScreenSources:t,imageSources:a,videoSources:n}=e,s=[{key:"screen",options:t.length>0?t:void 0,parser:this.parseScreenOptions.bind(this)},{key:"image",options:a,parser:this.parseImageOptions.bind(this)},{key:"video",options:n,parser:this.parseVideoOptions.bind(this)}];for(const{key:e,options:t,parser:a}of s)if(t){r.sourceCount++;const n=await a(this.localMixVideoTrack,t,this._mixVideoConfig[e]||[]);if("screen"===e){const r=this._mixVideoConfig[e]||[];this._mixVideoConfig[e]=[...r,...n.finalOptions]}else this._mixVideoConfig[e]=n.finalOptions;r.successOptions[e]=n.finalOptions,n.errors.length>0&&(r.failedDetails.push(...n.errors),n.errors.length===t.length&&r.allFailCount++)}return r}async parseMixOptions(e){const{RtcError:r,ErrorCode:t}=this.core.errorModule;if(!this.localMixVideoTrack||!this._mixVideoConfig)return{successOptions:{},failedDetails:[]};const a=[],n=__spreadValues({},e),{canvasInfo:s,camera:i,screen:o,text:c,image:d,video:l}=e;let u=!1;i&&(u=i.some(e=>!0===e.useInternalTrack)),!u&&o&&(u=o.some(e=>!0===e.useInternalTrack)),void 0!==this.core.room.isUsingVideoMixerInternalTrack&&(this.core.room.isUsingVideoMixerInternalTrack=u,u&&this.log.debug("isUsingVideoMixerInternalTrack",u)),s&&this.parseCanvasOptions(s);let p=0,m=0;const h=[{key:"camera",options:i,parser:this.parseCameraOptions.bind(this)},{key:"screen",options:o,parser:this.parseScreenOptions.bind(this)},{key:"text",options:c,parser:this.parseTextOptions.bind(this)},{key:"image",options:d,parser:this.parseImageOptions.bind(this)},{key:"video",options:l,parser:this.parseVideoOptions.bind(this)}];for(const{key:e,options:r,parser:t}of h)if(r){p++;const s=await t(this.localMixVideoTrack,r,this._mixVideoConfig[e]||[]);this._mixVideoConfig[e]=s.finalOptions,n[e]=s.finalOptions,s.errors.length>0&&(a.push(...s.errors),s.errors.length===r.length&&m++)}if(m>0&&m===p)throw new r({code:t.INVALID_PARAMETER,message:"all sources mix failed",data:{failedDetails:a}});return{successOptions:n,failedDetails:a}}parseCanvasOptions(e){if(!this.localMixVideoTrack||!this._mixVideoConfig)return;const{canvasColor:r,width:t,height:a,frameRate:n}=e;r&&this.localMixVideoTrack.setMixBackground(r),n&&this.localMixVideoTrack.setFps(n),this.localMixVideoTrack.resizeMixCanvas(t,a),this._mixVideoConfig.canvasInfo=e}prepareSourceOptions(e,r){const t=new Set(e.map(e=>e.id));return{removeIdList:r.filter(e=>!t.has(e.id)).map(e=>e.id),preOptionsMap:new Map(r.map(e=>[e.id,e]))}}recordSourceError(e,r,t,a,n){n.push({id:e,error:r}),t.has(e)&&a.push(t.get(e))}async parseCameraOptions(e,r,t=[]){const{removeIdList:a,preOptionsMap:n}=this.prepareSourceOptions(r,t);for(const r of a)e.removeCameraSource(r),this.removeEventListeners(r);const s=[],i=[];for(const t of r)try{await this.processSingleCameraSource(e,t),s.push(t)}catch(e){this.recordSourceError(t.id,e,n,s,i)}return{finalOptions:s,errors:i}}async processSingleCameraSource(e,r){const{id:t}=r;this.resolveCameraInternalTrack(e,r),e.inputLocalVideoTracks.has(t)?await this.updateExistingCameraSource(e,r):await this.addNewCameraSource(e,r)}async updateExistingCameraSource(e,r){var t,a;const{id:n,layout:s,profile:i}=r,o=null==(t=e.inputLocalVideoTracks.get(n))?void 0:t.mediaTrack;await this.updateCameraProfile(r);const c=null==(a=e.inputLocalVideoTracks.get(n))?void 0:a.mediaTrack,d=this.resolveVideoProfile(i);c!==o?e.updateCameraSource(n,s,c,d):e.updateCameraSource(n,s,null,d)}resolveCameraInternalTrack(e,r){var t;const{id:a,layout:n,profile:s,useInternalTrack:i}=r;if(i){if(e.inputLocalVideoTracks.get(a))return r;this.log.debug("resolve camera internal track",r),(null==(t=this.core.trtc.localVideoTrack)?void 0:t.sourceTrack)?(this.log.debug("resolve camera internal track outMediaTrack:",this.core.trtc.localVideoTrack.outMediaTrack,"sourceTrack:",this.core.trtc.localVideoTrack.sourceTrack),r.videoTrack=this.core.trtc.localVideoTrack.outMediaTrack,r.profile=this.core.trtc.localVideoTrack.profile):r.videoTrack=this.createPlaceholderVideoTrack(),this.removeEventListeners(a);const s=r=>{var t,s;const i=e.inputLocalVideoTracks.get(a);this.log.debug(`camera internal track preprocessed event from ${null==(t=r.room)?void 0:t.userId} to ${this.core.room.userId}, is same instance:${r.room===this.core.room} ,new track:`,r.mediaTrack,null==i?void 0:i.mediaTrack,e.outMediaTrack),r.room===this.core.room&&i&&r.mediaTrack&&(null==(s=r.mediaTrack)?void 0:s.kind)===this.core.constants.NAME.VIDEO&&r.mediaTrack!==(null==i?void 0:i.mediaTrack)&&r.mediaTrack!==e.outMediaTrack&&e.updateCameraSource(a,n,r.mediaTrack)},i=r=>{var t,s,i,o,c,d,l,u;const p=e.inputLocalVideoTracks.get(a);this.log.debug(`camera internal track stopped ${(null==(t=r.track)?void 0:t.mediaTrack)===(null==p?void 0:p.mediaTrack)||(null==(s=r.track)?void 0:s.outMediaTrack)===(null==p?void 0:p.mediaTrack)||(null==(i=r.track)?void 0:i.outMediaTrack)===e.outMediaTrack}`,null==(o=r.track)?void 0:o.mediaTrack,null==(c=r.track)?void 0:c.outMediaTrack,null==p?void 0:p.mediaTrack,e.outMediaTrack),!p||(null==(d=r.track)?void 0:d.mediaTrack)!==(null==p?void 0:p.mediaTrack)&&(null==(l=r.track)?void 0:l.outMediaTrack)!==(null==p?void 0:p.mediaTrack)&&(null==(u=r.track)?void 0:u.outMediaTrack)!==e.outMediaTrack||e.updateCameraSource(a,n,this.createPlaceholderVideoTrack())};this.core.innerEmitter.on(this.core.INNER_EVENT.LOCAL_VIDEO_TRACK_PREPROCESSED,s),this.core.innerEmitter.on(this.core.INNER_EVENT.LOCAL_TRACK_STOPPED,i),this.eventListeners.has(a)||this.eventListeners.set(a,{}),this.eventListeners.get(a).captureSuccess=()=>{this.core.innerEmitter.off(this.core.INNER_EVENT.LOCAL_VIDEO_TRACK_PREPROCESSED,s)},this.eventListeners.get(a).trackStop=()=>{this.core.innerEmitter.off(this.core.INNER_EVENT.LOCAL_TRACK_STOPPED,i)}}return r}async addNewCameraSource(e,r){const{id:t,layout:a,useInternalTrack:n}=r,s=await this.captureCamera(r);try{e.addCameraSource(t,s,a)}catch(e){throw s.close(),e}}resolveVideoProfile(e){if(!this.core.utils.isUndefined(e))return this.core.utils.isString(e)?this.core.constants.videoProfileMap[e]:e}async parseScreenOptions(e,r,t=[]){const{removeIdList:a,preOptionsMap:n}=this.prepareSourceOptions(r,t);for(const r of a)e.removeScreenSource(r),this.removeSystemAudioTrack(r),this.removeEventListeners(r);const s=[],i=[];for(const t of r)try{await this.processSingleScreenSource(e,t,n),s.push(t)}catch(e){this.recordSourceError(t.id,e,n,s,i)}return{finalOptions:s,errors:i}}async processSingleScreenSource(e,r,t){const{id:a,layout:n,useInternalTrack:s}=r;this.resolveScreenInternalTrack(e,r);const i=t.get(a),o=e.inputLocalScreenTracks.has(a),c=!(null==i?void 0:i.systemAudio)&&r.systemAudio;o&&!c?this.updateExistingScreenSource(e,a,n,i,r):await this.addNewScreenSource(e,r,i)}updateExistingScreenSource(e,r,t,a,n){e.updateScreenSource(r,t),(null==a?void 0:a.systemAudio)&&!n.systemAudio&&this.removeSystemAudioTrack(r)}resolveScreenInternalTrack(e,r){var t,a;const{id:n,layout:s,useInternalTrack:i}=r;if(i){if(e.inputLocalScreenTracks.get(n))return r;this.log.debug("resolve screen internal track",r,r.id,r.videoTrack),(null==(t=this.core.trtc.localScreenTrack)?void 0:t.sourceTrack)?(r.videoTrack=this.core.trtc.localScreenTrack.sourceTrack,r.profile=this.core.trtc.localScreenTrack.profile,(null==(a=this.core.trtc.localScreenAudioTrack)?void 0:a.mediaTrack)&&(r.audioTrack=this.core.trtc.localScreenAudioTrack.mediaTrack),delete r.captureElement,delete r.preferDisplaySurface,delete r.systemAudio):r.videoTrack=this.createPlaceholderVideoTrack(),this.removeEventListeners(n);const i=r=>{var t,a,i;const o=e.inputLocalScreenTracks.get(n);this.log.debug(`screen internal track capture success event, is same instance:${r.room===this.core.room}, isScreen:${null==(t=r.track)?void 0:t.isScreen} kind:${null==(a=r.track)?void 0:a.kind}`,o,r.track.sourceTrack),r.track.isScreen&&(null==(i=r.track)?void 0:i.kind)===this.core.constants.NAME.VIDEO&&r.room===this.core.room&&r.track.sourceTrack&&o&&e.updateScreenSource(n,s,r.track.sourceTrack)},o=r=>{var t,a;const i=e.inputLocalScreenTracks.get(n);this.log.debug(`screen internal track stopped, is same track:${(null==(t=r.track)?void 0:t.sourceTrack)===(null==i?void 0:i.mediaTrack)}, isScreen:${r.track.isScreen}`),r.track.isScreen&&(null==(a=r.track)?void 0:a.sourceTrack)===(null==i?void 0:i.mediaTrack)&&e.updateScreenSource(n,s,this.createPlaceholderVideoTrack())};this.core.innerEmitter.on(this.core.INNER_EVENT.LOCAL_TRACK_CAPTURE_SUCCESS,i),this.core.innerEmitter.on(this.core.INNER_EVENT.LOCAL_TRACK_STOPPED,o),this.eventListeners.has(n)||this.eventListeners.set(n,{}),this.eventListeners.get(n).captureSuccess=()=>{this.core.innerEmitter.off(this.core.INNER_EVENT.LOCAL_TRACK_CAPTURE_SUCCESS,i)},this.eventListeners.get(n).trackStop=()=>{this.core.innerEmitter.off(this.core.INNER_EVENT.LOCAL_TRACK_STOPPED,o)}}return r}async addNewScreenSource(e,r,t){const{id:a,layout:n}=r,s=await this.captureScreen(r);!(null==t?void 0:t.systemAudio)&&r.systemAudio&&e.inputLocalScreenTracks.has(a)&&e.removeScreenSource(a);try{e.addScreenSource(a,s,n)}catch(e){throw s.close(),e}}async parseTextOptions(e,r,t=[]){const{removeIdList:a,preOptionsMap:n}=this.prepareSourceOptions(r,t);for(const r of a)e.removeTextSource(r);const s=[],i=[];for(const t of r)try{n.has(t.id)?e.updateTextSource(t):e.addTextSource(t),s.push(t)}catch(e){this.recordSourceError(t.id,e,n,s,i)}return{finalOptions:s,errors:i}}async parseImageOptions(e,r,t=[]){const{removeIdList:a,preOptionsMap:n}=this.prepareSourceOptions(r,t);for(const r of a)e.removeImageSource(r);const s=[],i=[];for(const t of r)try{await this.processSingleImageSource(e,t,n),s.push(t)}catch(e){this.recordSourceError(t.id,e,n,s,i)}return{finalOptions:s,errors:i}}async processSingleImageSource(e,r,t){const{id:a,url:n,layout:s}=r,i=t.get(a);if(i){let r;i.url!==n&&(r=await this.core.utils.loadImage(n)),e.updateImageSource(a,s,r)}else{const r=await this.core.utils.loadImage(n);e.addImageSource(a,r,s)}}async parseVideoOptions(e,r,t=[]){const{removeIdList:a,preOptionsMap:n}=this.prepareSourceOptions(r,t);for(const r of a)e.removeVideoSource(r);const s=[],i=[];for(const t of r)try{await this.processSingleVideoSource(e,t,n),s.push(t)}catch(e){this.recordSourceError(t.id,e,n,s,i)}return{finalOptions:s,errors:i}}async processSingleVideoSource(e,r,t){const{id:a,url:n,layout:s}=r,i=t.get(a);if(i){let r;i.url!==n&&(r=await this.core.utils.loadVideo(n)),e.updateVideoSource(a,s,r)}else{const r=await this.core.utils.loadVideo(n);e.addVideoSource(a,r,s)}}createPlaceholderVideoTrack(){const e=document.createElement("canvas");e.width=1,e.height=1;const r=e.getContext("2d");if(!r){return e.captureStream(30).getVideoTracks()[0]}let t=null;const a=1e3/30,n=e.captureStream(30).getVideoTracks()[0],s=()=>{r.fillStyle="rgba(0, 0, 0, 0)",r.fillRect(0,0,e.width,e.height),"live"===n.readyState&&(t=setTimeout(s,a))};s();const i=n.stop.bind(n);return n.stop=()=>{t&&(clearTimeout(t),t=null),i()},n}removeEventListeners(e){const r=this.eventListeners.get(e);r&&(r.captureSuccess&&r.captureSuccess(),r.trackStop&&r.trackStop(),this.eventListeners.delete(e))}async captureCamera(e){const{id:r,cameraId:t,videoTrack:a,profile:n}=e,s=new this.core.LocalVideoTrack;s.log.id+=`-${r}`;const i={};if(t?i.deviceId=t:this.core.utils.isUndefined(a)||(i.customSource=a),!this.core.utils.isUndefined(n)){const e=this.resolveVideoProfile(n);e&&s.setProfile(e)}return await s.capture(i),s}async updateCameraProfile(e){var r;const{id:t,cameraId:a,videoTrack:n,profile:s}=e,i=null==(r=this.localMixVideoTrack)?void 0:r.inputLocalVideoTracks.get(t);if(i&&(a?await i.switchDevice(a):this.core.utils.isUndefined(n)||await i.setInputMediaStreamTrack(n),!this.core.utils.isUndefined(s))){const e=this.resolveVideoProfile(s);e&&i.setProfile(e),a&&i.isNeedToSwitchDevice(a)||await i.applyProfile()}}async captureScreen(e){const{id:r,profile:t,captureElement:a,preferDisplaySurface:n,systemAudio:s,videoTrack:i,audioTrack:o}=e,c=new this.core.LocalScreenTrack;c.log.id+=`-${r}`;const d={captureElement:a,preferDisplaySurface:n,systemAudio:s,videoTrack:i,audioTrack:o};if(!this.core.utils.isUndefined(t))if(this.core.utils.isString(t)){const e=this.core.constants.screenProfileMap[t];e&&c.setProfile(e)}else c.setProfile(t);const l=await c.capture(d);return s&&l.getAudioTracks().length>0?(this.systemAudioTrackList[r]=l.getAudioTracks()[0],this.log.info(`${r} system audio track captured`)):this.removeSystemAudioTrack(r),c.mediaTrack.addEventListener(this.core.constants.NAME.ENDED,()=>{this.handleScreenShareEnded(r)}),c}handleScreenShareEnded(e){var r,t,a;null==(r=this.localMixVideoTrack)||r.removeScreenSource(e),(null==(t=this._mixVideoConfig)?void 0:t.screen)&&(this._mixVideoConfig.screen=this._mixVideoConfig.screen.filter(r=>r.id!==e)),null==(a=this.onScreenShareStop)||a.call(this,e)}async _updatePreview({view:e,track:r,prevConfig:t}){if(this.core.utils.isUndefined(e)&&(null==t?void 0:t.view)){const e=this.core.utils.getViewListFromView(t.view);return void(e.length>0&&await r.play(e))}if(!this.core.utils.isUndefined(e)){const t=this.core.utils.getViewListFromView(e);t.length>0?await r.play(t):r.stop()}}removeSystemAudioTrack(e){const r=this.systemAudioTrackList[e];r&&(r.stop(),this.log.info(`${e} system audio track stop`),delete this.systemAudioTrackList[e])}};__publicField(_VideoMixer,"Name","VideoMixer");var VideoMixer=_VideoMixer,index_default=VideoMixer;export{index_default as default};export{VideoMixer};