@webav/av-canvas
Version:
Combine Text, Image, Video, Audio, UserMedia, DisplayMedia to generate MediaStream. With [AVRcorder](../av-recorder/README.md) you can output MP4 streams and save them as local files or push them to the server.
710 lines (709 loc) • 23.6 kB
JavaScript
var Ct = Object.defineProperty;
var St = (i) => {
throw TypeError(i);
};
var Mt = (i, t, e) => t in i ? Ct(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
var V = (i, t, e) => Mt(i, typeof t != "symbol" ? t + "" : t, e), at = (i, t, e) => t.has(i) || St("Cannot " + e);
var r = (i, t, e) => (at(i, t, "read from private field"), e ? e.call(i) : t.get(i)), m = (i, t, e) => t.has(i) ? St("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(i) : t.set(i, e), M = (i, t, e, n) => (at(i, t, "write to private field"), n ? n.call(i, e) : t.set(i, e), e), $ = (i, t, e) => (at(i, t, "access private method"), e);
import { Rect as E, Log as q, MediaStreamClip as Rt, Combinator as At, OffscreenSprite as Tt } from "@webav/av-cliper";
import { EventTool as lt, debounce as zt, workerTimer as Lt } from "@webav/internal-utils";
const it = [
"t",
"b",
"l",
"r",
"lt",
"lb",
"rt",
"rb",
"rotate"
];
function F(i) {
return document.createElement(i);
}
const ct = /* @__PURE__ */ new WeakMap();
function yt(i, t) {
if (ct.has(i))
return ct.get(i)(t);
let e = 10;
new ResizeObserver((o) => {
const h = o[0];
h != null && (e = 10 / (h.contentRect.width / i.width));
}).observe(i);
function s(o) {
const { w: h, h: d } = o, a = e, c = a / 2, l = h / 2, p = d / 2, f = a * 1.5, u = f / 2;
return {
...o.fixedAspectRatio ? {} : {
t: new E(-c, -p - c, a, a, o),
b: new E(-c, p - c, a, a, o),
l: new E(-l - c, -c, a, a, o),
r: new E(l - c, -c, a, a, o)
},
lt: new E(-l - c, -p - c, a, a, o),
lb: new E(-l - c, p - c, a, a, o),
rt: new E(l - c, -p - c, a, a, o),
rb: new E(l - c, p - c, a, a, o),
rotate: new E(-u, -p - a * 2 - u, f, f, o)
};
}
return ct.set(i, s), s(t);
}
const ht = /* @__PURE__ */ new WeakMap();
function K(i) {
if (ht.has(i))
return ht.get(i);
const t = {
w: i.clientWidth / i.width,
h: i.clientHeight / i.height
};
return new ResizeObserver(() => {
t.w = i.clientWidth / i.width, t.h = i.clientHeight / i.height;
}).observe(i), ht.set(i, t), t;
}
var U = /* @__PURE__ */ ((i) => (i.ActiveSpriteChange = "activeSpriteChange", i.AddSprite = "addSprite", i))(U || {}), R, j, B, X;
class Et {
constructor() {
m(this, R, []);
m(this, j, null);
m(this, B, new lt());
V(this, "on", r(this, B).on);
m(this, X, 0);
}
get activeSprite() {
return r(this, j);
}
set activeSprite(t) {
t !== r(this, j) && (M(this, j, t), r(this, B).emit("activeSpriteChange", t));
}
activeSpriteByCoord(t, e) {
this.activeSprite = this.getSprites().reverse().find((n) => n.visible && n.rect.checkHit(t, e)) ?? null;
}
async addSprite(t) {
await t.ready, r(this, R).push(t), M(this, R, r(this, R).sort((e, n) => e.zIndex - n.zIndex)), t.on("propsChange", (e) => {
e.zIndex != null && M(this, R, r(this, R).sort((n, s) => n.zIndex - s.zIndex));
}), r(this, B).emit("addSprite", t);
}
removeSprite(t) {
r(this, j) === t && (this.activeSprite = null), M(this, R, r(this, R).filter((e) => e !== t)), t.destroy();
}
getSprites(t = { time: !0 }) {
return r(this, R).filter(
(e) => e.visible && (t.time ? r(this, X) >= e.time.offset && r(this, X) <= e.time.offset + e.time.duration : !0)
);
}
updateRenderTime(t) {
M(this, X, t);
const e = this.activeSprite;
e != null && (t < e.time.offset || t > e.time.offset + e.time.duration) && (this.activeSprite = null);
}
destroy() {
r(this, B).destroy(), r(this, R).forEach((t) => t.destroy()), M(this, R, []);
}
}
R = new WeakMap(), j = new WeakMap(), B = new WeakMap(), X = new WeakMap();
function Ot(i, t, e) {
const n = K(t), s = new ResizeObserver(() => {
e.activeSprite != null && dt(e.activeSprite, t, h, d);
});
s.observe(t);
let o = () => {
};
const { rectEl: h, ctrlsEl: d } = kt(i);
h.addEventListener("pointerdown", (c) => {
if (Object.values(d).includes(c.target))
return;
const l = t.getBoundingClientRect(), p = (c.clientX - l.left) / n.w, f = (c.clientY - l.top) / n.h;
e.activeSpriteByCoord(p, f);
});
const a = e.on(U.ActiveSpriteChange, (c) => {
if (o(), c == null) {
h.style.display = "none";
return;
}
dt(c, t, h, d), o = c.on("propsChange", () => {
dt(c, t, h, d);
}), h.style.display = "";
});
return () => {
s.disconnect(), a(), h.remove(), o();
};
}
function kt(i) {
const t = F("div");
t.classList.add("sprite-rect"), t.style.cssText = `
position: absolute;
z-index: 3;
pointer-events: auto;
border: 1px solid #eee;
box-sizing: border-box;
display: none;
cursor: move;
`;
const e = Object.fromEntries(
it.map((n) => {
const s = F("div");
return s.classList.add(`ctrl-key-${n}`), s.style.cssText = `
display: none;
position: absolute;
border: 1px solid #3ee; border-radius: 50%;
box-sizing: border-box;
background-color: #fff;
pointer-events: auto;
cursor: ${n === "rotate" ? "crosshair" : "default"};
user-select: none;
`, [n, s];
})
);
return Object.values(e).forEach((n) => t.appendChild(n)), i.appendChild(t), {
rectEl: t,
ctrlsEl: e
};
}
function dt(i, t, e, n) {
const s = K(t), { x: o, y: h, w: d, h: a, angle: c } = i.rect;
Object.assign(e.style, {
left: `${o * s.w}px`,
top: `${h * s.h}px`,
width: `${d * s.w}px`,
height: `${a * s.h}px`,
rotate: `${c}rad`
}), Object.entries(yt(t, i.rect)).forEach(([l, { x: p, y: f, w: u, h: w }]) => {
Object.assign(n[l].style, {
display: "block",
left: "50%",
top: "50%",
width: `${u * s.w}px`,
height: `${w * s.h}px`,
// border 1px, 所以要 -1
transform: `translate(${p * s.w}px, ${f * s.h}px)`
});
});
}
function It(i, t) {
const e = (n) => {
if (n.button !== 0 || n.target !== i) return;
const s = K(i), { offsetX: o, offsetY: h } = n, d = o / s.w, a = h / s.h;
t.activeSpriteByCoord(d, a);
};
return i.addEventListener("pointerdown", e), () => {
i.removeEventListener("pointerdown", e);
};
}
function $t(i, t, e) {
let n = 0, s = 0, o = null;
const h = Ht(i, e), d = e.querySelector(".sprite-rect");
if (!d) throw Error("sprite-rect DOM Node not found");
const a = (u) => {
if (u.button !== 0 || t.activeSprite == null) return;
const w = t.activeSprite, { clientX: x, clientY: z } = u;
o = w.rect.clone(), h.magneticEffect(w.rect.x, w.rect.y, w.rect), n = x, s = z, window.addEventListener("pointermove", l), window.addEventListener("pointerup", p), u.stopPropagation();
}, c = K(i), l = (u) => {
if (t.activeSprite == null || o == null) return;
const { clientX: w, clientY: x } = u;
let z = o.x + (w - n) / c.w, S = o.y + (x - s) / c.h;
vt(
t.activeSprite.rect,
i,
h.magneticEffect(z, S, t.activeSprite.rect)
);
}, p = () => {
h.hide(), window.removeEventListener("pointermove", l), window.removeEventListener("pointerup", p);
};
d.addEventListener("pointerdown", a), i.addEventListener("pointerdown", a);
const f = Wt(i, d, t);
return () => {
h.destroy(), p(), d.removeEventListener("pointerdown", a), i.removeEventListener("pointerdown", a), f();
};
}
function Wt(i, t, e) {
const n = Array.from(t.children), s = K(i);
n.forEach((c, l) => {
const p = it[l];
c.addEventListener("pointerdown", (f) => {
if (f.button !== 0 || e.activeSprite == null) return;
const { clientX: u, clientY: w } = f;
p === "rotate" ? jt(
e.activeSprite.rect,
Bt(e.activeSprite.rect.center, s, i)
) : Pt({
sprRect: e.activeSprite.rect,
ctrlKey: p,
startX: u,
startY: w,
cvsRatio: s,
cvsEl: i
}), f.stopPropagation();
});
}), n[it.indexOf("rotate")].style.cursor = "crosshair";
const o = [
"ns-resize",
"nesw-resize",
"ew-resize",
"nwse-resize",
"ns-resize",
"nesw-resize",
"ew-resize",
"nwse-resize"
], h = {
t: 0,
rt: 1,
r: 2,
rb: 3,
b: 4,
lb: 5,
l: 6,
lt: 7
};
let d = () => {
};
const a = e.on(U.ActiveSpriteChange, (c) => {
if (d(), c == null) return;
const l = zt(function() {
const { angle: p } = c.rect, f = p < 0 ? p + 2 * Math.PI : p;
n.forEach((u, w) => {
const x = it[w];
if (x === "rotate") return;
const z = (h[x] + Math.floor((f + Math.PI / 8) / (Math.PI / 4))) % 8;
u.style.cursor = o[z];
});
}, 300);
d = c.on("propsChange", (p) => {
var f;
((f = p.rect) == null ? void 0 : f.angle) != null && l();
}), l();
});
return () => {
d(), a();
};
}
function Pt({
sprRect: i,
startX: t,
startY: e,
ctrlKey: n,
cvsRatio: s,
cvsEl: o
}) {
const h = i.clone(), d = (c) => {
const { clientX: l, clientY: p } = c, f = (l - t) / s.w, u = (p - e) / s.h, w = n.length === 1 ? Dt : Yt, { x, y: z, w: S, h: g } = h, N = Math.atan2(g, S), { incW: pt, incH: ft, incS: D, rotateAngle: ut } = w({
deltaX: f,
deltaY: u,
angle: i.angle,
ctrlKey: n,
diagonalAngle: N
}), C = 10;
let L = S, Y = g, tt = h.fixedScaleCenter ? pt * 2 : pt, et = h.fixedScaleCenter ? ft * 2 : ft, I = D;
const wt = Math.sqrt(g ** 2 + S ** 2), mt = Math.sqrt((C * (g / S)) ** 2 + C ** 2);
switch (n) {
case "l":
L = Math.max(S + tt, C), I = Math.min(D, S - C);
break;
case "r":
L = Math.max(S + tt, C), I = Math.max(D, C - S);
break;
case "b":
Y = Math.max(g + et, C), I = Math.min(D, g - C);
break;
case "t":
Y = Math.max(g + et, C), I = Math.max(D, C - g);
break;
case "lt":
case "lb":
L = Math.max(S + tt, C), Y = L === C ? g / S * L : g + et, I = Math.min(D, wt - mt);
break;
case "rt":
case "rb":
L = Math.max(S + tt, C), Y = L === C ? g / S * L : g + et, I = Math.max(D, mt - wt);
break;
}
let st = x, ot = z;
if (h.fixedScaleCenter)
st = x + S / 2 - L / 2, ot = z + g / 2 - Y / 2;
else {
const bt = I / 2 * Math.cos(ut) + x + S / 2, gt = I / 2 * Math.sin(ut) + z + g / 2;
st = bt - L / 2, ot = gt - Y / 2;
}
vt(i, o, {
x: st,
y: ot,
w: L,
h: Y
});
}, a = () => {
window.removeEventListener("pointermove", d), window.removeEventListener("pointerup", a);
};
window.addEventListener("pointermove", d), window.addEventListener("pointerup", a);
}
function Dt({
deltaX: i,
deltaY: t,
angle: e,
ctrlKey: n
}) {
let s = 0, o = 0, h = 0, d = e;
return n === "l" || n === "r" ? (s = i * Math.cos(e) + t * Math.sin(e), o = s * (n === "l" ? -1 : 1)) : (n === "t" || n === "b") && (d = e - Math.PI / 2, s = i * Math.cos(d) + t * Math.sin(d), h = s * (n === "b" ? -1 : 1)), { incW: o, incH: h, incS: s, rotateAngle: d };
}
function Yt({
deltaX: i,
deltaY: t,
angle: e,
ctrlKey: n,
diagonalAngle: s
}) {
const o = (n === "lt" || n === "rb" ? 1 : -1) * s + e, h = i * Math.cos(o) + t * Math.sin(o), d = n === "lt" || n === "lb" ? -1 : 1, a = h * Math.cos(s) * d, c = h * Math.sin(s) * d;
return { incW: a, incH: c, incS: h, rotateAngle: o };
}
function jt(i, t) {
const e = ({ clientX: s, clientY: o }) => {
const h = s - t.x, d = o - t.y, a = Math.atan2(d, h) + Math.PI / 2;
i.angle = a;
}, n = () => {
window.removeEventListener("pointermove", e), window.removeEventListener("pointerup", n);
};
window.addEventListener("pointermove", e), window.addEventListener("pointerup", n);
}
function Bt(i, t, e) {
const n = i.x * t.w, s = i.y * t.h, { left: o, top: h } = e.getBoundingClientRect();
return {
x: n + o,
y: s + h
};
}
function vt(i, t, e) {
const n = { x: i.x, y: i.y, w: i.w, h: i.h, ...e }, s = t.width * 0.05, o = t.height * 0.05;
n.x < -n.w + s ? n.x = -n.w + s : n.x > t.width - s && (n.x = t.width - s), n.y < -n.h + o ? n.y = -n.h + o : n.y > t.height - o && (n.y = t.height - o), i.x = n.x, i.y = n.y, i.w = n.w, i.h = n.h;
}
function Ht(i, t) {
const e = "display: none; position: absolute;", n = { w: 0, h: 0, x: 0, y: 0 }, s = {
vertMiddle: {
...n,
h: 100,
x: 50,
ref: { prop: "x", val: ({ w: a }) => (i.width - a) / 2 }
},
horMiddle: {
...n,
w: 100,
y: 50,
ref: { prop: "y", val: ({ h: a }) => (i.height - a) / 2 }
},
top: {
...n,
w: 100,
ref: { prop: "y", val: () => 0 }
},
bottom: {
...n,
w: 100,
y: 100,
ref: { prop: "y", val: ({ h: a }) => i.height - a }
},
left: {
...n,
h: 100,
ref: { prop: "x", val: () => 0 }
},
right: {
...n,
h: 100,
x: 100,
ref: { prop: "x", val: ({ w: a }) => i.width - a }
}
}, o = F("div");
o.style.cssText = `
position: absolute;
z-index: 4;
top: 0; left: 0;
width: 100%; height: 100%;
pointer-events: none;
box-sizing: border-box;
`;
const h = Object.fromEntries(
Object.entries(s).map(([a, { w: c, h: l, x: p, y: f }]) => {
const u = F("div");
return u.style.cssText = `
${e}
border-${c > 0 ? "top" : "left"}: 1px solid #3ee;
top: ${f}%; left: ${p}%;
${p === 100 ? "margin-left: -1px" : ""};
${f === 100 ? "margin-top: -1px" : ""};
width: ${c}%; height: ${l}%;
`, o.appendChild(u), [a, u];
})
);
t.appendChild(o);
const d = 6 / (900 / i.width);
return {
magneticEffect(a, c, l) {
const p = { x: a, y: c }, f = { x: d, y: d }, u = { x: "", y: "" };
Object.values(h).forEach((w) => w.style.display = "none");
for (const w in s) {
const { prop: x, val: z } = s[w].ref, S = z(l), N = Math.abs((x === "x" ? a : c) - S);
N <= d && N < f[x] && (f[x] = N, p[x] = S, u[x] = w);
}
return u.x && (h[u.x].style.display = "block"), u.y && (h[u.y].style.display = "block"), p;
},
hide() {
Object.values(h).forEach((a) => a.style.display = "none");
},
destroy() {
o.remove();
}
};
}
const Xt = {
sampleRate: 48e3,
channelCount: 2,
codec: "mp4a.40.2"
};
function Ft(i) {
const t = F("canvas");
return t.style.cssText = `
width: 100%;
height: 100%;
display: block;
touch-action: none;
`, t.width = i.width, t.height = i.height, t;
}
var v, y, H, _, G, J, O, Q, k, T, nt, rt, b, W, P, xt, A, Z;
class Gt {
/**
* 创建 `AVCanvas` 类的实例。
* @param attchEl - 要添加画布的元素。
* @param opts - 画布的选项
* @param opts.bgColor - 画布的背景颜色。
* @param opts.width - 画布的宽度。
* @param opts.height - 画布的高度。
*/
constructor(t, e) {
m(this, T);
m(this, v);
m(this, y);
m(this, H);
m(this, _, !1);
m(this, G, []);
m(this, J);
m(this, O, new lt());
V(this, "on", r(this, O).on);
m(this, Q);
m(this, k, 0);
m(this, b, new AudioContext());
m(this, W, r(this, b).createMediaStreamDestination());
m(this, P, /* @__PURE__ */ new Set());
m(this, A, {
start: 0,
end: 0,
// paused state when step equal 0
step: 0,
// step: (1000 / 30) * 1000,
audioPlayAt: 0
});
m(this, Z, /* @__PURE__ */ new WeakMap());
/**
* 添加 {@link VisibleSprite}
* @param args {@link VisibleSprite}
* @example
* const sprite = new VisibleSprite(
* new ImgClip({
* type: 'image/gif',
* stream: (await fetch('https://xx.gif')).body!,
* }),
* );
*/
V(this, "addSprite", async (t) => {
r(this, b).state === "suspended" && r(this, b).resume().catch(q.error);
const e = t.getClip();
if (e instanceof Rt && e.audioTrack != null) {
const n = r(this, b).createMediaStreamSource(
new MediaStream([e.audioTrack])
);
n.connect(r(this, W)), r(this, Z).set(t, n);
}
await r(this, y).addSprite(t), t.preFrame(0);
});
/**
* 删除 {@link VisibleSprite}
* @param args
* @returns
* @example
* const sprite = new VisibleSprite();
* avCvs.removeSprite(sprite);
*/
V(this, "removeSprite", (t) => {
var e;
(e = r(this, Z).get(t)) == null || e.disconnect(), r(this, y).removeSprite(t);
});
M(this, Q, e), M(this, v, Ft(e));
const n = r(this, v).getContext("2d", { alpha: !1 });
if (n == null) throw Error("canvas context is null");
M(this, H, n);
const s = F("div");
s.style.cssText = "width: 100%; height: 100%; position: relative;", s.appendChild(r(this, v)), t.appendChild(s), Vt(r(this, b)).connect(r(this, W)), yt(r(this, v), { x: 0, y: 0, w: 0, h: 0 }), M(this, y, new Et()), r(this, G).push(
// 鼠标样式、控制 sprite 依赖 activeSprite,
// activeSprite 需要在他们之前监听到 mousedown 事件 (代码顺序需要靠前)
It(r(this, v), r(this, y)),
Ot(s, r(this, v), r(this, y)),
$t(r(this, v), r(this, y), s),
r(this, y).on(U.AddSprite, (c) => {
const { rect: l } = c;
l.x === 0 && l.y === 0 && (l.x = (r(this, v).width - l.w) / 2, l.y = (r(this, v).height - l.h) / 2);
}),
lt.forwardEvent(r(this, y), r(this, O), [
U.ActiveSpriteChange
])
);
let o = r(this, k), h = performance.now(), d = 0;
const a = 1e3 / 30;
M(this, J, Lt(() => {
(performance.now() - h) / (a * d) < 1 || (d += 1, r(this, H).fillStyle = e.bgColor, r(this, H).fillRect(0, 0, r(this, v).width, r(this, v).height), $(this, T, xt).call(this), o !== r(this, k) && (o = r(this, k), r(this, O).emit("timeupdate", Math.round(o))));
}, a));
}
/**
* 每 33ms 更新一次画布,绘制已添加的 Sprite
* @param opts - 播放选项
* @param opts.start - 开始播放的时间(单位:微秒)
* @param [opts.end] - 结束播放的时间(单位:微秒)。如果未指定,则播放到最后一个 Sprite 的结束时间
* @param [opts.playbackRate] - 播放速率。1 表示正常速度,2 表示两倍速度,0.5 表示半速等。如果未指定,则默认为 1
* @throws 如果开始时间大于等于结束时间或小于 0,则抛出错误
*/
play(t) {
const e = r(this, y).getSprites({ time: !1 }).map((s) => s.time.offset + s.time.duration), n = t.end ?? (e.length > 0 ? Math.max(...e) : 1 / 0);
if (t.start >= n || t.start < 0)
throw Error(
`Invalid time parameter, ${JSON.stringify({ start: t.start, end: n })}`
);
$(this, T, nt).call(this, t.start), r(this, y).getSprites({ time: !1 }).forEach((s) => {
const { offset: o, duration: h } = s.time, d = r(this, k) - o;
s.preFrame(d > 0 && d < h ? d : 0);
}), r(this, A).start = t.start, r(this, A).end = n, r(this, A).step = (t.playbackRate ?? 1) * (1e3 / 30) * 1e3, r(this, b).resume(), r(this, A).audioPlayAt = 0, r(this, O).emit("playing"), q.info("AVCanvs play by:", r(this, A));
}
/**
* 暂停播放,画布内容不再更新
*/
pause() {
$(this, T, rt).call(this);
}
/**
* 预览 `AVCanvas` 指定时间的图像帧
*/
previewFrame(t) {
$(this, T, nt).call(this, t), $(this, T, rt).call(this);
}
/**
* 获取当前帧的截图图像 返回的是一个base64
*/
captureImage() {
return r(this, v).toDataURL();
}
get activeSprite() {
return r(this, y).activeSprite;
}
set activeSprite(t) {
r(this, y).activeSprite = t;
}
/**
* 销毁实例
*/
destroy() {
var t;
r(this, _) || (M(this, _, !0), r(this, b).close(), r(this, W).disconnect(), r(this, O).destroy(), r(this, J).call(this), (t = r(this, v).parentElement) == null || t.remove(), r(this, G).forEach((e) => e()), r(this, P).clear(), r(this, y).destroy());
}
/**
* 合成所有素材的图像与音频,返回实时媒体流 `MediaStream`
*
* 可用于 WebRTC 推流,或由 {@link [AVRecorder](../../av-recorder/classes/AVRecorder.html)} 录制生成视频文件
*
* @see [直播录制](https://webav-tech.github.io/WebAV/demo/4_2-recorder-avcanvas)
*
*/
captureStream() {
r(this, b).state === "suspended" && r(this, b).resume().catch(q.error);
const t = new MediaStream(
r(this, v).captureStream().getTracks().concat(r(this, W).stream.getTracks())
);
return q.info(
"AVCanvas.captureStream, tracks:",
t.getTracks().map((e) => e.kind)
), t;
}
/**
* 创建一个视频合成器 {@link [Combinator](../../av-cliper/classes/Combinator.html)} 实例,用于将当前画布添加的 Sprite 导出为视频文件流
*
* @param opts - 创建 Combinator 的可选参数
* @throws 如果没有添加素材,会抛出错误
*
* @example
* avCvs.createCombinator().output() // => ReadableStream
*
* @see [视频剪辑](https://webav-tech.github.io/WebAV/demo/6_4-video-editor)
*/
async createCombinator(t = {}) {
q.info("AVCanvas.createCombinator, opts:", t);
const e = new At({ ...r(this, Q), ...t }), n = r(this, y).getSprites({ time: !1 });
if (n.length === 0) throw Error("No sprite added");
for (const s of n) {
const o = new Tt(s.getClip());
o.time = { ...s.time }, s.copyStateTo(o), await e.addSprite(o);
}
return e;
}
}
v = new WeakMap(), y = new WeakMap(), H = new WeakMap(), _ = new WeakMap(), G = new WeakMap(), J = new WeakMap(), O = new WeakMap(), Q = new WeakMap(), k = new WeakMap(), T = new WeakSet(), nt = function(t) {
M(this, k, t), r(this, y).updateRenderTime(t);
}, rt = function() {
const t = r(this, A).step !== 0;
r(this, A).step = 0, t && (r(this, O).emit("paused"), r(this, b).suspend());
for (const e of r(this, P))
e.stop(), e.disconnect();
r(this, P).clear();
}, b = new WeakMap(), W = new WeakMap(), P = new WeakMap(), xt = function() {
var a;
const t = r(this, H);
let e = r(this, k);
const { start: n, end: s, step: o, audioPlayAt: h } = r(this, A);
o !== 0 && e >= n && e < s ? e += o : $(this, T, rt).call(this), $(this, T, nt).call(this, e);
const d = [];
for (const c of r(this, y).getSprites()) {
t.save();
const { audio: l } = c.render(t, e - c.time.offset);
t.restore(), d.push(l);
}
if (t.resetTransform(), o !== 0) {
const c = Math.max(r(this, b).currentTime, h), l = Nt(
d,
r(this, b)
);
let p = 0;
for (const f of l)
f.start(c), f.connect(r(this, b).destination), f.connect(r(this, W)), r(this, P).add(f), f.onended = () => {
f.disconnect(), r(this, P).delete(f);
}, p = Math.max(p, ((a = f.buffer) == null ? void 0 : a.duration) ?? 0);
r(this, A).audioPlayAt = c + p;
}
}, A = new WeakMap(), Z = new WeakMap();
function Nt(i, t) {
const e = [];
if (i.length === 0) return e;
for (const [n, s] of i) {
if (n == null || n.length <= 0) continue;
const o = t.createBuffer(
2,
n.length,
Xt.sampleRate
);
o.copyToChannel(n, 0), o.copyToChannel(s ?? n, 1);
const h = t.createBufferSource();
h.buffer = o, e.push(h);
}
return e;
}
function Vt(i) {
const t = i.createOscillator(), e = new Float32Array([0, 0]), n = new Float32Array([0, 0]), s = i.createPeriodicWave(e, n, {
disableNormalization: !0
});
return t.setPeriodicWave(s), t.start(), t;
}
export {
Gt as AVCanvas
};
//# sourceMappingURL=av-canvas.js.map