@orangecatai/adgen-canvas 0.0.26 → 0.0.28

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 (37) hide show
  1. package/dist/dev/{chunk-HAGQZMXY.js → chunk-OTDOAN2W.js} +3 -3
  2. package/dist/dev/{chunk-M6SLPQMN.js → chunk-WELJ6MTO.js} +2 -2
  3. package/dist/dev/data/{image-TSTRTL65.js → image-F5HBZTBB.js} +3 -3
  4. package/dist/dev/index.css +377 -0
  5. package/dist/dev/index.css.map +3 -3
  6. package/dist/dev/index.js +4506 -2591
  7. package/dist/dev/index.js.map +4 -4
  8. package/dist/dev/subset-shared.chunk.js +1 -1
  9. package/dist/dev/subset-worker.chunk.js +1 -1
  10. package/dist/prod/{chunk-FABLWJ5B.js → chunk-INDX7AB6.js} +1 -1
  11. package/dist/prod/{chunk-PIJUOUUJ.js → chunk-RI6ZX32X.js} +2 -2
  12. package/dist/prod/data/image-P4AE4WIT.js +1 -0
  13. package/dist/prod/index.css +1 -1
  14. package/dist/prod/index.js +69 -63
  15. package/dist/prod/subset-shared.chunk.js +1 -1
  16. package/dist/prod/subset-worker.chunk.js +1 -1
  17. package/dist/types/excalidraw/components/AIChatPanel.d.ts +25 -0
  18. package/dist/types/excalidraw/components/App.d.ts +9 -0
  19. package/dist/types/excalidraw/components/CampaignDropdown.d.ts +14 -0
  20. package/dist/types/excalidraw/components/FrameToolbar.d.ts +11 -2
  21. package/dist/types/excalidraw/components/ImageGeneratorPanel.d.ts +14 -0
  22. package/dist/types/excalidraw/components/VideoChainPanel.d.ts +58 -0
  23. package/dist/types/excalidraw/components/VideoElement.d.ts +26 -1
  24. package/dist/types/excalidraw/components/ai-chat/canvasTools.d.ts +272 -3
  25. package/dist/types/excalidraw/components/frameToolbarVariant.d.ts +23 -0
  26. package/dist/types/excalidraw/components/video/videoActions.d.ts +37 -0
  27. package/dist/types/excalidraw/index.d.ts +1 -0
  28. package/dist/types/excalidraw/types.d.ts +61 -0
  29. package/dist/types/excalidraw/utils/brandContextUtils.d.ts +21 -0
  30. package/dist/types/excalidraw/utils/videoApi.d.ts +81 -0
  31. package/dist/types/excalidraw/utils/videoDurationStops.d.ts +14 -0
  32. package/dist/types/excalidraw/utils/videoStitch.d.ts +24 -0
  33. package/package.json +2 -1
  34. package/dist/prod/data/image-D6B2C7FH.js +0 -1
  35. /package/dist/dev/{chunk-HAGQZMXY.js.map → chunk-OTDOAN2W.js.map} +0 -0
  36. /package/dist/dev/{chunk-M6SLPQMN.js.map → chunk-WELJ6MTO.js.map} +0 -0
  37. /package/dist/dev/data/{image-TSTRTL65.js.map → image-F5HBZTBB.js.map} +0 -0
@@ -21,3 +21,24 @@ export declare function buildImageGenSafePrompt(prompt: string, brandContext: Br
21
21
  width: number;
22
22
  height: number;
23
23
  }): string;
24
+ /**
25
+ * Augments a video prompt with brand direction reframed for motion.
26
+ *
27
+ * Deliberately NOT a reuse of buildBrandContextMessage: that builder targets
28
+ * static image ads and emits px size scales, layout patterns, and "render all
29
+ * on-image text in this exact typeface" mandates. Video models ignore px hints
30
+ * and garble text when pushed to reproduce a typeface, so this builder drops
31
+ * `layoutPattern` and `sizeScale` entirely and demotes typography to a soft
32
+ * note inside the on-screen-text clause.
33
+ *
34
+ * The logo is only mentioned when `opts.hasLogoReference` is true — i.e. the
35
+ * logo is actually attached as an input reference (seedance in reference mode).
36
+ * Asking a model to draw a brand mark it has never seen yields a mangled
37
+ * pseudo-logo, which is worse for brand safety than no logo at all.
38
+ *
39
+ * Returns `prompt` unchanged when the brand kit carries no usable direction, so
40
+ * a half-filled kit never appends an empty header.
41
+ */
42
+ export declare function buildVideoBrandPrompt(prompt: string, ctx: BrandContext, opts?: {
43
+ hasLogoReference?: boolean;
44
+ }): string;
@@ -13,6 +13,13 @@ export interface VideoJobParams {
13
13
  }
