@shotstack/shotstack-canvas 1.3.0 → 1.3.2
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/entry.node.cjs +63 -6
- package/dist/entry.node.js +63 -6
- package/dist/entry.web.js +46 -5
- package/package.json +1 -1
package/dist/entry.node.cjs
CHANGED
|
@@ -179,29 +179,69 @@ function bufferToArrayBuffer(buffer) {
|
|
|
179
179
|
}
|
|
180
180
|
return arrayBuffer;
|
|
181
181
|
}
|
|
182
|
-
|
|
182
|
+
var DEFAULT_WASM_URL = "https://shotstack-ingest-api-dev-sources.s3.ap-southeast-2.amazonaws.com/euo5r93oyr/zzz01k9h-yycyx-2x2y6-qx9bj-7n567b/source.wasm";
|
|
183
|
+
async function fetchWasmFromUrl(url) {
|
|
184
|
+
try {
|
|
185
|
+
const response = await fetch(url);
|
|
186
|
+
if (response.ok) {
|
|
187
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
188
|
+
const bytes = new Uint8Array(arrayBuffer);
|
|
189
|
+
if (bytes.length >= 4 && bytes[0] === 0 && bytes[1] === 97 && bytes[2] === 115 && bytes[3] === 109) {
|
|
190
|
+
console.log(`\u2705 Fetched WASM from URL (${bytes.length} bytes)`);
|
|
191
|
+
return arrayBuffer;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return void 0;
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.warn(`Failed to fetch WASM from ${url}:`, err);
|
|
197
|
+
return void 0;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function loadWasmNode(wasmBaseURL) {
|
|
183
201
|
try {
|
|
184
202
|
const { readFile: readFile2 } = await import("fs/promises");
|
|
185
203
|
const { fileURLToPath } = await import("url");
|
|
186
204
|
const path = await import("path");
|
|
205
|
+
const { createRequire } = await import("module");
|
|
187
206
|
const currentDir = path.dirname(fileURLToPath(import_meta.url));
|
|
207
|
+
let harfbuzzWasmPath;
|
|
208
|
+
try {
|
|
209
|
+
const require2 = createRequire(import_meta.url);
|
|
210
|
+
const harfbuzzPkgPath = require2.resolve("harfbuzzjs/package.json");
|
|
211
|
+
const harfbuzzDir = path.dirname(harfbuzzPkgPath);
|
|
212
|
+
harfbuzzWasmPath = path.join(harfbuzzDir, "hb.wasm");
|
|
213
|
+
} catch {
|
|
214
|
+
}
|
|
188
215
|
const candidates = [
|
|
216
|
+
// First try the harfbuzzjs package location (resolved via require)
|
|
217
|
+
...harfbuzzWasmPath ? [harfbuzzWasmPath] : [],
|
|
218
|
+
// Lambda environment paths
|
|
219
|
+
"/var/task/node_modules/harfbuzzjs/hb.wasm",
|
|
220
|
+
"/var/task/node_modules/@shotstack/shotstack-canvas/assets/wasm/hb.wasm",
|
|
221
|
+
// Relative paths from current directory
|
|
189
222
|
path.join(currentDir, "../../dist/hb.wasm"),
|
|
190
223
|
path.join(currentDir, "../dist/hb.wasm"),
|
|
191
224
|
path.join(currentDir, "../../assets/wasm/hb.wasm"),
|
|
192
225
|
path.join(currentDir, "../assets/wasm/hb.wasm"),
|
|
193
226
|
path.join(currentDir, "./hb.wasm"),
|
|
194
|
-
path.join(currentDir, "../hb.wasm")
|
|
227
|
+
path.join(currentDir, "../hb.wasm"),
|
|
228
|
+
// node_modules relative paths
|
|
229
|
+
path.join(currentDir, "../../node_modules/harfbuzzjs/hb.wasm"),
|
|
230
|
+
path.join(currentDir, "../../../node_modules/harfbuzzjs/hb.wasm"),
|
|
231
|
+
path.join(currentDir, "../../../../node_modules/harfbuzzjs/hb.wasm")
|
|
195
232
|
];
|
|
196
233
|
for (const candidate of candidates) {
|
|
197
234
|
try {
|
|
198
235
|
const buffer = await readFile2(candidate);
|
|
236
|
+
console.log(`\u2705 Found WASM at: ${candidate}`);
|
|
199
237
|
return bufferToArrayBuffer(buffer);
|
|
200
238
|
} catch {
|
|
201
239
|
continue;
|
|
202
240
|
}
|
|
203
241
|
}
|
|
204
|
-
|
|
242
|
+
console.log("Local WASM not found, fetching from URL...");
|
|
243
|
+
const urlToFetch = wasmBaseURL || DEFAULT_WASM_URL;
|
|
244
|
+
return await fetchWasmFromUrl(urlToFetch);
|
|
205
245
|
} catch {
|
|
206
246
|
return void 0;
|
|
207
247
|
}
|
|
@@ -273,7 +313,7 @@ async function initHB(wasmBaseURL) {
|
|
|
273
313
|
try {
|
|
274
314
|
let wasmBinary;
|
|
275
315
|
if (isNode()) {
|
|
276
|
-
wasmBinary = await loadWasmNode();
|
|
316
|
+
wasmBinary = await loadWasmNode(wasmBaseURL);
|
|
277
317
|
} else {
|
|
278
318
|
wasmBinary = await loadWasmWeb(wasmBaseURL);
|
|
279
319
|
}
|
|
@@ -1377,11 +1417,27 @@ async function createNodePainter(opts) {
|
|
|
1377
1417
|
const c = parseHex6(color, opacity);
|
|
1378
1418
|
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1379
1419
|
if (radius && radius > 0) {
|
|
1420
|
+
needsAlphaExtraction = true;
|
|
1421
|
+
ctx.save();
|
|
1422
|
+
ctx.fillStyle = "rgb(255, 255, 255)";
|
|
1423
|
+
ctx.fillRect(0, 0, op.width, op.height);
|
|
1424
|
+
ctx.restore();
|
|
1425
|
+
offscreenCtx.save();
|
|
1426
|
+
offscreenCtx.fillStyle = "rgb(0, 0, 0)";
|
|
1427
|
+
offscreenCtx.fillRect(0, 0, op.width, op.height);
|
|
1428
|
+
offscreenCtx.restore();
|
|
1380
1429
|
ctx.save();
|
|
1430
|
+
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1381
1431
|
ctx.beginPath();
|
|
1382
1432
|
roundRectPath(ctx, 0, 0, op.width, op.height, radius);
|
|
1383
1433
|
ctx.fill();
|
|
1384
1434
|
ctx.restore();
|
|
1435
|
+
offscreenCtx.save();
|
|
1436
|
+
offscreenCtx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1437
|
+
offscreenCtx.beginPath();
|
|
1438
|
+
roundRectPath(offscreenCtx, 0, 0, op.width, op.height, radius);
|
|
1439
|
+
offscreenCtx.fill();
|
|
1440
|
+
offscreenCtx.restore();
|
|
1385
1441
|
} else {
|
|
1386
1442
|
ctx.fillRect(0, 0, op.width, op.height);
|
|
1387
1443
|
}
|
|
@@ -2107,9 +2163,10 @@ async function createTextEngine(opts = {}) {
|
|
|
2107
2163
|
try {
|
|
2108
2164
|
const hasBackground = !!asset.background?.color;
|
|
2109
2165
|
const hasAnimation = !!asset.animation?.preset;
|
|
2110
|
-
const
|
|
2166
|
+
const hasBorderRadius = (asset.background?.borderRadius ?? 0) > 0;
|
|
2167
|
+
const needsAlpha = !hasBackground && hasAnimation || hasBorderRadius;
|
|
2111
2168
|
console.log(
|
|
2112
|
-
`\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, Alpha=${needsAlpha}`
|
|
2169
|
+
`\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, BorderRadius=${hasBorderRadius}, Alpha=${needsAlpha}`
|
|
2113
2170
|
);
|
|
2114
2171
|
const finalOptions = {
|
|
2115
2172
|
width: asset.width ?? width,
|
package/dist/entry.node.js
CHANGED
|
@@ -140,29 +140,69 @@ function bufferToArrayBuffer(buffer) {
|
|
|
140
140
|
}
|
|
141
141
|
return arrayBuffer;
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
var DEFAULT_WASM_URL = "https://shotstack-ingest-api-dev-sources.s3.ap-southeast-2.amazonaws.com/euo5r93oyr/zzz01k9h-yycyx-2x2y6-qx9bj-7n567b/source.wasm";
|
|
144
|
+
async function fetchWasmFromUrl(url) {
|
|
145
|
+
try {
|
|
146
|
+
const response = await fetch(url);
|
|
147
|
+
if (response.ok) {
|
|
148
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
149
|
+
const bytes = new Uint8Array(arrayBuffer);
|
|
150
|
+
if (bytes.length >= 4 && bytes[0] === 0 && bytes[1] === 97 && bytes[2] === 115 && bytes[3] === 109) {
|
|
151
|
+
console.log(`\u2705 Fetched WASM from URL (${bytes.length} bytes)`);
|
|
152
|
+
return arrayBuffer;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return void 0;
|
|
156
|
+
} catch (err) {
|
|
157
|
+
console.warn(`Failed to fetch WASM from ${url}:`, err);
|
|
158
|
+
return void 0;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function loadWasmNode(wasmBaseURL) {
|
|
144
162
|
try {
|
|
145
163
|
const { readFile: readFile2 } = await import("fs/promises");
|
|
146
164
|
const { fileURLToPath } = await import("url");
|
|
147
165
|
const path = await import("path");
|
|
166
|
+
const { createRequire } = await import("module");
|
|
148
167
|
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
168
|
+
let harfbuzzWasmPath;
|
|
169
|
+
try {
|
|
170
|
+
const require2 = createRequire(import.meta.url);
|
|
171
|
+
const harfbuzzPkgPath = require2.resolve("harfbuzzjs/package.json");
|
|
172
|
+
const harfbuzzDir = path.dirname(harfbuzzPkgPath);
|
|
173
|
+
harfbuzzWasmPath = path.join(harfbuzzDir, "hb.wasm");
|
|
174
|
+
} catch {
|
|
175
|
+
}
|
|
149
176
|
const candidates = [
|
|
177
|
+
// First try the harfbuzzjs package location (resolved via require)
|
|
178
|
+
...harfbuzzWasmPath ? [harfbuzzWasmPath] : [],
|
|
179
|
+
// Lambda environment paths
|
|
180
|
+
"/var/task/node_modules/harfbuzzjs/hb.wasm",
|
|
181
|
+
"/var/task/node_modules/@shotstack/shotstack-canvas/assets/wasm/hb.wasm",
|
|
182
|
+
// Relative paths from current directory
|
|
150
183
|
path.join(currentDir, "../../dist/hb.wasm"),
|
|
151
184
|
path.join(currentDir, "../dist/hb.wasm"),
|
|
152
185
|
path.join(currentDir, "../../assets/wasm/hb.wasm"),
|
|
153
186
|
path.join(currentDir, "../assets/wasm/hb.wasm"),
|
|
154
187
|
path.join(currentDir, "./hb.wasm"),
|
|
155
|
-
path.join(currentDir, "../hb.wasm")
|
|
188
|
+
path.join(currentDir, "../hb.wasm"),
|
|
189
|
+
// node_modules relative paths
|
|
190
|
+
path.join(currentDir, "../../node_modules/harfbuzzjs/hb.wasm"),
|
|
191
|
+
path.join(currentDir, "../../../node_modules/harfbuzzjs/hb.wasm"),
|
|
192
|
+
path.join(currentDir, "../../../../node_modules/harfbuzzjs/hb.wasm")
|
|
156
193
|
];
|
|
157
194
|
for (const candidate of candidates) {
|
|
158
195
|
try {
|
|
159
196
|
const buffer = await readFile2(candidate);
|
|
197
|
+
console.log(`\u2705 Found WASM at: ${candidate}`);
|
|
160
198
|
return bufferToArrayBuffer(buffer);
|
|
161
199
|
} catch {
|
|
162
200
|
continue;
|
|
163
201
|
}
|
|
164
202
|
}
|
|
165
|
-
|
|
203
|
+
console.log("Local WASM not found, fetching from URL...");
|
|
204
|
+
const urlToFetch = wasmBaseURL || DEFAULT_WASM_URL;
|
|
205
|
+
return await fetchWasmFromUrl(urlToFetch);
|
|
166
206
|
} catch {
|
|
167
207
|
return void 0;
|
|
168
208
|
}
|
|
@@ -234,7 +274,7 @@ async function initHB(wasmBaseURL) {
|
|
|
234
274
|
try {
|
|
235
275
|
let wasmBinary;
|
|
236
276
|
if (isNode()) {
|
|
237
|
-
wasmBinary = await loadWasmNode();
|
|
277
|
+
wasmBinary = await loadWasmNode(wasmBaseURL);
|
|
238
278
|
} else {
|
|
239
279
|
wasmBinary = await loadWasmWeb(wasmBaseURL);
|
|
240
280
|
}
|
|
@@ -1338,11 +1378,27 @@ async function createNodePainter(opts) {
|
|
|
1338
1378
|
const c = parseHex6(color, opacity);
|
|
1339
1379
|
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1340
1380
|
if (radius && radius > 0) {
|
|
1381
|
+
needsAlphaExtraction = true;
|
|
1382
|
+
ctx.save();
|
|
1383
|
+
ctx.fillStyle = "rgb(255, 255, 255)";
|
|
1384
|
+
ctx.fillRect(0, 0, op.width, op.height);
|
|
1385
|
+
ctx.restore();
|
|
1386
|
+
offscreenCtx.save();
|
|
1387
|
+
offscreenCtx.fillStyle = "rgb(0, 0, 0)";
|
|
1388
|
+
offscreenCtx.fillRect(0, 0, op.width, op.height);
|
|
1389
|
+
offscreenCtx.restore();
|
|
1341
1390
|
ctx.save();
|
|
1391
|
+
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1342
1392
|
ctx.beginPath();
|
|
1343
1393
|
roundRectPath(ctx, 0, 0, op.width, op.height, radius);
|
|
1344
1394
|
ctx.fill();
|
|
1345
1395
|
ctx.restore();
|
|
1396
|
+
offscreenCtx.save();
|
|
1397
|
+
offscreenCtx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1398
|
+
offscreenCtx.beginPath();
|
|
1399
|
+
roundRectPath(offscreenCtx, 0, 0, op.width, op.height, radius);
|
|
1400
|
+
offscreenCtx.fill();
|
|
1401
|
+
offscreenCtx.restore();
|
|
1346
1402
|
} else {
|
|
1347
1403
|
ctx.fillRect(0, 0, op.width, op.height);
|
|
1348
1404
|
}
|
|
@@ -2068,9 +2124,10 @@ async function createTextEngine(opts = {}) {
|
|
|
2068
2124
|
try {
|
|
2069
2125
|
const hasBackground = !!asset.background?.color;
|
|
2070
2126
|
const hasAnimation = !!asset.animation?.preset;
|
|
2071
|
-
const
|
|
2127
|
+
const hasBorderRadius = (asset.background?.borderRadius ?? 0) > 0;
|
|
2128
|
+
const needsAlpha = !hasBackground && hasAnimation || hasBorderRadius;
|
|
2072
2129
|
console.log(
|
|
2073
|
-
`\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, Alpha=${needsAlpha}`
|
|
2130
|
+
`\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, BorderRadius=${hasBorderRadius}, Alpha=${needsAlpha}`
|
|
2074
2131
|
);
|
|
2075
2132
|
const finalOptions = {
|
|
2076
2133
|
width: asset.width ?? width,
|
package/dist/entry.web.js
CHANGED
|
@@ -144,29 +144,69 @@ function bufferToArrayBuffer(buffer) {
|
|
|
144
144
|
}
|
|
145
145
|
return arrayBuffer;
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
var DEFAULT_WASM_URL = "https://shotstack-ingest-api-dev-sources.s3.ap-southeast-2.amazonaws.com/euo5r93oyr/zzz01k9h-yycyx-2x2y6-qx9bj-7n567b/source.wasm";
|
|
148
|
+
async function fetchWasmFromUrl(url) {
|
|
149
|
+
try {
|
|
150
|
+
const response = await fetch(url);
|
|
151
|
+
if (response.ok) {
|
|
152
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
153
|
+
const bytes = new Uint8Array(arrayBuffer);
|
|
154
|
+
if (bytes.length >= 4 && bytes[0] === 0 && bytes[1] === 97 && bytes[2] === 115 && bytes[3] === 109) {
|
|
155
|
+
console.log(`\u2705 Fetched WASM from URL (${bytes.length} bytes)`);
|
|
156
|
+
return arrayBuffer;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return void 0;
|
|
160
|
+
} catch (err) {
|
|
161
|
+
console.warn(`Failed to fetch WASM from ${url}:`, err);
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function loadWasmNode(wasmBaseURL) {
|
|
148
166
|
try {
|
|
149
167
|
const { readFile } = await import("fs/promises");
|
|
150
168
|
const { fileURLToPath } = await import("url");
|
|
151
169
|
const path = await import("path");
|
|
170
|
+
const { createRequire } = await import("module");
|
|
152
171
|
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
172
|
+
let harfbuzzWasmPath;
|
|
173
|
+
try {
|
|
174
|
+
const require2 = createRequire(import.meta.url);
|
|
175
|
+
const harfbuzzPkgPath = require2.resolve("harfbuzzjs/package.json");
|
|
176
|
+
const harfbuzzDir = path.dirname(harfbuzzPkgPath);
|
|
177
|
+
harfbuzzWasmPath = path.join(harfbuzzDir, "hb.wasm");
|
|
178
|
+
} catch {
|
|
179
|
+
}
|
|
153
180
|
const candidates = [
|
|
181
|
+
// First try the harfbuzzjs package location (resolved via require)
|
|
182
|
+
...harfbuzzWasmPath ? [harfbuzzWasmPath] : [],
|
|
183
|
+
// Lambda environment paths
|
|
184
|
+
"/var/task/node_modules/harfbuzzjs/hb.wasm",
|
|
185
|
+
"/var/task/node_modules/@shotstack/shotstack-canvas/assets/wasm/hb.wasm",
|
|
186
|
+
// Relative paths from current directory
|
|
154
187
|
path.join(currentDir, "../../dist/hb.wasm"),
|
|
155
188
|
path.join(currentDir, "../dist/hb.wasm"),
|
|
156
189
|
path.join(currentDir, "../../assets/wasm/hb.wasm"),
|
|
157
190
|
path.join(currentDir, "../assets/wasm/hb.wasm"),
|
|
158
191
|
path.join(currentDir, "./hb.wasm"),
|
|
159
|
-
path.join(currentDir, "../hb.wasm")
|
|
192
|
+
path.join(currentDir, "../hb.wasm"),
|
|
193
|
+
// node_modules relative paths
|
|
194
|
+
path.join(currentDir, "../../node_modules/harfbuzzjs/hb.wasm"),
|
|
195
|
+
path.join(currentDir, "../../../node_modules/harfbuzzjs/hb.wasm"),
|
|
196
|
+
path.join(currentDir, "../../../../node_modules/harfbuzzjs/hb.wasm")
|
|
160
197
|
];
|
|
161
198
|
for (const candidate of candidates) {
|
|
162
199
|
try {
|
|
163
200
|
const buffer = await readFile(candidate);
|
|
201
|
+
console.log(`\u2705 Found WASM at: ${candidate}`);
|
|
164
202
|
return bufferToArrayBuffer(buffer);
|
|
165
203
|
} catch {
|
|
166
204
|
continue;
|
|
167
205
|
}
|
|
168
206
|
}
|
|
169
|
-
|
|
207
|
+
console.log("Local WASM not found, fetching from URL...");
|
|
208
|
+
const urlToFetch = wasmBaseURL || DEFAULT_WASM_URL;
|
|
209
|
+
return await fetchWasmFromUrl(urlToFetch);
|
|
170
210
|
} catch {
|
|
171
211
|
return void 0;
|
|
172
212
|
}
|
|
@@ -238,7 +278,7 @@ async function initHB(wasmBaseURL) {
|
|
|
238
278
|
try {
|
|
239
279
|
let wasmBinary;
|
|
240
280
|
if (isNode()) {
|
|
241
|
-
wasmBinary = await loadWasmNode();
|
|
281
|
+
wasmBinary = await loadWasmNode(wasmBaseURL);
|
|
242
282
|
} else {
|
|
243
283
|
wasmBinary = await loadWasmWeb(wasmBaseURL);
|
|
244
284
|
}
|
|
@@ -1332,11 +1372,12 @@ function createWebPainter(canvas) {
|
|
|
1332
1372
|
const { color, opacity, radius } = op.bg;
|
|
1333
1373
|
if (color) {
|
|
1334
1374
|
const c = parseHex6(color, opacity);
|
|
1335
|
-
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1336
1375
|
if (radius && radius > 0) {
|
|
1376
|
+
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1337
1377
|
drawRoundedRect(ctx, 0, 0, w, h, radius);
|
|
1338
1378
|
ctx.fill();
|
|
1339
1379
|
} else {
|
|
1380
|
+
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
1340
1381
|
ctx.fillRect(0, 0, w, h);
|
|
1341
1382
|
}
|
|
1342
1383
|
}
|
package/package.json
CHANGED