@alpha-video-kit/svg 0.1.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.cjs ADDED
@@ -0,0 +1,51 @@
1
+ "use strict";var K=Object.defineProperty;var P=s=>{throw TypeError(s)};var N=(s,i,e)=>i in s?K(s,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[i]=e;var j=(s,i,e)=>N(s,typeof i!="symbol"?i+"":i,e),q=(s,i,e)=>i.has(s)||P("Cannot "+e);var t=(s,i,e)=>(q(s,i,"read from private field"),e?e.call(s):i.get(s)),v=(s,i,e)=>i.has(s)?P("Cannot add the same private member more than once"):i instanceof WeakSet?i.add(s):i.set(s,e),o=(s,i,e,d)=>(q(s,i,"write to private field"),d?d.call(s,e):i.set(s,e),e),h=(s,i,e)=>(q(s,i,"access private method"),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function T(s){const{canvas:i}=s,e=i.getContext("2d"),d=document.createElement("canvas"),y=d.getContext("2d");let c=!1;function L(w,a,n,p){return`<svg xmlns="http://www.w3.org/2000/svg"
2
+ xmlns:xlink="http://www.w3.org/1999/xlink"
3
+ width="${a}" height="${n}"
4
+ viewBox="0 0 ${a} ${n}">
5
+ <defs>
6
+ <filter id="r2a" color-interpolation-filters="sRGB">
7
+ <feColorMatrix type="matrix"
8
+ values="0 0 0 0 1
9
+ 0 0 0 0 1
10
+ 0 0 0 0 1
11
+ 1 0 0 0 0"/>
12
+ </filter>
13
+ <mask id="alphaMask">
14
+ <svg viewBox="0 ${n} ${a} ${n}"
15
+ width="${a}" height="${n}"
16
+ preserveAspectRatio="none">
17
+ <image href="${w}"
18
+ width="${a}" height="${p}"
19
+ filter="url(#r2a)"/>
20
+ </svg>
21
+ </mask>
22
+ </defs>
23
+ <svg viewBox="0 0 ${a} ${n}"
24
+ width="${a}" height="${n}"
25
+ preserveAspectRatio="none"
26
+ mask="url(#alphaMask)">
27
+ <image href="${w}"
28
+ width="${a}" height="${p}"/>
29
+ </svg>
30
+ </svg>`}return{drawFrame(w){if(c)return;const a=w.videoWidth,n=w.videoHeight,p=Math.floor(n/2);(i.width!==a||i.height!==p)&&(i.width=a,i.height=p),(d.width!==a||d.height!==n)&&(d.width=a,d.height=n),y.drawImage(w,0,0);const x=d.toDataURL("image/png"),S=L(x,a,p,n),E=new Blob([S],{type:"image/svg+xml"}),u=URL.createObjectURL(E),F=new Image;F.onload=()=>{if(c){URL.revokeObjectURL(u);return}e.clearRect(0,0,a,p),e.drawImage(F,0,0),URL.revokeObjectURL(u)},F.src=u},setPremultipliedAlpha(w){},destroy(){c||(c=!0)},get isDestroyed(){return c}}}function _(s){const{canvas:i,premultipliedAlpha:e=!1}=s,d=i.getContext("2d",{willReadFrequently:!0}),y=document.createElement("canvas"),c=y.getContext("2d",{willReadFrequently:!0});let L=!1,w=e;return{drawFrame(a){if(L)return;const n=a.videoWidth,p=a.videoHeight,x=Math.floor(p/2);(i.width!==n||i.height!==x)&&(i.width=n,i.height=x),(y.width!==n||y.height!==p)&&(y.width=n,y.height=p),c.drawImage(a,0,0);const S=c.getImageData(0,0,n,x),E=c.getImageData(0,x,n,x),u=S.data,F=E.data;for(let m=0;m<u.length;m+=4){const I=F[m];if(w)u[m+3]=I;else{const O=I/255;u[m]=Math.round(u[m]*O),u[m+1]=Math.round(u[m+1]*O),u[m+2]=Math.round(u[m+2]*O),u[m+3]=I}}d.putImageData(S,0,0)},setPremultipliedAlpha(a){w=a},destroy(){L||(L=!0)},get isDestroyed(){return L}}}function G(s){const{mode:i="canvas",...e}=s;return i==="svg-filter"?T(e):_(e)}var M,g,l,b,R,A,k,C,r,$,H,Q,D,f,z,U,V,J,B;class W extends HTMLElement{constructor(){super();v(this,r);v(this,M);v(this,g,null);v(this,l,null);v(this,b,null);v(this,R,null);v(this,A,null);v(this,k,!1);v(this,C,!1);v(this,f,()=>{h(this,r,$).call(this)});const e=this.attachShadow({mode:"open"});e.innerHTML=`
31
+ <style>
32
+ :host {
33
+ display: inline-block;
34
+ position: relative;
35
+ }
36
+ canvas {
37
+ display: block;
38
+ width: 100%;
39
+ height: 100%;
40
+ }
41
+ ::slotted(video) {
42
+ position: absolute;
43
+ opacity: 0;
44
+ pointer-events: none;
45
+ width: 0;
46
+ height: 0;
47
+ }
48
+ </style>
49
+ <canvas></canvas>
50
+ <slot></slot>
51
+ `,o(this,M,e.querySelector("canvas"))}get premultipliedAlpha(){return this.hasAttribute("premultipliedalpha")}set premultipliedAlpha(e){e?this.setAttribute("premultipliedalpha",""):this.removeAttribute("premultipliedalpha")}attributeChangedCallback(e,d,y){var c;e==="premultipliedalpha"&&((c=t(this,g))==null||c.setPremultipliedAlpha(this.premultipliedAlpha)),e==="mode"&&(h(this,r,U).call(this),h(this,r,$).call(this))}connectedCallback(){o(this,R,new IntersectionObserver(([e])=>{o(this,k,e.isIntersecting),h(this,r,$).call(this)},{threshold:0})),t(this,R).observe(this),o(this,A,new MutationObserver(()=>h(this,r,$).call(this))),t(this,A).observe(this,{childList:!0}),h(this,r,$).call(this)}disconnectedCallback(){var e,d;(e=t(this,R))==null||e.disconnect(),o(this,R,null),(d=t(this,A))==null||d.disconnect(),o(this,A,null),h(this,r,D).call(this),h(this,r,U).call(this)}}M=new WeakMap,g=new WeakMap,l=new WeakMap,b=new WeakMap,R=new WeakMap,A=new WeakMap,k=new WeakMap,C=new WeakMap,r=new WeakSet,$=function(){t(this,C)||(o(this,C,!0),queueMicrotask(()=>{o(this,C,!1),h(this,r,H).call(this)}))},H=function(){const e=this.querySelector("video");e!==t(this,l)&&(h(this,r,D).call(this),o(this,l,e),e&&h(this,r,Q).call(this,e)),t(this,k)&&t(this,l)?(h(this,r,z).call(this),h(this,r,V).call(this),h(this,r,J).call(this)):h(this,r,B).call(this)},Q=function(e){e.addEventListener("play",t(this,f)),e.addEventListener("pause",t(this,f)),e.addEventListener("seeked",t(this,f)),e.addEventListener("loadeddata",t(this,f))},D=function(){t(this,l)&&(t(this,l).removeEventListener("play",t(this,f)),t(this,l).removeEventListener("pause",t(this,f)),t(this,l).removeEventListener("seeked",t(this,f)),t(this,l).removeEventListener("loadeddata",t(this,f)),o(this,l,null),h(this,r,B).call(this))},f=new WeakMap,z=function(){if(t(this,g)&&!t(this,g).isDestroyed)return;const e=this.getAttribute("mode")??"canvas";o(this,g,G({canvas:t(this,M),premultipliedAlpha:this.premultipliedAlpha,mode:e}))},U=function(){var e;(e=t(this,g))==null||e.destroy(),o(this,g,null)},V=function(){!t(this,g)||!t(this,l)||t(this,l).readyState<2||t(this,g).drawFrame(t(this,l))},J=function(){if(t(this,b)!==null||!t(this,l)||t(this,l).paused)return;const e=()=>{h(this,r,V).call(this),t(this,l)&&!t(this,l).paused&&t(this,k)?o(this,b,requestAnimationFrame(e)):o(this,b,null)};o(this,b,requestAnimationFrame(e))},B=function(){t(this,b)!==null&&(cancelAnimationFrame(t(this,b)),o(this,b,null))},j(W,"observedAttributes",["premultipliedalpha","mode"]);exports.StackedAlphaVideoSVG=W;exports.createCanvasFilterRenderer=_;exports.createRenderer=G;exports.createSvgFilterRenderer=T;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Canvas 2D renderer with pixel manipulation.
3
+ * Draws the video to an offscreen canvas, reads pixels from top and bottom halves,
4
+ * applies alpha from the bottom half to the top half's color data.
5
+ * No SVG filters used — pure Canvas 2D fallback for maximum compatibility.
6
+ */
7
+ export declare function createCanvasFilterRenderer(options: StackedAlphaRendererOptions): StackedAlphaRenderer;
8
+
9
+ export declare function createRenderer(options: SvgRendererOptions): StackedAlphaRenderer;
10
+
11
+ /**
12
+ * Pure SVG filter renderer.
13
+ * Renders each frame by drawing the video to a temporary canvas to get a data URL,
14
+ * then uses an SVG with filter-based alpha extraction and masking.
15
+ */
16
+ export declare function createSvgFilterRenderer(options: StackedAlphaRendererOptions): StackedAlphaRenderer;
17
+
18
+ export declare interface StackedAlphaRenderer {
19
+ drawFrame(video: HTMLVideoElement): void;
20
+ setPremultipliedAlpha(value: boolean): void;
21
+ destroy(): void;
22
+ readonly isDestroyed: boolean;
23
+ }
24
+
25
+ export declare interface StackedAlphaRendererOptions {
26
+ canvas: HTMLCanvasElement | OffscreenCanvas;
27
+ premultipliedAlpha?: boolean;
28
+ }
29
+
30
+ export declare class StackedAlphaVideoSVG extends HTMLElement {
31
+ #private;
32
+ static observedAttributes: string[];
33
+ constructor();
34
+ get premultipliedAlpha(): boolean;
35
+ set premultipliedAlpha(value: boolean);
36
+ attributeChangedCallback(name: string, _oldValue: string | null, _newValue: string | null): void;
37
+ connectedCallback(): void;
38
+ disconnectedCallback(): void;
39
+ }
40
+
41
+ export declare type SvgRendererMode = 'svg-filter' | 'canvas';
42
+
43
+ export declare interface SvgRendererOptions extends StackedAlphaRendererOptions {
44
+ mode?: SvgRendererMode;
45
+ }
46
+
47
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,203 @@
1
+ var H = Object.defineProperty;
2
+ var P = (s) => {
3
+ throw TypeError(s);
4
+ };
5
+ var Q = (s, i, t) => i in s ? H(s, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[i] = t;
6
+ var j = (s, i, t) => Q(s, typeof i != "symbol" ? i + "" : i, t), O = (s, i, t) => i.has(s) || P("Cannot " + t);
7
+ var e = (s, i, t) => (O(s, i, "read from private field"), t ? t.call(s) : i.get(s)), v = (s, i, t) => i.has(s) ? P("Cannot add the same private member more than once") : i instanceof WeakSet ? i.add(s) : i.set(s, t), o = (s, i, t, d) => (O(s, i, "write to private field"), d ? d.call(s, t) : i.set(s, t), t), l = (s, i, t) => (O(s, i, "access private method"), t);
8
+ function z(s) {
9
+ const { canvas: i } = s, t = i.getContext("2d"), d = document.createElement("canvas"), y = d.getContext("2d");
10
+ let c = !1;
11
+ function $(w, a, n, p) {
12
+ return `<svg xmlns="http://www.w3.org/2000/svg"
13
+ xmlns:xlink="http://www.w3.org/1999/xlink"
14
+ width="${a}" height="${n}"
15
+ viewBox="0 0 ${a} ${n}">
16
+ <defs>
17
+ <filter id="r2a" color-interpolation-filters="sRGB">
18
+ <feColorMatrix type="matrix"
19
+ values="0 0 0 0 1
20
+ 0 0 0 0 1
21
+ 0 0 0 0 1
22
+ 1 0 0 0 0"/>
23
+ </filter>
24
+ <mask id="alphaMask">
25
+ <svg viewBox="0 ${n} ${a} ${n}"
26
+ width="${a}" height="${n}"
27
+ preserveAspectRatio="none">
28
+ <image href="${w}"
29
+ width="${a}" height="${p}"
30
+ filter="url(#r2a)"/>
31
+ </svg>
32
+ </mask>
33
+ </defs>
34
+ <svg viewBox="0 0 ${a} ${n}"
35
+ width="${a}" height="${n}"
36
+ preserveAspectRatio="none"
37
+ mask="url(#alphaMask)">
38
+ <image href="${w}"
39
+ width="${a}" height="${p}"/>
40
+ </svg>
41
+ </svg>`;
42
+ }
43
+ return {
44
+ drawFrame(w) {
45
+ if (c) return;
46
+ const a = w.videoWidth, n = w.videoHeight, p = Math.floor(n / 2);
47
+ (i.width !== a || i.height !== p) && (i.width = a, i.height = p), (d.width !== a || d.height !== n) && (d.width = a, d.height = n), y.drawImage(w, 0, 0);
48
+ const x = d.toDataURL("image/png"), F = $(x, a, p, n), I = new Blob([F], { type: "image/svg+xml" }), u = URL.createObjectURL(I), M = new Image();
49
+ M.onload = () => {
50
+ if (c) {
51
+ URL.revokeObjectURL(u);
52
+ return;
53
+ }
54
+ t.clearRect(0, 0, a, p), t.drawImage(M, 0, 0), URL.revokeObjectURL(u);
55
+ }, M.src = u;
56
+ },
57
+ setPremultipliedAlpha(w) {
58
+ },
59
+ destroy() {
60
+ c || (c = !0);
61
+ },
62
+ get isDestroyed() {
63
+ return c;
64
+ }
65
+ };
66
+ }
67
+ function J(s) {
68
+ const { canvas: i, premultipliedAlpha: t = !1 } = s, d = i.getContext("2d", { willReadFrequently: !0 }), y = document.createElement("canvas"), c = y.getContext("2d", { willReadFrequently: !0 });
69
+ let $ = !1, w = t;
70
+ return {
71
+ drawFrame(a) {
72
+ if ($) return;
73
+ const n = a.videoWidth, p = a.videoHeight, x = Math.floor(p / 2);
74
+ (i.width !== n || i.height !== x) && (i.width = n, i.height = x), (y.width !== n || y.height !== p) && (y.width = n, y.height = p), c.drawImage(a, 0, 0);
75
+ const F = c.getImageData(0, 0, n, x), I = c.getImageData(0, x, n, x), u = F.data, M = I.data;
76
+ for (let m = 0; m < u.length; m += 4) {
77
+ const q = M[m];
78
+ if (w)
79
+ u[m + 3] = q;
80
+ else {
81
+ const D = q / 255;
82
+ u[m] = Math.round(u[m] * D), u[m + 1] = Math.round(u[m + 1] * D), u[m + 2] = Math.round(u[m + 2] * D), u[m + 3] = q;
83
+ }
84
+ }
85
+ d.putImageData(F, 0, 0);
86
+ },
87
+ setPremultipliedAlpha(a) {
88
+ w = a;
89
+ },
90
+ destroy() {
91
+ $ || ($ = !0);
92
+ },
93
+ get isDestroyed() {
94
+ return $;
95
+ }
96
+ };
97
+ }
98
+ function K(s) {
99
+ const { mode: i = "canvas", ...t } = s;
100
+ return i === "svg-filter" ? z(t) : J(t);
101
+ }
102
+ var E, g, h, b, L, A, k, C, r, R, _, T, S, f, W, U, V, G, B;
103
+ class N extends HTMLElement {
104
+ constructor() {
105
+ super();
106
+ v(this, r);
107
+ v(this, E);
108
+ v(this, g, null);
109
+ v(this, h, null);
110
+ v(this, b, null);
111
+ v(this, L, null);
112
+ v(this, A, null);
113
+ v(this, k, !1);
114
+ v(this, C, !1);
115
+ v(this, f, () => {
116
+ l(this, r, R).call(this);
117
+ });
118
+ const t = this.attachShadow({ mode: "open" });
119
+ t.innerHTML = `
120
+ <style>
121
+ :host {
122
+ display: inline-block;
123
+ position: relative;
124
+ }
125
+ canvas {
126
+ display: block;
127
+ width: 100%;
128
+ height: 100%;
129
+ }
130
+ ::slotted(video) {
131
+ position: absolute;
132
+ opacity: 0;
133
+ pointer-events: none;
134
+ width: 0;
135
+ height: 0;
136
+ }
137
+ </style>
138
+ <canvas></canvas>
139
+ <slot></slot>
140
+ `, o(this, E, t.querySelector("canvas"));
141
+ }
142
+ get premultipliedAlpha() {
143
+ return this.hasAttribute("premultipliedalpha");
144
+ }
145
+ set premultipliedAlpha(t) {
146
+ t ? this.setAttribute("premultipliedalpha", "") : this.removeAttribute("premultipliedalpha");
147
+ }
148
+ attributeChangedCallback(t, d, y) {
149
+ var c;
150
+ t === "premultipliedalpha" && ((c = e(this, g)) == null || c.setPremultipliedAlpha(this.premultipliedAlpha)), t === "mode" && (l(this, r, U).call(this), l(this, r, R).call(this));
151
+ }
152
+ connectedCallback() {
153
+ o(this, L, new IntersectionObserver(
154
+ ([t]) => {
155
+ o(this, k, t.isIntersecting), l(this, r, R).call(this);
156
+ },
157
+ { threshold: 0 }
158
+ )), e(this, L).observe(this), o(this, A, new MutationObserver(() => l(this, r, R).call(this))), e(this, A).observe(this, { childList: !0 }), l(this, r, R).call(this);
159
+ }
160
+ disconnectedCallback() {
161
+ var t, d;
162
+ (t = e(this, L)) == null || t.disconnect(), o(this, L, null), (d = e(this, A)) == null || d.disconnect(), o(this, A, null), l(this, r, S).call(this), l(this, r, U).call(this);
163
+ }
164
+ }
165
+ E = new WeakMap(), g = new WeakMap(), h = new WeakMap(), b = new WeakMap(), L = new WeakMap(), A = new WeakMap(), k = new WeakMap(), C = new WeakMap(), r = new WeakSet(), R = function() {
166
+ e(this, C) || (o(this, C, !0), queueMicrotask(() => {
167
+ o(this, C, !1), l(this, r, _).call(this);
168
+ }));
169
+ }, _ = function() {
170
+ const t = this.querySelector("video");
171
+ t !== e(this, h) && (l(this, r, S).call(this), o(this, h, t), t && l(this, r, T).call(this, t)), e(this, k) && e(this, h) ? (l(this, r, W).call(this), l(this, r, V).call(this), l(this, r, G).call(this)) : l(this, r, B).call(this);
172
+ }, T = function(t) {
173
+ t.addEventListener("play", e(this, f)), t.addEventListener("pause", e(this, f)), t.addEventListener("seeked", e(this, f)), t.addEventListener("loadeddata", e(this, f));
174
+ }, S = function() {
175
+ e(this, h) && (e(this, h).removeEventListener("play", e(this, f)), e(this, h).removeEventListener("pause", e(this, f)), e(this, h).removeEventListener("seeked", e(this, f)), e(this, h).removeEventListener("loadeddata", e(this, f)), o(this, h, null), l(this, r, B).call(this));
176
+ }, f = new WeakMap(), W = function() {
177
+ if (e(this, g) && !e(this, g).isDestroyed) return;
178
+ const t = this.getAttribute("mode") ?? "canvas";
179
+ o(this, g, K({
180
+ canvas: e(this, E),
181
+ premultipliedAlpha: this.premultipliedAlpha,
182
+ mode: t
183
+ }));
184
+ }, U = function() {
185
+ var t;
186
+ (t = e(this, g)) == null || t.destroy(), o(this, g, null);
187
+ }, V = function() {
188
+ !e(this, g) || !e(this, h) || e(this, h).readyState < 2 || e(this, g).drawFrame(e(this, h));
189
+ }, G = function() {
190
+ if (e(this, b) !== null || !e(this, h) || e(this, h).paused) return;
191
+ const t = () => {
192
+ l(this, r, V).call(this), e(this, h) && !e(this, h).paused && e(this, k) ? o(this, b, requestAnimationFrame(t)) : o(this, b, null);
193
+ };
194
+ o(this, b, requestAnimationFrame(t));
195
+ }, B = function() {
196
+ e(this, b) !== null && (cancelAnimationFrame(e(this, b)), o(this, b, null));
197
+ }, j(N, "observedAttributes", ["premultipliedalpha", "mode"]);
198
+ export {
199
+ N as StackedAlphaVideoSVG,
200
+ J as createCanvasFilterRenderer,
201
+ K as createRenderer,
202
+ z as createSvgFilterRenderer
203
+ };
@@ -0,0 +1 @@
1
+ "use strict";const e=require("./index.cjs");customElements.get("stacked-alpha-video-svg")||customElements.define("stacked-alpha-video-svg",e.StackedAlphaVideoSVG);
@@ -0,0 +1 @@
1
+ export { }
@@ -0,0 +1,2 @@
1
+ import { StackedAlphaVideoSVG as e } from "./index.js";
2
+ customElements.get("stacked-alpha-video-svg") || customElements.define("stacked-alpha-video-svg", e);
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@alpha-video-kit/svg",
3
+ "version": "0.1.0",
4
+ "description": "SVG filter-based renderer for stacked alpha videos",
5
+ "type": "module",
6
+ "files": ["dist"],
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ },
16
+ "./register": {
17
+ "import": "./dist/register.js",
18
+ "require": "./dist/register.cjs"
19
+ }
20
+ },
21
+ "scripts": {
22
+ "build": "vite build",
23
+ "typecheck": "tsc --noEmit",
24
+ "test": "vitest run",
25
+ "clean": "rm -rf dist"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^5.6.0",
29
+ "vite": "^6.0.0",
30
+ "vite-plugin-dts": "^4.0.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/stepancar/alpha-video-kit",
39
+ "directory": "packages/svg"
40
+ }
41
+ }