@nodaro/shared 3.12.1 → 3.14.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.
Files changed (83) hide show
  1. package/dist/index.cjs +442 -6
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +423 -3
  4. package/dist/index.d.ts +423 -3
  5. package/dist/index.js +400 -7
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/__tests__/producer-types.test.ts +5 -0
  9. package/src/__tests__/video-overlay-docs.test.ts +39 -0
  10. package/src/__tests__/video-overlay.test.ts +572 -0
  11. package/src/catalog-projection.ts +20 -0
  12. package/src/i18n/action-fx.ja.ts +17 -17
  13. package/src/i18n/aesthetic.ja.ts +26 -20
  14. package/src/i18n/animals.ja.ts +49 -49
  15. package/src/i18n/atmosphere.ja.ts +19 -19
  16. package/src/i18n/backdrop.ja.ts +13 -13
  17. package/src/i18n/camera-format.ja.ts +3 -3
  18. package/src/i18n/camera-motions.ja.ts +15 -15
  19. package/src/i18n/character-fx.ja.ts +12 -12
  20. package/src/i18n/character-motion.ja.ts +72 -72
  21. package/src/i18n/color-look.ja.ts +19 -19
  22. package/src/i18n/composition-effects.ja.ts +6 -6
  23. package/src/i18n/era.ja.ts +11 -11
  24. package/src/i18n/exposure-settings.ja.ts +10 -10
  25. package/src/i18n/framing.ja.ts +11 -11
  26. package/src/i18n/furniture.ja.ts +22 -22
  27. package/src/i18n/held-prop.ja.ts +7 -7
  28. package/src/i18n/instrumentation.ja.ts +41 -41
  29. package/src/i18n/lens.ja.ts +5 -5
  30. package/src/i18n/lighting.ja.ts +21 -21
  31. package/src/i18n/materials.ja.ts +4 -4
  32. package/src/i18n/mood.ja.ts +18 -18
  33. package/src/i18n/music-genre.ja.ts +16 -16
  34. package/src/i18n/music-mood.ja.ts +18 -18
  35. package/src/i18n/person.ar.ts +1 -0
  36. package/src/i18n/person.de.ts +1 -0
  37. package/src/i18n/person.es.ts +1 -0
  38. package/src/i18n/person.fr.ts +1 -0
  39. package/src/i18n/person.he.ts +1 -0
  40. package/src/i18n/person.hi.ts +1 -0
  41. package/src/i18n/person.ja.ts +179 -178
  42. package/src/i18n/person.ko.ts +1 -0
  43. package/src/i18n/person.pt-BR.ts +1 -0
  44. package/src/i18n/person.ru.ts +1 -0
  45. package/src/i18n/person.zh-CN.ts +1 -0
  46. package/src/i18n/photo-genre.ja.ts +11 -11
  47. package/src/i18n/photographer.ja.ts +17 -17
  48. package/src/i18n/pose.ja.ts +14 -14
  49. package/src/i18n/post-process-effects.ja.ts +5 -5
  50. package/src/i18n/render-quality.ja.ts +9 -9
  51. package/src/i18n/setting.ar.ts +2 -0
  52. package/src/i18n/setting.de.ts +2 -0
  53. package/src/i18n/setting.es.ts +2 -0
  54. package/src/i18n/setting.fr.ts +2 -0
  55. package/src/i18n/setting.he.ts +2 -0
  56. package/src/i18n/setting.hi.ts +2 -0
  57. package/src/i18n/setting.ja.ts +16 -14
  58. package/src/i18n/setting.ko.ts +2 -0
  59. package/src/i18n/setting.pt-BR.ts +2 -0
  60. package/src/i18n/setting.ru.ts +2 -0
  61. package/src/i18n/setting.zh-CN.ts +2 -0
  62. package/src/i18n/style.ja.ts +10 -10
  63. package/src/i18n/styling.ar.ts +2 -0
  64. package/src/i18n/styling.de.ts +2 -0
  65. package/src/i18n/styling.es.ts +2 -0
  66. package/src/i18n/styling.fr.ts +2 -0
  67. package/src/i18n/styling.he.ts +2 -0
  68. package/src/i18n/styling.hi.ts +2 -0
  69. package/src/i18n/styling.ja.ts +58 -56
  70. package/src/i18n/styling.ko.ts +2 -0
  71. package/src/i18n/styling.pt-BR.ts +2 -0
  72. package/src/i18n/styling.ru.ts +2 -0
  73. package/src/i18n/styling.zh-CN.ts +2 -0
  74. package/src/i18n/temporal.ja.ts +5 -5
  75. package/src/i18n/transitions.ja.ts +12 -12
  76. package/src/i18n/vehicles.ja.ts +29 -29
  77. package/src/i18n/voice-character.ja.ts +27 -27
  78. package/src/i18n/voice-delivery.ja.ts +28 -28
  79. package/src/i18n/weapons.ja.ts +19 -19
  80. package/src/index.ts +2 -0
  81. package/src/producer-types.ts +3 -0
  82. package/src/trigger-node-types.ts +3 -0
  83. package/src/video-overlay.ts +812 -0
