@vosjs/studio-core 0.35.4 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6396,6 +6396,21 @@ var FRAME_STEP_SRC = `
6396
6396
  }
6397
6397
  function stepBg(bgEl, bgT) {
6398
6398
  if (!bgEl.paused) bgEl.pause()
6399
+ // Capture pages: the loop's frame by PTS from its own provider, like the
6400
+ // footage. The loop clock only moves forward between wraps, so the walk
6401
+ // stays sequential and a wrap is one re-seek to the keyframe at 0.
6402
+ var bwc = bgEl.__voilaWc
6403
+ if (bwc) {
6404
+ var bwT = Math.min(bgT, bwc.duration || bgT)
6405
+ if (bwc.req !== bwT) {
6406
+ var bwp = bwc.seek(bwT)
6407
+ if (ns.pendingDecodes) {
6408
+ ns.pendingDecodes.add(bwp)
6409
+ bwp.finally(function () { ns.pendingDecodes.delete(bwp) })
6410
+ }
6411
+ }
6412
+ return
6413
+ }
6399
6414
  var bgTarget = Math.min(bgT, bgEl.duration || bgT)
6400
6415
  if (bgEl.readyState >= 1 && !bgEl.seeking && Math.abs(bgEl.currentTime - bgTarget) > 0.02) {
6401
6416
  if (ns.pendingDecodes) {
@@ -6479,6 +6494,7 @@ var SETUP = `async (ctx) => {
6479
6494
  // page has a memory budget) and FAIL-OPEN: any fetch trouble degrades to
6480
6495
  // the plain network element, never a dead LOAD.
6481
6496
  const BLOB_FETCH_MAX = 400 * 1024 * 1024
6497
+ const BG_BLOB_MAX = 64 * 1024 * 1024
6482
6498
  const toBlobUrl = async (src) => {
6483
6499
  const resp = await fetch(src)
6484
6500
  if (!resp.ok) throw new Error('[voila] blob fetch HTTP ' + resp.status)
@@ -6679,9 +6695,48 @@ var SETUP = `async (ctx) => {
6679
6695
  if (bgm && bgm.key) {
6680
6696
  try {
6681
6697
  if (bgm.kind === 'image') await loadImage(bgm.key)
6682
- else (await load(bgm.key, true)).loop = true
6698
+ else {
6699
+ const bgV = await load(bgm.key, true)
6700
+ bgV.loop = true
6701
+ // Capture pages: the loop gets its own provider. An element seek
6702
+ // decodes from the previous keyframe on EVERY frame (a baked loop
6703
+ // has one every few seconds), and the capture waits for it; the
6704
+ // sequential walk decodes each packet once. The whole loop is read
6705
+ // into a Blob first when it is small enough (one request instead
6706
+ // of ranged reads against a CDN). FAIL-OPEN to the element at
6707
+ // every step, like the footage.
6708
+ if (ctx.data.videoDecodeMode === 'webcodecs' && !bgV.__voilaWc) {
6709
+ try {
6710
+ if (!(ns.videoBlobs && ns.videoBlobs.get(bgm.key)) && bgm.key.indexOf('blob:') !== 0 && bgm.key.indexOf('data:') !== 0) {
6711
+ try {
6712
+ const bgResp = await fetch(bgm.key)
6713
+ const bgLen = Number(bgResp.headers.get('content-length') || 0)
6714
+ if (bgResp.ok && bgLen <= BG_BLOB_MAX) {
6715
+ ;(ns.videoBlobs || (ns.videoBlobs = new Map())).set(bgm.key, await bgResp.blob())
6716
+ } else {
6717
+ try { if (bgResp.body) await bgResp.body.cancel() } catch (e) { void e }
6718
+ }
6719
+ } catch (e) { void e }
6720
+ }
6721
+ const bgWc = await makeWcProvider(bgm.key)
6722
+ if (bgWc && (!bgV.videoWidth || (bgWc.width === bgV.videoWidth && bgWc.height === bgV.videoHeight))) bgV.__voilaWc = bgWc
6723
+ } catch (e) {
6724
+ console.warn('[voila] webcodecs provider unavailable for the background, seeks stay html5', e)
6725
+ }
6726
+ }
6727
+ }
6683
6728
  } catch (e) { console.warn('[voila] background media failed to load', e) }
6684
6729
  }
6730
+ // Which path decodes what, for a host's telemetry: 'provider' is the
6731
+ // sequential WebCodecs walk, 'element' an HTMLVideoElement seek per frame.
6732
+ ns.voilaDecode = {
6733
+ recording: ctx.data.isImage ? 'none' : video.__voilaWc ? 'provider' : 'element',
6734
+ backdrop: (function () {
6735
+ if (!bgm || !bgm.key || bgm.kind === 'image') return 'none'
6736
+ const bgHit = cache.get(bgm.key)
6737
+ return bgHit && bgHit.__voilaWc ? 'provider' : 'element'
6738
+ })(),
6739
+ }
6685
6740
  // Frame prep: a capture harness calls every ns.framePrep hook right after
6686
6741
  // seeking the timeline and before the first paint, then awaits
6687
6742
  // waitForVideosReady. The footage for the frame is requested HERE, so the
@@ -7310,7 +7365,14 @@ var ON_FRAME = `(ctx, content, dt) => {
7310
7365
  // Blur: softens the media behind the card (design px \xD7 s).
7311
7366
  var bgBlur = bgm.blur || 0
7312
7367
  if (bgBlur > 0 && bgC.filter !== undefined) bgC.filter = 'blur(' + bgBlur * s + 'px)'
7313
- try { bgC.drawImage(bgEl, (W - bgDw) / 2 + bgOx, (H - bgDh) / 2 + bgOy, bgDw, bgDh) } catch (e) {}
7368
+ // The loop's provider draws its current sample (paused capture
7369
+ // pages); false \u21D2 the element (playback, or before the first ask).
7370
+ try {
7371
+ var bgWcp = !bgIsImg && !playing ? bgEl.__voilaWc : null
7372
+ if (!(bgWcp && bgWcp.draw(bgC, null, (W - bgDw) / 2 + bgOx, (H - bgDh) / 2 + bgOy, bgDw, bgDh))) {
7373
+ bgC.drawImage(bgEl, (W - bgDw) / 2 + bgOx, (H - bgDh) / 2 + bgOy, bgDw, bgDh)
7374
+ }
7375
+ } catch (e) {}
7314
7376
  if (bgBlur > 0 && bgC.filter !== undefined) bgC.filter = 'none'
7315
7377
  var bgDim = bgm.dim || 0
7316
7378
  if (bgDim > 0) {