14
14
  export interface VideoJobResult {
15
15
  videoPresignedUrl: string;
16
+ /**
17
+ * The S3 object key the host persisted the finished segment under (see
18
+ * `/api/sdk/video-gen/status`). Chains persist this per segment so a
19
+ * resumed chain can re-fetch a segment's bytes after its presigned URL
20
+ * (1hr TTL) has expired.
21
+ */
22
+ videoS3Key?: string;
16
23
  }
17
24
  /**
18
25
  * Submit a video generation job to the host proxy.
@@ -28,3 +35,77 @@ export declare function submitVideoJob(params: VideoJobParams, videoGenUrl: stri
28
35
  * Rejects with an Error on failure or abort.
29
36
  */
30
37
  export declare function pollVideoJob(jobId: string, videoGenStatusUrl: string, onProgress: (progress: number) => void, signal?: AbortSignal): Promise<VideoJobResult>;
38
+ /**
39
+ * Presigned S3 URLs can't be fetched directly from the browser — S3 buckets
40
+ * generally don't grant CORS to the app's origin for arbitrary GET-with-body-
41
+ * read requests, so a bare `fetch()` fails with an opaque "Failed to fetch"
42
+ * (unlike a `<video src>`, which the browser loads without a CORS check).
43
+ * Route through the host's download proxy when available: it fetches
44
+ * server-side (no CORS involved) and streams the bytes back same-origin.
45
+ */
46
+ export declare function resolveFetchUrl(videoPresignedUrl: string, videoDownloadProxyUrl: string | undefined): string;
47
+ export declare function fetchSegmentBlob(videoPresignedUrl: string, videoDownloadProxyUrl: string | undefined, signal?: AbortSignal): Promise<Blob>;
48
+ export declare function uploadMergedVideo(blob: Blob, uploadUrl: string | undefined): Promise<string>;
49
+ /**
50
+ * Narrative role of a segment within the ad's arc, assigned by the
51
+ * shot-splitter (`/api/sdk/video-plan`). "hold" marks a segment generated
52
+ * after the story has already resolved — an ambient continuation rather than
53
+ * new plot action.
54
+ */
55
+ export type ChainSegmentBeat = "setup" | "build" | "turn" | "resolution" | "hold";
56
+ export interface VideoPlan {
57
+ styleAnchor: string;
58
+ segments: Array<{
59
+ beat: ChainSegmentBeat;
60
+ prompt: string;
61
+ }>;
62
+ }
63
+ /** Calls the host shot-splitter to divide a concept into per-segment prompts. */
64
+ export declare function planVideoChain(videoPlanUrl: string, params: {
65
+ concept: string;
66
+ segmentCount: number;
67
+ segmentDurationSeconds: number;
68
+ }, signal?: AbortSignal): Promise<VideoPlan>;
69
+ export interface ChainSegmentPlan {
70
+ index: number;
71
+ prompt: string;
72
+ }
73
+ export interface ChainSegmentResult {
74
+ index: number;
75
+ jobId: string;
76
+ videoBlob: Blob;
77
+ videoS3Key?: string;
78
+ }
79
+ export interface ChainParams {
80
+ segments: ChainSegmentPlan[];
81
+ /** Every VideoJobParams field except prompt/firstFrameDataUrl, which vary per segment. */
82
+ baseParams: Omit<VideoJobParams, "prompt" | "firstFrameDataUrl">;
83
+ videoGenUrl: string;
84
+ videoGenStatusUrl: string;
85
+ /** First frame for segment 0, e.g. a user-uploaded starting image. Omit to let the model choose its own opening frame. */
86
+ initialFirstFrameDataUrl?: string;
87
+ /** Segment index to resume from. Requires `resumeFirstFrameDataUrl`. */
88
+ resumeFromIndex?: number;
89
+ /** The last frame extracted from segment `resumeFromIndex - 1`, re-derived by the caller from its persisted `videoS3Key`. */
90
+ resumeFirstFrameDataUrl?: string;
91
+ }
92
+ export interface ChainDeps {
93
+ submit: typeof submitVideoJob;
94
+ poll: typeof pollVideoJob;
95
+ fetchSegment: (videoPresignedUrl: string, signal?: AbortSignal) => Promise<Blob>;
96
+ extractLastFrame: (video: Blob) => Promise<string>;
97
+ }
98
+ export interface ChainCallbacks {
99
+ onSegmentStart?: (index: number) => void;
100
+ onSegmentProgress?: (index: number, progress: number) => void;
101
+ onSegmentDone?: (index: number, result: ChainSegmentResult) => void | Promise<void>;
102
+ }
103
+ export interface ChainResult {
104
+ segments: ChainSegmentResult[];
105
+ }
106
+ /** Thrown when a chain segment fails. `segmentIndex` identifies which one, for a "Retry from segment N" UI. */
107
+ export declare class ChainSegmentError extends Error {
108
+ readonly segmentIndex: number;
109
+ constructor(segmentIndex: number, cause: unknown);
110
+ }
111
+ export declare function runVideoChain(params: ChainParams, deps: ChainDeps, callbacks?: ChainCallbacks, signal?: AbortSignal): Promise<ChainResult>;
@@ -0,0 +1,14 @@
1
+ export declare const MAX_CHAIN_SEGMENTS = 6;
2
+ export interface DurationStopsConfig {
3
+ supportsDuration: boolean;
4
+ durationMode?: "choices" | "slider";
5
+ durationValues?: readonly number[];
6
+ minDuration?: number;
7
+ maxDuration?: number;
8
+ }
9
+ /** The model's largest single-generation duration, or null if it doesn't support duration at all. */
10
+ export declare function nativeMaxFor(cfg: DurationStopsConfig): number | null;
11
+ /** The full ascending list of valid duration values for this model's duration control. */
12
+ export declare function stopsFor(cfg: DurationStopsConfig): number[];
13
+ /** How many chain segments a given stop implies (1 = single-shot, no chaining). */
14
+ export declare function segmentCountAt(stop: number, nativeMax: number): number;
@@ -0,0 +1,24 @@
1
+ export type AudioPolicy = "first-only" | "none";
2
+ /**
3
+ * Decodes the final frame of a video and returns it as a lossless PNG data
4
+ * URL, suitable as the next chain segment's `firstFrameDataUrl`.
5
+ *
6
+ * Uses `CanvasSink.getCanvas(Infinity)` rather than seeking a `<video>`
7
+ * element to `duration - epsilon`: a time-based seek can land on a keyframe
8
+ * boundary or a black tail frame depending on the encoder, which poisons the
9
+ * next segment's starting state.
10
+ */
11
+ export declare function extractLastFrame(video: Blob): Promise<string>;
12
+ /**
13
+ * Stream-copy concatenates segments produced by the same model at the same
14
+ * codec/resolution/fps into one MP4. No re-encode — packets are demuxed
15
+ * from each input and remuxed with shifted timestamps, so this is fast and
16
+ * lossless.
17
+ *
18
+ * Audio policy exists because Veo and Seedance are always-on-audio models
19
+ * with no way to request a silent segment — muting has to happen here, at
20
+ * merge time, to behave the same across every model.
21
+ */
22
+ export declare function concatSegments(segments: Blob[], opts: {
23
+ audio: AudioPolicy;
24
+ }): Promise<Blob>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orangecatai/adgen-canvas",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "type": "module",
5
5
  "types": "./dist/types/excalidraw/index.d.ts",
6
6
  "main": "./dist/prod/index.js",
@@ -106,6 +106,7 @@
106
106
  "lodash.throttle": "4.1.1",
107
107
  "lucide-react": "0.577.0",
108
108
  "marked": "17.0.4",
109
+ "mediabunny": "1.51.0",
109
110
  "nanoid": "3.3.3",
110
111
  "pako": "2.0.3",
111
112
  "perfect-freehand": "1.2.0",
@@ -1 +0,0 @@
1
- import{S as a,T as b,U as c}from"../chunk-PIJUOUUJ.js";import"../chunk-FABLWJ5B.js";import"../chunk-SRAX5OIU.js";export{c as decodePngMetadata,b as encodePngMetadata,a as getTEXtChunk};