package/dist/index.cjs CHANGED
@@ -4049,9 +4049,9 @@ var VIDEO_REF_VIDEO_DURATION_LIMITS = {
4049
4049
  function checkRefVideoDurations(provider, durationsSec) {
4050
4050
  const limit = VIDEO_REF_VIDEO_DURATION_LIMITS[provider];
4051
4051
  if (!limit) return { ok: true };
4052
- const usable = durationsSec.filter((d) => Number.isFinite(d) && d > 0);
4053
- if (usable.length === 0) return { ok: true };
4054
- const offender = usable.find((d) => d < limit.minSec || d > limit.maxSec);
4052
+ const usable2 = durationsSec.filter((d) => Number.isFinite(d) && d > 0);
4053
+ if (usable2.length === 0) return { ok: true };
4054
+ const offender = usable2.find((d) => d < limit.minSec || d > limit.maxSec);
4055
4055
  if (offender !== void 0) {
4056
4056
  return {
4057
4057
  ok: false,
@@ -4059,7 +4059,7 @@ function checkRefVideoDurations(provider, durationsSec) {
4059
4059
  };
4060
4060
  }
4061
4061
  if (limit.maxTotalSec !== void 0) {
4062
- const total = usable.reduce((a, b) => a + b, 0);
4062
+ const total = usable2.reduce((a, b) => a + b, 0);
4063
4063
  if (total > limit.maxTotalSec) {
4064
4064
  return {
4065
4065
  ok: false,
@@ -5502,7 +5502,10 @@ var VIDEO_PRODUCER_TYPES = /* @__PURE__ */ new Set([
5502
5502
  // with the standard `videoUrl` field. It is a video producer as much as it
5503
5503
  // is a composition producer — omitting it here is the "cannot connect the
5504
5504
  // outputs" bug, and its `composition` handle is typed separately.
5505
- "pro-3d-render"
5505
+ "pro-3d-render",
5506
+ // Video Overlay: timed image layers over a video in one local FFmpeg pass
5507
+ // (the base audio copied) — emits a video URL on `video-out`.
5508
+ "video-overlay"
5506
5509
  ]);
5507
5510
  var DYNAMIC_PRODUCER_TYPES = /* @__PURE__ */ new Set([
5508
5511
  "list",
@@ -9569,10 +9572,12 @@ function fieldKeyFromHandle(handleId) {
9569
9572
  var SCHEDULE_TRIGGER_NODE_TYPE = "schedule-trigger";
9570
9573
  var WEBHOOK_TRIGGER_NODE_TYPE = "webhook-trigger";
9571
9574
  var TELEGRAM_TRIGGER_NODE_TYPE = "telegram-trigger";
9575
+ var TELEGRAM_ACCOUNT_TRIGGER_NODE_TYPE = "telegram-account-trigger";
9572
9576
  var PROJECTED_TRIGGER_NODE_TYPES = /* @__PURE__ */ new Set([
9573
9577
  SCHEDULE_TRIGGER_NODE_TYPE,
9574
9578
  WEBHOOK_TRIGGER_NODE_TYPE,
9575
- TELEGRAM_TRIGGER_NODE_TYPE
9579
+ TELEGRAM_TRIGGER_NODE_TYPE,
9580
+ TELEGRAM_ACCOUNT_TRIGGER_NODE_TYPE
9576
9581
  ]);
9577
9582
  function isProjectedTriggerNodeType(type) {
9578
9583
  return typeof type === "string" && PROJECTED_TRIGGER_NODE_TYPES.has(type);
@@ -15643,6 +15648,394 @@ function isRtlText(text) {
15643
15648
  return /[֐-׿؀-ۿݐ-ݿࢠ-ࣿיִ-﷿ﹰ-]/.test(text);
15644
15649
  }
15645
15650
 
15651
+ // src/video-overlay.ts
15652
+ var VIDEO_OVERLAY_MAX_LAYERS = 20;
15653
+ var VIDEO_OVERLAY_MAX_TIME_SEC = 3600;
15654
+ var VIDEO_OVERLAY_HANDLE_IDS = [
15655
+ "overlay",
15656
+ "overlay2",
15657
+ "overlay3",
15658
+ "overlay4",
15659
+ "overlay5",
15660
+ "overlay6",
15661
+ "overlay7",
15662
+ "overlay8",
15663
+ "overlay9",
15664
+ "overlay10",
15665
+ "overlay11",
15666
+ "overlay12"
15667
+ ];
15668
+ var VIDEO_OVERLAY_PRESET_IDS = ["card", "corner-badge", "full-frame"];
15669
+ var VIDEO_OVERLAY_CORNERS = ["top-left", "top-right", "bottom-left", "bottom-right"];
15670
+ var VIDEO_OVERLAY_FITS = ["contain", "cover"];
15671
+ var VIDEO_OVERLAY_OUTPUT_ASPECTS = ["16:9", "9:16", "1:1", "4:5"];
15672
+ var VIDEO_OVERLAY_LAYER_PLAN_HANDLE = "layerPlan";
15673
+ var VIDEO_OVERLAY_BOUNDS = {
15674
+ x: [-100, 100],
15675
+ y: [-100, 100],
15676
+ width: [1, 100],
15677
+ height: [1, 100],
15678
+ opacity: [0, 1],
15679
+ zIndex: [0, 100]
15680
+ };
15681
+ var VIDEO_OVERLAY_MAX_TOTAL_LAYER_BYTES = 100 * 1024 * 1024;
15682
+ var VIDEO_OVERLAY_ANIMATION_SEC = 0.15;
15683
+ var VIDEO_OVERLAY_ANIMATION_MIN_SCALE = 0.96;
15684
+ var VIDEO_OVERLAY_BADGE_WIDTH = 18;
15685
+ var VIDEO_OVERLAY_BADGE_INSET = 4;
15686
+ var VIDEO_OVERLAY_DEFAULT_BACKGROUND = "#000000";
15687
+ var VIDEO_OVERLAY_BOX_FIELDS = ["anchor", "x", "y", "width", "height", "fit"];
15688
+ var VIDEO_OVERLAY_WARNING_CODES = ["clipped", "skipped", "animated_first_frame", "audio_reencoded"];
15689
+ var VIDEO_OVERLAY_ERROR_CODES = [
15690
+ "no_layers",
15691
+ "too_many_layers",
15692
+ "incomplete_box",
15693
+ "layer_without_image",
15694
+ "time_out_of_range",
15695
+ "end_before_start",
15696
+ "fit_without_aspect",
15697
+ "field_out_of_bounds"
15698
+ ];
15699
+ var badge = (anchor, sx, sy) => ({
15700
+ anchor,
15701
+ x: sx * VIDEO_OVERLAY_BADGE_INSET,
15702
+ y: sy * VIDEO_OVERLAY_BADGE_INSET,
15703
+ width: VIDEO_OVERLAY_BADGE_WIDTH,
15704
+ fit: "contain"
15705
+ });
15706
+ var VIDEO_OVERLAY_PRESETS = {
15707
+ card: { anchor: "center", x: 0, y: -4, width: 78, height: 60, fit: "contain" },
15708
+ "full-frame": { anchor: "center", x: 0, y: 0, width: 100, height: 100, fit: "cover" },
15709
+ "corner-badge": {
15710
+ "bottom-right": badge("bottom-right", -1, -1),
15711
+ "bottom-left": badge("bottom-left", 1, -1),
15712
+ "top-right": badge("top-right", -1, 1),
15713
+ "top-left": badge("top-left", 1, 1)
15714
+ }
15715
+ };
15716
+ var DEFAULT_VIDEO_OVERLAY_LAYER = Object.freeze({
15717
+ start: 0,
15718
+ preset: "corner-badge",
15719
+ corner: "bottom-right",
15720
+ ...VIDEO_OVERLAY_PRESETS["corner-badge"]["bottom-right"],
15721
+ opacity: 1,
15722
+ animate: true
15723
+ });
15724
+ var HEX6 = /^#[0-9a-fA-F]{6}$/;
15725
+ function isVideoOverlayPresetId(v) {
15726
+ return typeof v === "string" && VIDEO_OVERLAY_PRESET_IDS.includes(v);
15727
+ }
15728
+ function isVideoOverlayCorner(v) {
15729
+ return typeof v === "string" && VIDEO_OVERLAY_CORNERS.includes(v);
15730
+ }
15731
+ function isVideoOverlayOutputAspect(v) {
15732
+ return typeof v === "string" && VIDEO_OVERLAY_OUTPUT_ASPECTS.includes(v);
15733
+ }
15734
+ function isFit(v) {
15735
+ return v === "contain" || v === "cover";
15736
+ }
15737
+ function asLayer(v) {
15738
+ return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
15739
+ }
15740
+ function videoOverlaySlotOfHandle(handle) {
15741
+ return VIDEO_OVERLAY_HANDLE_IDS.indexOf(handle ?? "") + 1;
15742
+ }
15743
+ function videoOverlayPresetBox(preset, corner) {
15744
+ return preset === "corner-badge" ? VIDEO_OVERLAY_PRESETS["corner-badge"][isVideoOverlayCorner(corner) ? corner : "bottom-right"] : VIDEO_OVERLAY_PRESETS[preset];
15745
+ }
15746
+ var TRAILING_DEFAULTS = { x: 0, y: 0, fit: "contain", opacity: 1, animate: true };
15747
+ function usable(key, value) {
15748
+ if (value === null || value === void 0) return false;
15749
+ if (key === "preset") return isVideoOverlayPresetId(value);
15750
+ if (key === "corner") return isVideoOverlayCorner(value);
15751
+ return true;
15752
+ }
15753
+ function clean(raw) {
15754
+ const entries = Object.entries(raw);
15755
+ if (entries.every(([k, v]) => usable(k, v))) return raw;
15756
+ return Object.fromEntries(entries.filter(([k, v]) => usable(k, v)));
15757
+ }
15758
+ function sameShallow(a, b) {
15759
+ if (!b || typeof b !== "object") return false;
15760
+ const ka = Object.keys(a);
15761
+ const kb = Object.keys(b);
15762
+ return ka.length === kb.length && ka.every((k) => a[k] === b[k]);
15763
+ }
15764
+ function expandVideoOverlayLayer(raw) {
15765
+ const obj = asLayer(raw);
15766
+ const layer = obj ? clean(obj) : {};
15767
+ const present = VIDEO_OVERLAY_BOX_FIELDS.filter((f) => layer[f] !== void 0);
15768
+ let out;
15769
+ if (isVideoOverlayPresetId(layer.preset)) {
15770
+ const box = videoOverlayPresetBox(layer.preset, layer.corner);
15771
+ out = { ...box, ...layer };
15772
+ if (present.some((f) => layer[f] !== box[f])) delete out.preset;
15773
+ } else if (present.length === 0) {
15774
+ out = { ...DEFAULT_VIDEO_OVERLAY_LAYER, ...videoOverlayPresetBox("corner-badge", layer.corner), ...layer };
15775
+ } else if (layer.anchor === void 0 || layer.width === void 0) {
15776
+ return raw;
15777
+ } else {
15778
+ out = { ...layer };
15779
+ }
15780
+ for (const [k, v] of Object.entries(TRAILING_DEFAULTS)) if (out[k] === void 0) out[k] = v;
15781
+ return sameShallow(out, raw) ? raw : out;
15782
+ }
15783
+ function expandVideoOverlayPresets(layers) {
15784
+ let changed = false;
15785
+ const out = layers.map((l) => {
15786
+ const e = expandVideoOverlayLayer(l);
15787
+ if (e !== l) changed = true;
15788
+ return e;
15789
+ });
15790
+ return changed ? out : layers;
15791
+ }
15792
+ function applyVideoOverlayPreset(layer, preset, corner) {
15793
+ const base = { ...expandVideoOverlayLayer(layer) };
15794
+ for (const f of VIDEO_OVERLAY_BOX_FIELDS) delete base[f];
15795
+ delete base.preset;
15796
+ const nextCorner = preset === "corner-badge" ? corner ?? (isVideoOverlayCorner(base.corner) ? base.corner : "bottom-right") : void 0;
15797
+ return expandVideoOverlayLayer({
15798
+ ...base,
15799
+ ...videoOverlayPresetBox(preset, nextCorner),
15800
+ preset,
15801
+ ...nextCorner ? { corner: nextCorner } : {}
15802
+ });
15803
+ }
15804
+ function toCustomVideoOverlayLayer(layer) {
15805
+ const { preset: _tag, ...rest } = expandVideoOverlayLayer(layer);
15806
+ return rest;
15807
+ }
15808
+ function clearWiredVideoOverlayImageUrls(layers, wiredSlots) {
15809
+ let out = null;
15810
+ for (const slot of wiredSlots) {
15811
+ if (!Number.isInteger(slot) || slot < 1 || slot > VIDEO_OVERLAY_HANDLE_IDS.length) continue;
15812
+ const layer = layers[slot - 1];
15813
+ if (!asLayer(layer) || !("imageUrl" in layer)) continue;
15814
+ out ??= [...layers];
15815
+ const { imageUrl: _cleared, ...rest } = layer;
15816
+ out[slot - 1] = rest;
15817
+ }
15818
+ return out ?? layers;
15819
+ }
15820
+ function normalizeVideoOverlayNodes(nodes, edges) {
15821
+ let changed = false;
15822
+ const out = nodes.map((node) => {
15823
+ if (node.type !== "video-overlay") return node;
15824
+ const data = node.data;
15825
+ if (!data || typeof data !== "object" || Array.isArray(data)) return node;
15826
+ const d = data;
15827
+ if (!Array.isArray(d.layers)) return node;
15828
+ const layers = d.layers;
15829
+ const wired = /* @__PURE__ */ new Set();
15830
+ for (const e of edges ?? []) {
15831
+ if (e.target !== node.id) continue;
15832
+ const slot = videoOverlaySlotOfHandle(typeof e.targetHandle === "string" ? e.targetHandle : void 0);
15833
+ if (slot > 0) wired.add(slot);
15834
+ }
15835
+ const cleared = clearWiredVideoOverlayImageUrls(layers, wired);
15836
+ let layersChanged = cleared !== layers;
15837
+ const next = cleared.map((l) => {
15838
+ if (!asLayer(l)) return l;
15839
+ const e = expandVideoOverlayLayer(l);
15840
+ if (e !== l) layersChanged = true;
15841
+ return e;
15842
+ });
15843
+ if (!layersChanged) return node;
15844
+ changed = true;
15845
+ return { ...node, data: { ...d, layers: next } };
15846
+ });
15847
+ return changed ? out : nodes;
15848
+ }
15849
+ var isSlot = (v) => typeof v === "number" && Number.isInteger(v) && v >= 1;
15850
+ var isIndex = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
15851
+ function videoOverlayRenderOrder(layers) {
15852
+ return layers.map((l, i) => {
15853
+ const own = isSlot(l?.slot) ? l.slot - 1 : isIndex(l?.index) ? l.index : i;
15854
+ return { i, z: typeof l?.zIndex === "number" && Number.isFinite(l.zIndex) ? l.zIndex : own };
15855
+ }).sort((a, b) => a.z - b.z || a.i - b.i).map((e) => e.i);
15856
+ }
15857
+ var evenFloor = (n) => Math.max(2, Math.floor(n / 2) * 2);
15858
+ function videoOverlayCanvas(display, outputAspect) {
15859
+ if (isVideoOverlayOutputAspect(outputAspect)) {
15860
+ const d = ASPECT_RATIO_DIMENSIONS[outputAspect];
15861
+ return { w: d.width, h: d.height };
15862
+ }
15863
+ if (!display || !(display.width > 0) || !(display.height > 0)) return null;
15864
+ const sar = typeof display.sar === "number" && Number.isFinite(display.sar) && display.sar > 0 ? display.sar : 1;
15865
+ return { w: evenFloor(display.width * sar), h: evenFloor(display.height) };
15866
+ }
15867
+ function anchorFactors(anchor) {
15868
+ const h = anchor.endsWith("left") ? 0 : anchor.endsWith("right") ? 1 : 0.5;
15869
+ const v = anchor.startsWith("top") ? 0 : anchor.startsWith("bottom") ? 1 : 0.5;
15870
+ return [h, v];
15871
+ }
15872
+ function resolveVideoOverlayGeometry(canvas, layer, imageAspect) {
15873
+ const aspect = Number.isFinite(imageAspect) && imageAspect > 0 ? imageAspect : 1;
15874
+ let bw = Math.max(1, Math.round(layer.width / 100 * canvas.w));
15875
+ let bh = layer.height !== void 0 ? Math.max(1, Math.round(layer.height / 100 * canvas.h)) : Math.max(1, Math.round(bw / aspect));
15876
+ if (layer.height === void 0 && bh > canvas.h) {
15877
+ bw = Math.max(1, Math.round(bw * (canvas.h / bh)));
15878
+ bh = canvas.h;
15879
+ }
15880
+ const [ax, ay] = anchorFactors(layer.anchor);
15881
+ const left = Math.round(ax * (canvas.w - bw) + layer.x / 100 * canvas.w);
15882
+ const top = Math.round(ay * (canvas.h - bh) + layer.y / 100 * canvas.h);
15883
+ let dw;
15884
+ let dh;
15885
+ if (layer.fit === "cover") {
15886
+ dw = bw;
15887
+ dh = bh;
15888
+ } else if (bw / bh > aspect) {
15889
+ dh = bh;
15890
+ dw = bh * aspect;
15891
+ } else {
15892
+ dw = bw;
15893
+ dh = bw / aspect;
15894
+ }
15895
+ const width = evenFloor(dw);
15896
+ const height = evenFloor(dh);
15897
+ return {
15898
+ box: { left, top, width: bw, height: bh },
15899
+ drawn: { left: left + Math.floor((bw - width) / 2), top: top + Math.floor((bh - height) / 2), width, height }
15900
+ };
15901
+ }
15902
+ var inTimeRange = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 && v <= VIDEO_OVERLAY_MAX_TIME_SEC;
15903
+ var BOUNDED_FIELDS = Object.keys(VIDEO_OVERLAY_BOUNDS);
15904
+ function outOfBounds(l) {
15905
+ for (const f of BOUNDED_FIELDS) {
15906
+ const v = l[f];
15907
+ if (v === void 0 || v === null) continue;
15908
+ const [min, max] = VIDEO_OVERLAY_BOUNDS[f];
15909
+ const integer = f === "zIndex";
15910
+ if (typeof v !== "number" || !Number.isFinite(v) || v < min || v > max || integer && !Number.isInteger(v)) {
15911
+ return { field: f, allowed: `${integer ? "integers " : ""}${min}..${max}` };
15912
+ }
15913
+ }
15914
+ if (l.anchor != null && !OVERLAY_ANCHORS.includes(l.anchor)) {
15915
+ return { field: "anchor", allowed: OVERLAY_ANCHORS.join(", ") };
15916
+ }
15917
+ if (l.fit != null && !isFit(l.fit)) return { field: "fit", allowed: VIDEO_OVERLAY_FITS.join(", ") };
15918
+ if (l.animate != null && typeof l.animate !== "boolean") return { field: "animate", allowed: "true, false" };
15919
+ return null;
15920
+ }
15921
+ function hasDrawableVideoOverlayBox(layer) {
15922
+ const l = asLayer(layer);
15923
+ if (!l) return false;
15924
+ if (!OVERLAY_ANCHORS.includes(l.anchor)) return false;
15925
+ if (typeof l.width !== "number" || !Number.isFinite(l.width)) return false;
15926
+ return outOfBounds(l) === null;
15927
+ }
15928
+ function validateVideoOverlayRequest(body) {
15929
+ const layers = Array.isArray(body.layers) ? body.layers : [];
15930
+ if (layers.length === 0) return { ok: false, code: "no_layers", params: {} };
15931
+ if (layers.length > VIDEO_OVERLAY_MAX_LAYERS) {
15932
+ return { ok: false, code: "too_many_layers", params: { max: VIDEO_OVERLAY_MAX_LAYERS, count: layers.length } };
15933
+ }
15934
+ for (let i = 0; i < layers.length; i++) {
15935
+ const l = asLayer(layers[i]) ?? {};
15936
+ const at = (code, params = {}) => ({
15937
+ ok: false,
15938
+ code,
15939
+ layer: i,
15940
+ ...typeof l.slot === "number" ? { slot: l.slot } : {},
15941
+ params
15942
+ });
15943
+ const boxFields = VIDEO_OVERLAY_BOX_FIELDS.filter((f) => l[f] !== void 0 && l[f] !== null);
15944
+ if (!isVideoOverlayPresetId(l.preset) && boxFields.length > 0 && (l.anchor == null || l.width == null)) return at("incomplete_box");
15945
+ const bad = outOfBounds(l);
15946
+ if (bad) return at("field_out_of_bounds", bad);
15947
+ if (typeof l.imageUrl !== "string" || l.imageUrl.length === 0) return at("layer_without_image");
15948
+ if (!inTimeRange(l.start)) return at("time_out_of_range", { field: "start", max: VIDEO_OVERLAY_MAX_TIME_SEC });
15949
+ if (l.end !== void 0 && l.end !== null) {
15950
+ if (!inTimeRange(l.end)) return at("time_out_of_range", { field: "end", max: VIDEO_OVERLAY_MAX_TIME_SEC });
15951
+ if (!(l.end > l.start)) return at("end_before_start", { start: l.start, end: l.end });
15952
+ }
15953
+ }
15954
+ if (!isVideoOverlayOutputAspect(body.outputAspect) && (body.baseFit != null || body.backgroundColor != null)) {
15955
+ return { ok: false, code: "fit_without_aspect", params: {} };
15956
+ }
15957
+ return { ok: true };
15958
+ }
15959
+ var MESSAGES = {
15960
+ no_layers: () => "At least 1 layer is required",
15961
+ too_many_layers: (p) => `At most ${p.max} layers (got ${p.count})`,
15962
+ incomplete_box: () => "anchor and width are required without a preset",
15963
+ layer_without_image: () => "no image \u2014 connect one to the layer's handle or set imageUrl",
15964
+ time_out_of_range: (p) => `${p.field} must be between 0 and ${p.max} s`,
15965
+ end_before_start: (p) => `end (${p.end} s) must be after start (${p.start} s)`,
15966
+ fit_without_aspect: () => "baseFit and backgroundColor need an outputAspect",
15967
+ field_out_of_bounds: (p) => `${p.field} is out of range (allowed: ${p.allowed})`
15968
+ };
15969
+ function videoOverlayLayerLabel(ref) {
15970
+ return typeof ref.slot === "number" ? `Layer ${ref.slot}` : typeof ref.layer === "number" ? `layers[${ref.layer}]` : "";
15971
+ }
15972
+ function formatVideoOverlayError(issue2) {
15973
+ const label = videoOverlayLayerLabel(issue2);
15974
+ const text = MESSAGES[issue2.code](issue2.params);
15975
+ return label ? `${label}: ${text}` : text;
15976
+ }
15977
+ function assembleVideoOverlayRequest(input) {
15978
+ const stored = Array.isArray(input.data.layers) ? input.data.layers : [];
15979
+ const wired = input.wiredImageUrls.slice(0, VIDEO_OVERLAY_HANDLE_IDS.length);
15980
+ const slots = Math.max(wired.length, stored.length);
15981
+ const layers = [];
15982
+ for (let i = 0; i < slots; i++) {
15983
+ const raw = asLayer(stored[i]);
15984
+ const wiredUrl = wired[i];
15985
+ const own = raw?.imageUrl;
15986
+ const image = typeof wiredUrl === "string" && wiredUrl.length > 0 ? wiredUrl : typeof own === "string" && own.length > 0 ? own : void 0;
15987
+ if (!image) continue;
15988
+ layers.push(expandVideoOverlayLayer({ ...raw ?? {}, imageUrl: image, slot: i + 1 }));
15989
+ }
15990
+ const outputAspect = isVideoOverlayOutputAspect(input.data.outputAspect) ? input.data.outputAspect : void 0;
15991
+ const baseFit = isFit(input.data.baseFit) ? input.data.baseFit : void 0;
15992
+ const backgroundColor = typeof input.data.backgroundColor === "string" && HEX6.test(input.data.backgroundColor) ? input.data.backgroundColor : void 0;
15993
+ return {
15994
+ videoUrl: input.videoUrl,
15995
+ layers,
15996
+ ...outputAspect ? { outputAspect } : {},
15997
+ ...baseFit ? { baseFit } : {},
15998
+ ...backgroundColor ? { backgroundColor } : {}
15999
+ };
16000
+ }
16001
+ function videoOverlaySlotSources(layers, wiredImageUrls) {
16002
+ const stored = Array.isArray(layers) ? layers : [];
16003
+ const wired = wiredImageUrls.slice(0, VIDEO_OVERLAY_HANDLE_IDS.length);
16004
+ return Array.from({ length: Math.max(stored.length, wired.length) }, (_, i) => {
16005
+ const w = wired[i];
16006
+ if (typeof w === "string" && w.length > 0) return w;
16007
+ const own = asLayer(stored[i])?.imageUrl;
16008
+ return typeof own === "string" && own.length > 0 ? own : void 0;
16009
+ });
16010
+ }
16011
+ function canonicalValue(v) {
16012
+ if (Array.isArray(v)) return v.map((x) => x === void 0 ? null : canonicalValue(x));
16013
+ if (v !== null && typeof v === "object") {
16014
+ const out = {};
16015
+ for (const k of Object.keys(v).sort()) {
16016
+ const x = v[k];
16017
+ if (x !== void 0 && x !== null) out[k] = canonicalValue(x);
16018
+ }
16019
+ return out;
16020
+ }
16021
+ return v;
16022
+ }
16023
+ var VIDEO_OVERLAY_MAX_COMPOSITION_KEY_LENGTH = 65536;
16024
+ function videoOverlayCompositionKey(c) {
16025
+ const sources = c.sources.map((s) => typeof s === "string" && s.length > 0 ? s : null);
16026
+ while (sources.length > 0 && sources[sources.length - 1] === null) sources.pop();
16027
+ return JSON.stringify(
16028
+ canonicalValue([
16029
+ c.baseUrl || null,
16030
+ sources,
16031
+ Array.isArray(c.data.layers) ? c.data.layers : [],
16032
+ c.data.outputAspect ?? null,
16033
+ c.data.baseFit ?? null,
16034
+ c.data.backgroundColor ?? null
16035
+ ])
16036
+ );
16037
+ }
16038
+
15646
16039
  // src/entity-image-handle.ts
15647
16040
  var ENTITY_IMAGE_HANDLE_TYPES = /* @__PURE__ */ new Set([
15648
16041
  "character",
@@ -19562,6 +19955,7 @@ exports.DEFAULT_VIDEO_ANALYSIS_MODEL = DEFAULT_VIDEO_ANALYSIS_MODEL;
19562
19955
  exports.DEFAULT_VIDEO_ANALYSIS_TIER = DEFAULT_VIDEO_ANALYSIS_TIER;
19563
19956
  exports.DEFAULT_VIDEO_CLIP_COST = DEFAULT_VIDEO_CLIP_COST;
19564
19957
  exports.DEFAULT_VIDEO_DURATION_SEC = DEFAULT_VIDEO_DURATION_SEC;
19958
+ exports.DEFAULT_VIDEO_OVERLAY_LAYER = DEFAULT_VIDEO_OVERLAY_LAYER;
19565
19959
  exports.DEFAULT_VIDEO_PROVIDER = DEFAULT_VIDEO_PROVIDER;
19566
19960
  exports.DEFAULT_VOICE_CHANGER_MODEL = DEFAULT_VOICE_CHANGER_MODEL;
19567
19961
  exports.DEFAULT_VOICE_DESIGN_MODEL = DEFAULT_VOICE_DESIGN_MODEL;
@@ -20007,6 +20401,7 @@ exports.StyleDirectivesSchema = StyleDirectivesSchema;
20007
20401
  exports.SubGateNameSchema = SubGateNameSchema;
20008
20402
  exports.T2I_TO_I2I_VARIANT = T2I_TO_I2I_VARIANT;
20009
20403
  exports.TASK_CHAINED_EDIT_PROVIDERS = TASK_CHAINED_EDIT_PROVIDERS;
20404
+ exports.TELEGRAM_ACCOUNT_TRIGGER_NODE_TYPE = TELEGRAM_ACCOUNT_TRIGGER_NODE_TYPE;
20010
20405
  exports.TELEGRAM_TRIGGER_NODE_TYPE = TELEGRAM_TRIGGER_NODE_TYPE;
20011
20406
  exports.TEMPLATE_CATEGORIES = TEMPLATE_CATEGORIES;
20012
20407
  exports.TEXT_TO_AUDIO_PROVIDERS = TEXT_TO_AUDIO_PROVIDERS;
@@ -20077,6 +20472,26 @@ exports.VIDEO_MODEL_CAPS = VIDEO_MODEL_CAPS;
20077
20472
  exports.VIDEO_MODE_ALIASES = VIDEO_MODE_ALIASES;
20078
20473
  exports.VIDEO_ONLY_PARAMETER_NODE_TYPES = VIDEO_ONLY_PARAMETER_NODE_TYPES;
20079
20474
  exports.VIDEO_OUTPUT_CANVAS = VIDEO_OUTPUT_CANVAS;
20475
+ exports.VIDEO_OVERLAY_ANIMATION_MIN_SCALE = VIDEO_OVERLAY_ANIMATION_MIN_SCALE;
20476
+ exports.VIDEO_OVERLAY_ANIMATION_SEC = VIDEO_OVERLAY_ANIMATION_SEC;
20477
+ exports.VIDEO_OVERLAY_BADGE_INSET = VIDEO_OVERLAY_BADGE_INSET;
20478
+ exports.VIDEO_OVERLAY_BADGE_WIDTH = VIDEO_OVERLAY_BADGE_WIDTH;
20479
+ exports.VIDEO_OVERLAY_BOUNDS = VIDEO_OVERLAY_BOUNDS;
20480
+ exports.VIDEO_OVERLAY_BOX_FIELDS = VIDEO_OVERLAY_BOX_FIELDS;
20481
+ exports.VIDEO_OVERLAY_CORNERS = VIDEO_OVERLAY_CORNERS;
20482
+ exports.VIDEO_OVERLAY_DEFAULT_BACKGROUND = VIDEO_OVERLAY_DEFAULT_BACKGROUND;
20483
+ exports.VIDEO_OVERLAY_ERROR_CODES = VIDEO_OVERLAY_ERROR_CODES;
20484
+ exports.VIDEO_OVERLAY_FITS = VIDEO_OVERLAY_FITS;
20485
+ exports.VIDEO_OVERLAY_HANDLE_IDS = VIDEO_OVERLAY_HANDLE_IDS;
20486
+ exports.VIDEO_OVERLAY_LAYER_PLAN_HANDLE = VIDEO_OVERLAY_LAYER_PLAN_HANDLE;
20487
+ exports.VIDEO_OVERLAY_MAX_COMPOSITION_KEY_LENGTH = VIDEO_OVERLAY_MAX_COMPOSITION_KEY_LENGTH;
20488
+ exports.VIDEO_OVERLAY_MAX_LAYERS = VIDEO_OVERLAY_MAX_LAYERS;
20489
+ exports.VIDEO_OVERLAY_MAX_TIME_SEC = VIDEO_OVERLAY_MAX_TIME_SEC;
20490
+ exports.VIDEO_OVERLAY_MAX_TOTAL_LAYER_BYTES = VIDEO_OVERLAY_MAX_TOTAL_LAYER_BYTES;
20491
+ exports.VIDEO_OVERLAY_OUTPUT_ASPECTS = VIDEO_OVERLAY_OUTPUT_ASPECTS;
20492
+ exports.VIDEO_OVERLAY_PRESETS = VIDEO_OVERLAY_PRESETS;
20493
+ exports.VIDEO_OVERLAY_PRESET_IDS = VIDEO_OVERLAY_PRESET_IDS;
20494
+ exports.VIDEO_OVERLAY_WARNING_CODES = VIDEO_OVERLAY_WARNING_CODES;
20080
20495
  exports.VIDEO_PRODUCER_TYPES = VIDEO_PRODUCER_TYPES;
20081
20496
  exports.VIDEO_PROMPT_MAX = VIDEO_PROMPT_MAX;
20082
20497
  exports.VIDEO_PROVIDERS_REQUIRING_IMAGE = VIDEO_PROVIDERS_REQUIRING_IMAGE;
@@ -20122,12 +20537,14 @@ exports.applyScene3DV2EditOperations = applyScene3DV2EditOperations;
20122
20537
  exports.applySlots = applySlots;
20123
20538
  exports.applyVideoAudioToggle = applyVideoAudioToggle;
20124
20539
  exports.applyVideoNegativePrompt = applyVideoNegativePrompt;
20540
+ exports.applyVideoOverlayPreset = applyVideoOverlayPreset;
20125
20541
  exports.asEditPlanMode = asEditPlanMode;
20126
20542
  exports.asEditPlanTier = asEditPlanTier;
20127
20543
  exports.aspectRatioFromDims = aspectRatioFromDims;
20128
20544
  exports.aspectRatioOptionsByKind = aspectRatioOptionsByKind;
20129
20545
  exports.aspectRatioToNumber = aspectRatioToNumber;
20130
20546
  exports.assembleNarratedVideoCredits = assembleNarratedVideoCredits;
20547
+ exports.assembleVideoOverlayRequest = assembleVideoOverlayRequest;
20131
20548
  exports.assertCanvasExecutionAllowed = assertCanvasExecutionAllowed;
20132
20549
  exports.autoStrokeWidth = autoStrokeWidth;
20133
20550
  exports.availableReasoningEfforts = availableReasoningEfforts;
@@ -20182,6 +20599,7 @@ exports.classifyRefToken = classifyRefToken;
20182
20599
  exports.cleanOrphanedItems = cleanOrphanedItems;
20183
20600
  exports.clearImageCriticMetadata = clearImageCriticMetadata;
20184
20601
  exports.clearVideoCriticMetadata = clearVideoCriticMetadata;
20602
+ exports.clearWiredVideoOverlayImageUrls = clearWiredVideoOverlayImageUrls;
20185
20603
  exports.clipLookSchema = clipLookSchema;
20186
20604
  exports.collectAncestorRefs = collectAncestorRefs;
20187
20605
  exports.combineSameLabelRefs = combineSameLabelRefs;
@@ -20233,6 +20651,8 @@ exports.evaluateJsonExpression = evaluateJsonExpression;
20233
20651
  exports.evaluateJsonPath = evaluateJsonPath;
20234
20652
  exports.expandExtraRefsToConnectedReferences = expandExtraRefsToConnectedReferences;
20235
20653
  exports.expandItemsWithRepeat = expandItemsWithRepeat;
20654
+ exports.expandVideoOverlayLayer = expandVideoOverlayLayer;
20655
+ exports.expandVideoOverlayPresets = expandVideoOverlayPresets;
20236
20656
  exports.extractAllGeneratedResults = extractAllGeneratedResults;
20237
20657
  exports.extractCharacterLoraFields = extractCharacterLoraFields;
20238
20658
  exports.extractGeneratedJsonAsList = extractGeneratedJsonAsList;
@@ -20252,6 +20672,7 @@ exports.findSeedance2AudioOverLimit = findSeedance2AudioOverLimit;
20252
20672
  exports.findWordlessTranscriptFeeds = findWordlessTranscriptFeeds;
20253
20673
  exports.firstSightExtraRole = firstSightExtraRole;
20254
20674
  exports.flattenItems = flattenItems;
20675
+ exports.formatVideoOverlayError = formatVideoOverlayError;
20255
20676
  exports.getAnimal = getAnimal;
20256
20677
  exports.getAnimalLabel = getAnimalLabel;
20257
20678
  exports.getAnimalPromptHint = getAnimalPromptHint;
@@ -20304,6 +20725,7 @@ exports.groupByKindAndFamily = groupByKindAndFamily;
20304
20725
  exports.groupHandleId = groupHandleId;
20305
20726
  exports.groupLlmModelsByVendor = groupLlmModelsByVendor;
20306
20727
  exports.hasContiguousSegmentDurations = hasContiguousSegmentDurations;
20728
+ exports.hasDrawableVideoOverlayBox = hasDrawableVideoOverlayBox;
20307
20729
  exports.hasFeature = hasFeature;
20308
20730
  exports.hasUrlParserHazard = hasUrlParserHazard;
20309
20731
  exports.hexToRgbaArray = hexToRgbaArray;
@@ -20376,6 +20798,9 @@ exports.isValidTimezone = isValidTimezone;
20376
20798
  exports.isVeoProvider = isVeoProvider;
20377
20799
  exports.isVideoAnalysisMixedTier = isVideoAnalysisMixedTier;
20378
20800
  exports.isVideoAnalysisTier = isVideoAnalysisTier;
20801
+ exports.isVideoOverlayCorner = isVideoOverlayCorner;
20802
+ exports.isVideoOverlayOutputAspect = isVideoOverlayOutputAspect;
20803
+ exports.isVideoOverlayPresetId = isVideoOverlayPresetId;
20379
20804
  exports.isWan3Provider = isWan3Provider;
20380
20805
  exports.jsonResultToList = jsonResultToList;
20381
20806
  exports.knownEntitySlugsFromRefs = knownEntitySlugsFromRefs;
@@ -20439,6 +20864,7 @@ exports.normalizeScheduleRule = normalizeScheduleRule;
20439
20864
  exports.normalizeScheduleRules = normalizeScheduleRules;
20440
20865
  exports.normalizeTemplateCategory = normalizeTemplateCategory;
20441
20866
  exports.normalizeTranscript = normalizeTranscript;
20867
+ exports.normalizeVideoOverlayNodes = normalizeVideoOverlayNodes;
20442
20868
  exports.normalizeVideoRequestParams = normalizeVideoRequestParams;
20443
20869
  exports.normalizeWan3Resolution = normalizeWan3Resolution;
20444
20870
  exports.orderedLlmModels = orderedLlmModels;
@@ -20555,6 +20981,7 @@ exports.resolveTopazUpscale = resolveTopazUpscale;
20555
20981
  exports.resolveVideoAnalysisModel = resolveVideoAnalysisModel;
20556
20982
  exports.resolveVideoLinkOutput = resolveVideoLinkOutput;
20557
20983
  exports.resolveVideoModeForInputs = resolveVideoModeForInputs;
20984
+ exports.resolveVideoOverlayGeometry = resolveVideoOverlayGeometry;
20558
20985
  exports.resolveVideoProviderForMode = resolveVideoProviderForMode;
20559
20986
  exports.resolveXfadeName = resolveXfadeName;
20560
20987
  exports.rewriteSceneBindings = rewriteSceneBindings;
@@ -20690,6 +21117,7 @@ exports.templateCategoryStoredValues = templateCategoryStoredValues;
20690
21117
  exports.timezoneOffsetMinutes = timezoneOffsetMinutes;
20691
21118
  exports.toConnectedReference = toConnectedReference;
20692
21119
  exports.toConnectedReferences = toConnectedReferences;
21120
+ exports.toCustomVideoOverlayLayer = toCustomVideoOverlayLayer;
20693
21121
  exports.togglePick = togglePick;
20694
21122
  exports.transcribeLaneSupportsWordTimestamps = transcribeLaneSupportsWordTimestamps;
20695
21123
  exports.transcribeProvidersWithWordTimestamps = transcribeProvidersWithWordTimestamps;
@@ -20717,6 +21145,7 @@ exports.validateNoNestedGroups = validateNoNestedGroups;
20717
21145
  exports.validateObjects = validateObjects;
20718
21146
  exports.validateProviderForNodeType = validateProviderForNodeType;
20719
21147
  exports.validateSubWorkflowRoutes = validateSubWorkflowRoutes;
21148
+ exports.validateVideoOverlayRequest = validateVideoOverlayRequest;
20720
21149
  exports.variantJobId = variantJobId;
20721
21150
  exports.vec3Schema = vec3Schema;
20722
21151
  exports.verifyScene3DPlanV2ContentHash = verifyScene3DPlanV2ContentHash;
@@ -20729,6 +21158,13 @@ exports.videoLinkNeedsDownload = videoLinkNeedsDownload;
20729
21158
  exports.videoModelCanSpeakDialogue = videoModelCanSpeakDialogue;
20730
21159
  exports.videoModelSupportsAudio = videoModelSupportsAudio;
20731
21160
  exports.videoNegativeSuffix = videoNegativeSuffix;
21161
+ exports.videoOverlayCanvas = videoOverlayCanvas;
21162
+ exports.videoOverlayCompositionKey = videoOverlayCompositionKey;
21163
+ exports.videoOverlayLayerLabel = videoOverlayLayerLabel;
21164
+ exports.videoOverlayPresetBox = videoOverlayPresetBox;
21165
+ exports.videoOverlayRenderOrder = videoOverlayRenderOrder;
21166
+ exports.videoOverlaySlotOfHandle = videoOverlaySlotOfHandle;
21167
+ exports.videoOverlaySlotSources = videoOverlaySlotSources;
20732
21168
  exports.videoProviderFoldsLoneEndFrame = videoProviderFoldsLoneEndFrame;
20733
21169
  exports.videoProviderRequiresImage = videoProviderRequiresImage;
20734
21170
  exports.windowAnalysisSchema = windowAnalysisSchema;