@shotstack/shotstack-canvas 2.0.5 → 2.0.7

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.
@@ -573,7 +573,7 @@ var wordTimingSchema = import_zod2.wordTimingSchema.extend({
573
573
  confidence: import_zod.z.number().min(0).max(1).optional()
574
574
  });
575
575
  var richCaptionFontSchema = import_zod.z.object({
576
- family: import_zod.z.string().default(CANVAS_CONFIG.DEFAULTS.fontFamily),
576
+ family: import_zod.z.string().default("Roboto"),
577
577
  size: import_zod.z.number().int().min(1).max(500).default(24),
578
578
  weight: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).default("400"),
579
579
  color: import_zod.z.string().regex(HEX6).default("#ffffff"),
@@ -4875,7 +4875,7 @@ function extractFontConfig(asset) {
4875
4875
  const font = asset.font;
4876
4876
  const active = asset.active?.font;
4877
4877
  return {
4878
- family: font?.family ?? CANVAS_CONFIG.DEFAULTS.fontFamily,
4878
+ family: font?.family ?? "Roboto",
4879
4879
  size: font?.size ?? 24,
4880
4880
  weight: String(font?.weight ?? "400"),
4881
4881
  baseColor: font?.color ?? "#ffffff",
@@ -5615,6 +5615,7 @@ var NodeRawEncoder = class _NodeRawEncoder {
5615
5615
  preset = "ultrafast",
5616
5616
  profile = "high"
5617
5617
  } = config;
5618
+ const hasAlpha = config.hasAlpha ?? false;
5618
5619
  const args = [
5619
5620
  "-y",
5620
5621
  "-f",
@@ -5628,32 +5629,49 @@ var NodeRawEncoder = class _NodeRawEncoder {
5628
5629
  "-thread_queue_size",
5629
5630
  "512",
5630
5631
  "-i",
5631
- "pipe:0",
5632
- "-c:v",
5633
- "libx264",
5634
- "-preset",
5635
- preset,
5636
- "-tune",
5637
- "stillimage",
5638
- "-crf",
5639
- String(crf),
5640
- "-profile:v",
5641
- profile,
5642
- "-g",
5643
- "300",
5644
- "-bf",
5645
- "2",
5646
- "-threads",
5647
- "0",
5648
- "-pix_fmt",
5649
- "yuv420p",
5650
- "-r",
5651
- String(fps),
5652
- "-movflags",
5653
- "+faststart"
5632
+ "pipe:0"
5654
5633
  ];
5634
+ if (hasAlpha) {
5635
+ args.push(
5636
+ "-c:v",
5637
+ "prores_ks",
5638
+ "-profile:v",
5639
+ "4444",
5640
+ "-pix_fmt",
5641
+ "yuva444p10le",
5642
+ "-vendor",
5643
+ "apl0",
5644
+ "-r",
5645
+ String(fps)
5646
+ );
5647
+ } else {
5648
+ args.push(
5649
+ "-c:v",
5650
+ "libx264",
5651
+ "-preset",
5652
+ preset,
5653
+ "-tune",
5654
+ "stillimage",
5655
+ "-crf",
5656
+ String(crf),
5657
+ "-profile:v",
5658
+ profile,
5659
+ "-g",
5660
+ "300",
5661
+ "-bf",
5662
+ "2",
5663
+ "-threads",
5664
+ "0",
5665
+ "-pix_fmt",
5666
+ "yuv420p",
5667
+ "-r",
5668
+ String(fps),
5669
+ "-movflags",
5670
+ "+faststart"
5671
+ );
5672
+ }
5655
5673
  if (this.outputToMemory) {
5656
- args.push("-f", "mp4", "pipe:1");
5674
+ args.push("-f", hasAlpha ? "mov" : "mp4", "pipe:1");
5657
5675
  } else {
5658
5676
  args.push(this.outputPath);
5659
5677
  }
@@ -5781,14 +5799,14 @@ async function createNodeRawEncoder(config, options) {
5781
5799
  }
5782
5800
 
5783
5801
  // src/core/rich-caption-renderer.ts
5784
- var OPEN_SANS_FONT_URL = "https://fonts.gstatic.com/s/opensans/v44/mem8YaGs126MiZpBA-U1UpcaXcl0Aw.ttf";
5785
- var OPEN_SANS_FONT_URLS = {
5786
- "300": OPEN_SANS_FONT_URL,
5787
- "400": OPEN_SANS_FONT_URL,
5788
- "500": OPEN_SANS_FONT_URL,
5789
- "600": OPEN_SANS_FONT_URL,
5790
- "700": OPEN_SANS_FONT_URL,
5791
- "800": OPEN_SANS_FONT_URL
5802
+ var ROBOTO_FONT_URL = "https://fonts.gstatic.com/s/roboto/v50/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf";
5803
+ var ROBOTO_FONT_URLS = {
5804
+ "300": ROBOTO_FONT_URL,
5805
+ "400": ROBOTO_FONT_URL,
5806
+ "500": ROBOTO_FONT_URL,
5807
+ "600": ROBOTO_FONT_URL,
5808
+ "700": ROBOTO_FONT_URL,
5809
+ "800": ROBOTO_FONT_URL
5792
5810
  };
5793
5811
  var RichCaptionRenderer = class {
5794
5812
  width;
@@ -5818,12 +5836,12 @@ var RichCaptionRenderer = class {
5818
5836
  async initialize() {
5819
5837
  this.fontRegistry = await FontRegistry.getSharedInstance(this.wasmBaseURL);
5820
5838
  this.layoutEngine = new CaptionLayoutEngine(this.fontRegistry);
5821
- const weightsToLoad = Object.keys(OPEN_SANS_FONT_URLS);
5839
+ const weightsToLoad = Object.keys(ROBOTO_FONT_URLS);
5822
5840
  const loadPromises = weightsToLoad.map(async (weight) => {
5823
- const existingFace = await this.fontRegistry.getFace({ family: "Open Sans", weight });
5841
+ const existingFace = await this.fontRegistry.getFace({ family: "Roboto", weight });
5824
5842
  if (!existingFace) {
5825
- const bytes = await loadFileOrHttpToArrayBuffer(OPEN_SANS_FONT_URLS[weight]);
5826
- await this.fontRegistry.registerFromBytes(bytes, { family: "Open Sans", weight });
5843
+ const bytes = await loadFileOrHttpToArrayBuffer(ROBOTO_FONT_URLS[weight]);
5844
+ await this.fontRegistry.registerFromBytes(bytes, { family: "Roboto", weight });
5827
5845
  }
5828
5846
  });
5829
5847
  await Promise.all(loadPromises);
@@ -5867,7 +5885,7 @@ var RichCaptionRenderer = class {
5867
5885
  maxLines: asset.maxLines ?? 2,
5868
5886
  position: asset.position ?? "bottom",
5869
5887
  fontSize: font?.size ?? 24,
5870
- fontFamily: font?.family ?? "Open Sans",
5888
+ fontFamily: font?.family ?? "Roboto",
5871
5889
  fontWeight: String(font?.weight ?? "400"),
5872
5890
  letterSpacing: style?.letterSpacing ?? 0,
5873
5891
  wordSpacing: typeof style?.wordSpacing === "number" ? style.wordSpacing : 0,
@@ -5913,6 +5931,8 @@ var RichCaptionRenderer = class {
5913
5931
  animationStyle,
5914
5932
  animationSpeed
5915
5933
  );
5934
+ const bgColor = options?.bgColor;
5935
+ const hasAlpha = !bgColor;
5916
5936
  const encoder = new NodeRawEncoder();
5917
5937
  await encoder.configure(
5918
5938
  {
@@ -5922,7 +5942,8 @@ var RichCaptionRenderer = class {
5922
5942
  duration,
5923
5943
  crf: options?.crf ?? 23,
5924
5944
  preset: options?.preset ?? "ultrafast",
5925
- profile: options?.profile ?? "high"
5945
+ profile: options?.profile ?? "high",
5946
+ hasAlpha
5926
5947
  },
5927
5948
  {
5928
5949
  outputPath,
@@ -5934,7 +5955,6 @@ var RichCaptionRenderer = class {
5934
5955
  height: this.height,
5935
5956
  pixelRatio: this.pixelRatio
5936
5957
  });
5937
- const bgColor = options?.bgColor ?? "#000000";
5938
5958
  const totalStart = performance.now();
5939
5959
  let framesProcessed = 0;
5940
5960
  let lastPct = -1;
@@ -5948,7 +5968,7 @@ var RichCaptionRenderer = class {
5948
5968
  height: this.height * this.pixelRatio,
5949
5969
  pixelRatio: this.pixelRatio,
5950
5970
  clear: true,
5951
- bg: { color: bgColor, opacity: 1, radius: 0 }
5971
+ ...bgColor ? { bg: { color: bgColor, opacity: 1, radius: 0 } } : {}
5952
5972
  };
5953
5973
  await painter.render([beginOp, ...captionOps]);
5954
5974
  const rawResult = painter.toRawRGBA();
@@ -1207,6 +1207,7 @@ interface VideoEncoderConfig {
1207
1207
  hardwareAcceleration?: "prefer-hardware" | "prefer-software" | "no-preference";
1208
1208
  crf?: number;
1209
1209
  preset?: "ultrafast" | "superfast" | "veryfast" | "faster" | "fast" | "medium" | "slow" | "slower" | "veryslow";
1210
+ hasAlpha?: boolean;
1210
1211
  }
1211
1212
  interface VideoEncoderProgress {
1212
1213
  framesEncoded: number;
@@ -1207,6 +1207,7 @@ interface VideoEncoderConfig {
1207
1207
  hardwareAcceleration?: "prefer-hardware" | "prefer-software" | "no-preference";
1208
1208
  crf?: number;
1209
1209
  preset?: "ultrafast" | "superfast" | "veryfast" | "faster" | "fast" | "medium" | "slow" | "slower" | "veryslow";
1210
+ hasAlpha?: boolean;
1210
1211
  }
1211
1212
  interface VideoEncoderProgress {
1212
1213
  framesEncoded: number;
@@ -184,7 +184,7 @@ var wordTimingSchema = baseWordTimingSchema.extend({
184
184
  confidence: z.number().min(0).max(1).optional()
185
185
  });
186
186
  var richCaptionFontSchema = z.object({
187
- family: z.string().default(CANVAS_CONFIG.DEFAULTS.fontFamily),
187
+ family: z.string().default("Roboto"),
188
188
  size: z.number().int().min(1).max(500).default(24),
189
189
  weight: z.union([z.string(), z.number()]).default("400"),
190
190
  color: z.string().regex(HEX6).default("#ffffff"),
@@ -4485,7 +4485,7 @@ function extractFontConfig(asset) {
4485
4485
  const font = asset.font;
4486
4486
  const active = asset.active?.font;
4487
4487
  return {
4488
- family: font?.family ?? CANVAS_CONFIG.DEFAULTS.fontFamily,
4488
+ family: font?.family ?? "Roboto",
4489
4489
  size: font?.size ?? 24,
4490
4490
  weight: String(font?.weight ?? "400"),
4491
4491
  baseColor: font?.color ?? "#ffffff",
@@ -5225,6 +5225,7 @@ var NodeRawEncoder = class _NodeRawEncoder {
5225
5225
  preset = "ultrafast",
5226
5226
  profile = "high"
5227
5227
  } = config;
5228
+ const hasAlpha = config.hasAlpha ?? false;
5228
5229
  const args = [
5229
5230
  "-y",
5230
5231
  "-f",
@@ -5238,32 +5239,49 @@ var NodeRawEncoder = class _NodeRawEncoder {
5238
5239
  "-thread_queue_size",
5239
5240
  "512",
5240
5241
  "-i",
5241
- "pipe:0",
5242
- "-c:v",
5243
- "libx264",
5244
- "-preset",
5245
- preset,
5246
- "-tune",
5247
- "stillimage",
5248
- "-crf",
5249
- String(crf),
5250
- "-profile:v",
5251
- profile,
5252
- "-g",
5253
- "300",
5254
- "-bf",
5255
- "2",
5256
- "-threads",
5257
- "0",
5258
- "-pix_fmt",
5259
- "yuv420p",
5260
- "-r",
5261
- String(fps),
5262
- "-movflags",
5263
- "+faststart"
5242
+ "pipe:0"
5264
5243
  ];
5244
+ if (hasAlpha) {
5245
+ args.push(
5246
+ "-c:v",
5247
+ "prores_ks",
5248
+ "-profile:v",
5249
+ "4444",
5250
+ "-pix_fmt",
5251
+ "yuva444p10le",
5252
+ "-vendor",
5253
+ "apl0",
5254
+ "-r",
5255
+ String(fps)
5256
+ );
5257
+ } else {
5258
+ args.push(
5259
+ "-c:v",
5260
+ "libx264",
5261
+ "-preset",
5262
+ preset,
5263
+ "-tune",
5264
+ "stillimage",
5265
+ "-crf",
5266
+ String(crf),
5267
+ "-profile:v",
5268
+ profile,
5269
+ "-g",
5270
+ "300",
5271
+ "-bf",
5272
+ "2",
5273
+ "-threads",
5274
+ "0",
5275
+ "-pix_fmt",
5276
+ "yuv420p",
5277
+ "-r",
5278
+ String(fps),
5279
+ "-movflags",
5280
+ "+faststart"
5281
+ );
5282
+ }
5265
5283
  if (this.outputToMemory) {
5266
- args.push("-f", "mp4", "pipe:1");
5284
+ args.push("-f", hasAlpha ? "mov" : "mp4", "pipe:1");
5267
5285
  } else {
5268
5286
  args.push(this.outputPath);
5269
5287
  }
@@ -5391,14 +5409,14 @@ async function createNodeRawEncoder(config, options) {
5391
5409
  }
5392
5410
 
5393
5411
  // src/core/rich-caption-renderer.ts
5394
- var OPEN_SANS_FONT_URL = "https://fonts.gstatic.com/s/opensans/v44/mem8YaGs126MiZpBA-U1UpcaXcl0Aw.ttf";
5395
- var OPEN_SANS_FONT_URLS = {
5396
- "300": OPEN_SANS_FONT_URL,
5397
- "400": OPEN_SANS_FONT_URL,
5398
- "500": OPEN_SANS_FONT_URL,
5399
- "600": OPEN_SANS_FONT_URL,
5400
- "700": OPEN_SANS_FONT_URL,
5401
- "800": OPEN_SANS_FONT_URL
5412
+ var ROBOTO_FONT_URL = "https://fonts.gstatic.com/s/roboto/v50/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf";
5413
+ var ROBOTO_FONT_URLS = {
5414
+ "300": ROBOTO_FONT_URL,
5415
+ "400": ROBOTO_FONT_URL,
5416
+ "500": ROBOTO_FONT_URL,
5417
+ "600": ROBOTO_FONT_URL,
5418
+ "700": ROBOTO_FONT_URL,
5419
+ "800": ROBOTO_FONT_URL
5402
5420
  };
5403
5421
  var RichCaptionRenderer = class {
5404
5422
  width;
@@ -5428,12 +5446,12 @@ var RichCaptionRenderer = class {
5428
5446
  async initialize() {
5429
5447
  this.fontRegistry = await FontRegistry.getSharedInstance(this.wasmBaseURL);
5430
5448
  this.layoutEngine = new CaptionLayoutEngine(this.fontRegistry);
5431
- const weightsToLoad = Object.keys(OPEN_SANS_FONT_URLS);
5449
+ const weightsToLoad = Object.keys(ROBOTO_FONT_URLS);
5432
5450
  const loadPromises = weightsToLoad.map(async (weight) => {
5433
- const existingFace = await this.fontRegistry.getFace({ family: "Open Sans", weight });
5451
+ const existingFace = await this.fontRegistry.getFace({ family: "Roboto", weight });
5434
5452
  if (!existingFace) {
5435
- const bytes = await loadFileOrHttpToArrayBuffer(OPEN_SANS_FONT_URLS[weight]);
5436
- await this.fontRegistry.registerFromBytes(bytes, { family: "Open Sans", weight });
5453
+ const bytes = await loadFileOrHttpToArrayBuffer(ROBOTO_FONT_URLS[weight]);
5454
+ await this.fontRegistry.registerFromBytes(bytes, { family: "Roboto", weight });
5437
5455
  }
5438
5456
  });
5439
5457
  await Promise.all(loadPromises);
@@ -5477,7 +5495,7 @@ var RichCaptionRenderer = class {
5477
5495
  maxLines: asset.maxLines ?? 2,
5478
5496
  position: asset.position ?? "bottom",
5479
5497
  fontSize: font?.size ?? 24,
5480
- fontFamily: font?.family ?? "Open Sans",
5498
+ fontFamily: font?.family ?? "Roboto",
5481
5499
  fontWeight: String(font?.weight ?? "400"),
5482
5500
  letterSpacing: style?.letterSpacing ?? 0,
5483
5501
  wordSpacing: typeof style?.wordSpacing === "number" ? style.wordSpacing : 0,
@@ -5523,6 +5541,8 @@ var RichCaptionRenderer = class {
5523
5541
  animationStyle,
5524
5542
  animationSpeed
5525
5543
  );
5544
+ const bgColor = options?.bgColor;
5545
+ const hasAlpha = !bgColor;
5526
5546
  const encoder = new NodeRawEncoder();
5527
5547
  await encoder.configure(
5528
5548
  {
@@ -5532,7 +5552,8 @@ var RichCaptionRenderer = class {
5532
5552
  duration,
5533
5553
  crf: options?.crf ?? 23,
5534
5554
  preset: options?.preset ?? "ultrafast",
5535
- profile: options?.profile ?? "high"
5555
+ profile: options?.profile ?? "high",
5556
+ hasAlpha
5536
5557
  },
5537
5558
  {
5538
5559
  outputPath,
@@ -5544,7 +5565,6 @@ var RichCaptionRenderer = class {
5544
5565
  height: this.height,
5545
5566
  pixelRatio: this.pixelRatio
5546
5567
  });
5547
- const bgColor = options?.bgColor ?? "#000000";
5548
5568
  const totalStart = performance.now();
5549
5569
  let framesProcessed = 0;
5550
5570
  let lastPct = -1;
@@ -5558,7 +5578,7 @@ var RichCaptionRenderer = class {
5558
5578
  height: this.height * this.pixelRatio,
5559
5579
  pixelRatio: this.pixelRatio,
5560
5580
  clear: true,
5561
- bg: { color: bgColor, opacity: 1, radius: 0 }
5581
+ ...bgColor ? { bg: { color: bgColor, opacity: 1, radius: 0 } } : {}
5562
5582
  };
5563
5583
  await painter.render([beginOp, ...captionOps]);
5564
5584
  const rawResult = painter.toRawRGBA();
@@ -1148,6 +1148,7 @@ interface VideoEncoderConfig {
1148
1148
  hardwareAcceleration?: "prefer-hardware" | "prefer-software" | "no-preference";
1149
1149
  crf?: number;
1150
1150
  preset?: "ultrafast" | "superfast" | "veryfast" | "faster" | "fast" | "medium" | "slow" | "slower" | "veryslow";
1151
+ hasAlpha?: boolean;
1151
1152
  }
1152
1153
  interface VideoEncoderProgress {
1153
1154
  framesEncoded: number;
package/dist/entry.web.js CHANGED
@@ -18062,7 +18062,7 @@ var wordTimingSchema = baseWordTimingSchema.extend({
18062
18062
  confidence: external_exports.number().min(0).max(1).optional()
18063
18063
  });
18064
18064
  var richCaptionFontSchema = external_exports.object({
18065
- family: external_exports.string().default(CANVAS_CONFIG.DEFAULTS.fontFamily),
18065
+ family: external_exports.string().default("Roboto"),
18066
18066
  size: external_exports.number().int().min(1).max(500).default(24),
18067
18067
  weight: external_exports.union([external_exports.string(), external_exports.number()]).default("400"),
18068
18068
  color: external_exports.string().regex(HEX6).default("#ffffff"),
@@ -36035,7 +36035,7 @@ function extractFontConfig(asset) {
36035
36035
  const font = asset.font;
36036
36036
  const active = asset.active?.font;
36037
36037
  return {
36038
- family: font?.family ?? CANVAS_CONFIG.DEFAULTS.fontFamily,
36038
+ family: font?.family ?? "Roboto",
36039
36039
  size: font?.size ?? 24,
36040
36040
  weight: String(font?.weight ?? "400"),
36041
36041
  baseColor: font?.color ?? "#ffffff",
package/package.json CHANGED
@@ -1,65 +1,65 @@
1
- {
2
- "name": "@shotstack/shotstack-canvas",
3
- "version": "2.0.5",
4
- "description": "Text layout & animation engine (HarfBuzz) for Node & Web - fully self-contained.",
5
- "type": "module",
6
- "main": "./dist/entry.node.cjs",
7
- "module": "./dist/entry.node.js",
8
- "browser": "./dist/entry.web.js",
9
- "types": "./dist/entry.node.d.ts",
10
- "exports": {
11
- ".": {
12
- "node": {
13
- "import": "./dist/entry.node.js",
14
- "require": "./dist/entry.node.cjs"
15
- },
16
- "browser": "./dist/entry.web.js",
17
- "default": "./dist/entry.web.js"
18
- }
19
- },
20
- "files": [
21
- "dist/**",
22
- "scripts/postinstall.js",
23
- "README.md",
24
- "LICENSE"
25
- ],
26
- "scripts": {
27
- "dev": "tsup --watch",
28
- "build": "tsup",
29
- "postinstall": "node scripts/postinstall.js",
30
- "vendor:harfbuzz": "node scripts/vendor-harfbuzz.js",
31
- "example:node": "node examples/node-example.mjs",
32
- "example:video": "node examples/node-video.mjs",
33
- "example:web": "vite dev examples/web-example",
34
- "test:caption-web": "vite dev examples/caption-tests",
35
- "prepublishOnly": "npm run build"
36
- },
37
- "publishConfig": {
38
- "access": "public",
39
- "registry": "https://registry.npmjs.org/"
40
- },
41
- "engines": {
42
- "node": ">=18"
43
- },
44
- "sideEffects": false,
45
- "dependencies": {
46
- "@resvg/resvg-js": "^2.6.2",
47
- "@resvg/resvg-wasm": "^2.6.2",
48
- "@shotstack/schemas": "1.6.0",
49
- "canvas": "npm:@napi-rs/canvas@^0.1.54",
50
- "ffmpeg-static": "^5.2.0",
51
- "fontkit": "^2.0.4",
52
- "harfbuzzjs": "0.4.12",
53
- "lru-cache": "^11.2.5",
54
- "mp4-muxer": "^5.1.3",
55
- "zod": "^4.2.0"
56
- },
57
- "devDependencies": {
58
- "@types/node": "^20.14.10",
59
- "tsup": "^8.2.3",
60
- "typescript": "^5.5.3",
61
- "vite": "^5.3.3",
62
- "vite-plugin-top-level-await": "1.6.0",
63
- "vite-plugin-wasm": "3.5.0"
64
- }
65
- }
1
+ {
2
+ "name": "@shotstack/shotstack-canvas",
3
+ "version": "2.0.7",
4
+ "description": "Text layout & animation engine (HarfBuzz) for Node & Web - fully self-contained.",
5
+ "type": "module",
6
+ "main": "./dist/entry.node.cjs",
7
+ "module": "./dist/entry.node.js",
8
+ "browser": "./dist/entry.web.js",
9
+ "types": "./dist/entry.node.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "node": {
13
+ "import": "./dist/entry.node.js",
14
+ "require": "./dist/entry.node.cjs"
15
+ },
16
+ "browser": "./dist/entry.web.js",
17
+ "default": "./dist/entry.web.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist/**",
22
+ "scripts/postinstall.js",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "dev": "tsup --watch",
28
+ "build": "tsup",
29
+ "postinstall": "node scripts/postinstall.js",
30
+ "vendor:harfbuzz": "node scripts/vendor-harfbuzz.js",
31
+ "example:node": "node examples/node-example.mjs",
32
+ "example:video": "node examples/node-video.mjs",
33
+ "example:web": "vite dev examples/web-example",
34
+ "test:caption-web": "vite dev examples/caption-tests",
35
+ "prepublishOnly": "npm run build"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public",
39
+ "registry": "https://registry.npmjs.org/"
40
+ },
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "sideEffects": false,
45
+ "dependencies": {
46
+ "@resvg/resvg-js": "^2.6.2",
47
+ "@resvg/resvg-wasm": "^2.6.2",
48
+ "@shotstack/schemas": "1.8.3",
49
+ "canvas": "npm:@napi-rs/canvas@^0.1.54",
50
+ "ffmpeg-static": "^5.2.0",
51
+ "fontkit": "^2.0.4",
52
+ "harfbuzzjs": "0.4.12",
53
+ "lru-cache": "^11.2.5",
54
+ "mp4-muxer": "^5.1.3",
55
+ "zod": "^4.2.0"
56
+ },
57
+ "devDependencies": {
58
+ "@types/node": "^20.14.10",
59
+ "tsup": "^8.2.3",
60
+ "typescript": "^5.5.3",
61
+ "vite": "^5.3.3",
62
+ "vite-plugin-top-level-await": "1.6.0",
63
+ "vite-plugin-wasm": "3.5.0"
64
+ }
65
+ }