@ume-group/contracts 0.2.1
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/README.md +37 -0
- package/dist/adserving.d.ts +150 -0
- package/dist/adserving.d.ts.map +1 -0
- package/dist/adserving.js +8 -0
- package/dist/campaigns.d.ts +37 -0
- package/dist/campaigns.d.ts.map +1 -0
- package/dist/campaigns.js +8 -0
- package/dist/gausst.d.ts +236 -0
- package/dist/gausst.d.ts.map +1 -0
- package/dist/gausst.js +307 -0
- package/dist/gausst.test.d.ts +2 -0
- package/dist/gausst.test.d.ts.map +1 -0
- package/dist/gausst.test.js +71 -0
- package/dist/index.d.ts +1531 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1112 -0
- package/dist/layer2/index.d.ts +9 -0
- package/dist/layer2/index.d.ts.map +1 -0
- package/dist/layer2/index.js +10 -0
- package/dist/layer2/shaders.d.ts +185 -0
- package/dist/layer2/shaders.d.ts.map +1 -0
- package/dist/layer2/shaders.js +604 -0
- package/dist/layer2/webcam-utils.d.ts +113 -0
- package/dist/layer2/webcam-utils.d.ts.map +1 -0
- package/dist/layer2/webcam-utils.js +147 -0
- package/dist/layer2/webcam-utils.test.d.ts +2 -0
- package/dist/layer2/webcam-utils.test.d.ts.map +1 -0
- package/dist/layer2/webcam-utils.test.js +18 -0
- package/dist/layer2.d.ts +558 -0
- package/dist/layer2.d.ts.map +1 -0
- package/dist/layer2.js +376 -0
- package/dist/layer2.test.d.ts +2 -0
- package/dist/layer2.test.d.ts.map +1 -0
- package/dist/layer2.test.js +65 -0
- package/dist/perspective.d.ts +28 -0
- package/dist/perspective.d.ts.map +1 -0
- package/dist/perspective.js +157 -0
- package/dist/segmentation/MediaPipeSegmenter.d.ts +201 -0
- package/dist/segmentation/MediaPipeSegmenter.d.ts.map +1 -0
- package/dist/segmentation/MediaPipeSegmenter.js +434 -0
- package/dist/segmentation/index.d.ts +5 -0
- package/dist/segmentation/index.d.ts.map +1 -0
- package/dist/segmentation/index.js +4 -0
- package/dist/webcam/GarbageMatteDragManager.d.ts +63 -0
- package/dist/webcam/GarbageMatteDragManager.d.ts.map +1 -0
- package/dist/webcam/GarbageMatteDragManager.js +183 -0
- package/dist/webcam/WebcamStreamManager.d.ts +103 -0
- package/dist/webcam/WebcamStreamManager.d.ts.map +1 -0
- package/dist/webcam/WebcamStreamManager.js +356 -0
- package/dist/webcam/index.d.ts +5 -0
- package/dist/webcam/index.d.ts.map +1 -0
- package/dist/webcam/index.js +2 -0
- package/openapi/admetise.yaml +632 -0
- package/openapi/includu.yaml +621 -0
- package/openapi/integration.yaml +372 -0
- package/openapi/shared/schemas.yaml +227 -0
- package/package.json +53 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1531 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for Includu Platform
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - @includu/editor (timeline editor)
|
|
6
|
+
* - @includu/cms (video library)
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Debug flag - true in Vite dev mode, false in production builds.
|
|
10
|
+
* Can also be set manually for testing.
|
|
11
|
+
*/
|
|
12
|
+
export declare let DEBUG: boolean;
|
|
13
|
+
/** Override the DEBUG flag (useful for testing or manual control) */
|
|
14
|
+
export declare function setDebug(value: boolean): void;
|
|
15
|
+
/** Debug logger - only outputs when DEBUG is true (dev mode by default) */
|
|
16
|
+
export declare function debug(...args: unknown[]): void;
|
|
17
|
+
/**
|
|
18
|
+
* A video clip from any source (CMS, YouTube, etc.)
|
|
19
|
+
*/
|
|
20
|
+
export interface VideoClip {
|
|
21
|
+
/** Unique identifier */
|
|
22
|
+
id: string;
|
|
23
|
+
/** Display title */
|
|
24
|
+
title: string;
|
|
25
|
+
/** Optional description */
|
|
26
|
+
description?: string;
|
|
27
|
+
/** Duration in seconds */
|
|
28
|
+
duration: number;
|
|
29
|
+
/** Thumbnail URL */
|
|
30
|
+
thumbnail?: string;
|
|
31
|
+
/** HLS manifest URL for playback */
|
|
32
|
+
hlsUrl: string;
|
|
33
|
+
/** Original source type */
|
|
34
|
+
sourceType: 'cms' | 'youtube' | 'vimeo' | 'url';
|
|
35
|
+
/** Source-specific identifier (e.g., Cloudflare Stream UID) */
|
|
36
|
+
sourceId?: string;
|
|
37
|
+
/** Creation timestamp */
|
|
38
|
+
createdAt: string;
|
|
39
|
+
/** Last updated timestamp */
|
|
40
|
+
updatedAt: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Video clip with CMS-specific metadata
|
|
44
|
+
*/
|
|
45
|
+
export interface CMSVideoClip extends VideoClip {
|
|
46
|
+
sourceType: 'cms';
|
|
47
|
+
/** Cloudflare Stream video UID */
|
|
48
|
+
streamUid: string;
|
|
49
|
+
/** Processing status */
|
|
50
|
+
status: 'uploading' | 'processing' | 'ready' | 'error';
|
|
51
|
+
/** Upload progress (0-100) */
|
|
52
|
+
uploadProgress?: number;
|
|
53
|
+
/** Tags for organization */
|
|
54
|
+
tags: string[];
|
|
55
|
+
/** Original filename */
|
|
56
|
+
originalFilename?: string;
|
|
57
|
+
/** File size in bytes */
|
|
58
|
+
fileSize?: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Live stream input
|
|
62
|
+
*/
|
|
63
|
+
export interface LiveStream {
|
|
64
|
+
id: string;
|
|
65
|
+
title: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
/** SRT ingest URL */
|
|
68
|
+
srtUrl: string;
|
|
69
|
+
/** HLS playback URL (when live) */
|
|
70
|
+
hlsUrl?: string;
|
|
71
|
+
/** Stream status */
|
|
72
|
+
status: 'idle' | 'connecting' | 'live' | 'ended';
|
|
73
|
+
/** Cloudflare Stream live input ID */
|
|
74
|
+
streamInputId: string;
|
|
75
|
+
createdAt: string;
|
|
76
|
+
}
|
|
77
|
+
export type OverlayType = 'text' | 'emoji' | 'shape' | 'image' | 'cta' | 'sprite-sequence' | 'video';
|
|
78
|
+
/** Track type for overlays - determines which timeline track they appear on */
|
|
79
|
+
export type OverlayTrack = 'overlays' | 'branding' | 'motion-gfx';
|
|
80
|
+
export interface TextContent {
|
|
81
|
+
text: string;
|
|
82
|
+
fontSize: number;
|
|
83
|
+
fontFamily: string;
|
|
84
|
+
fontWeight: 'normal' | 'bold';
|
|
85
|
+
color: string;
|
|
86
|
+
textAlign: 'left' | 'center' | 'right';
|
|
87
|
+
/**
|
|
88
|
+
* Background plane properties (independent from text transform)
|
|
89
|
+
* When present, background is rendered as a separate layer that can be scaled independently
|
|
90
|
+
*/
|
|
91
|
+
background?: {
|
|
92
|
+
/** Background color (hex or rgba) */
|
|
93
|
+
color: string;
|
|
94
|
+
/** Background opacity (0-1), default 1 */
|
|
95
|
+
opacity?: number;
|
|
96
|
+
/** Padding around text as percentage of overlay size */
|
|
97
|
+
padding?: {
|
|
98
|
+
x: number;
|
|
99
|
+
y: number;
|
|
100
|
+
};
|
|
101
|
+
/** Independent scale multiplier for background plane (default 1.0) */
|
|
102
|
+
scale?: number;
|
|
103
|
+
/** Corner radius in pixels */
|
|
104
|
+
borderRadius?: number;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Text offset within the background plane
|
|
108
|
+
* Allows positioning text independently from its background
|
|
109
|
+
*/
|
|
110
|
+
textOffset?: {
|
|
111
|
+
/** Horizontal offset as percentage of background width (-50 to 50) */
|
|
112
|
+
x: number;
|
|
113
|
+
/** Vertical offset as percentage of background height (-50 to 50) */
|
|
114
|
+
y: number;
|
|
115
|
+
};
|
|
116
|
+
/** @deprecated Use background.color instead */
|
|
117
|
+
backgroundColor?: string;
|
|
118
|
+
}
|
|
119
|
+
export interface EmojiContent {
|
|
120
|
+
emoji: string;
|
|
121
|
+
size: number;
|
|
122
|
+
}
|
|
123
|
+
export interface ShapeContent {
|
|
124
|
+
shape: 'rectangle' | 'circle' | 'arrow';
|
|
125
|
+
fillColor: string;
|
|
126
|
+
fillOpacity: number;
|
|
127
|
+
strokeColor: string;
|
|
128
|
+
strokeWidth: number;
|
|
129
|
+
cornerRadius?: number;
|
|
130
|
+
}
|
|
131
|
+
export interface ImageContent {
|
|
132
|
+
src: string;
|
|
133
|
+
alt?: string;
|
|
134
|
+
fit: 'contain' | 'cover' | 'fill';
|
|
135
|
+
opacity?: number;
|
|
136
|
+
borderRadius?: number;
|
|
137
|
+
/** Optional click URL to make the image clickable */
|
|
138
|
+
clickUrl?: string;
|
|
139
|
+
}
|
|
140
|
+
export interface CTAContent {
|
|
141
|
+
text: string;
|
|
142
|
+
url: string;
|
|
143
|
+
newTab: boolean;
|
|
144
|
+
style: {
|
|
145
|
+
backgroundColor: string;
|
|
146
|
+
textColor: string;
|
|
147
|
+
borderRadius: number;
|
|
148
|
+
fontSize: number;
|
|
149
|
+
fontWeight: 'normal' | 'bold';
|
|
150
|
+
padding: {
|
|
151
|
+
x: number;
|
|
152
|
+
y: number;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
hoverStyle?: {
|
|
156
|
+
backgroundColor?: string;
|
|
157
|
+
textColor?: string;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Sprite sequence overlay content for animated image sequences
|
|
162
|
+
*
|
|
163
|
+
* Renders pre-rendered image sequences (sprite sheets) as animated overlays.
|
|
164
|
+
* Supports both grid layouts (columns × rows) and horizontal strips.
|
|
165
|
+
*
|
|
166
|
+
* Animation is driven by CSS background-position, independent of video FPS.
|
|
167
|
+
*
|
|
168
|
+
* @example Grid layout (4×4 = 16 frames):
|
|
169
|
+
* { frameWidth: 256, frameHeight: 256, frameCount: 16, columns: 4 }
|
|
170
|
+
*
|
|
171
|
+
* @example Horizontal strip (12 frames in a row):
|
|
172
|
+
* { frameWidth: 128, frameHeight: 128, frameCount: 12, columns: 12 }
|
|
173
|
+
*/
|
|
174
|
+
export interface SpriteSequenceContent {
|
|
175
|
+
/**
|
|
176
|
+
* URL to the sprite sheet image
|
|
177
|
+
* Supports R2 upload URLs or external URLs
|
|
178
|
+
*/
|
|
179
|
+
spritesheetUrl: string;
|
|
180
|
+
/** Width of a single frame in pixels */
|
|
181
|
+
frameWidth: number;
|
|
182
|
+
/** Height of a single frame in pixels */
|
|
183
|
+
frameHeight: number;
|
|
184
|
+
/** Total number of frames in the sprite sheet */
|
|
185
|
+
frameCount: number;
|
|
186
|
+
/**
|
|
187
|
+
* Number of frames per row (columns)
|
|
188
|
+
* - For grid layout: columns × rows = frameCount
|
|
189
|
+
* - For horizontal strip: columns = frameCount
|
|
190
|
+
*/
|
|
191
|
+
columns: number;
|
|
192
|
+
/**
|
|
193
|
+
* Sprite animation frames per second
|
|
194
|
+
* Independent of video FPS - sprite animates at its own rate
|
|
195
|
+
*/
|
|
196
|
+
framesPerSecond: number;
|
|
197
|
+
/** Loop the animation (default: true) */
|
|
198
|
+
loop: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Play forward then backward (ping-pong)
|
|
201
|
+
* When true: 0,1,2,3,2,1,0,1,2...
|
|
202
|
+
*/
|
|
203
|
+
pingPong?: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Which frame to start on (0-indexed, default: 0)
|
|
206
|
+
*/
|
|
207
|
+
startFrame?: number;
|
|
208
|
+
/** Opacity 0-1 (default: 1) */
|
|
209
|
+
opacity?: number;
|
|
210
|
+
/**
|
|
211
|
+
* CSS filter for color tinting
|
|
212
|
+
* Example: "hue-rotate(90deg)" or "sepia(1) saturate(5) hue-rotate(300deg)"
|
|
213
|
+
*/
|
|
214
|
+
tintFilter?: string;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Video overlay content - for WebM/MP4 with alpha channel support
|
|
218
|
+
* Used for motion graphics, animated effects, and video compositing
|
|
219
|
+
*/
|
|
220
|
+
export interface VideoContent {
|
|
221
|
+
/**
|
|
222
|
+
* URL to the video file
|
|
223
|
+
* Supports WebM (VP9 with alpha), MP4, or any browser-supported format
|
|
224
|
+
*/
|
|
225
|
+
videoUrl: string;
|
|
226
|
+
/** Loop the video (default: true) */
|
|
227
|
+
loop: boolean;
|
|
228
|
+
/** Mute the video audio (default: true for motion graphics) */
|
|
229
|
+
muted: boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Playback rate (1.0 = normal speed)
|
|
232
|
+
* Range: 0.25 to 4.0
|
|
233
|
+
*/
|
|
234
|
+
playbackRate?: number;
|
|
235
|
+
/**
|
|
236
|
+
* Start time offset in seconds
|
|
237
|
+
* Use to skip to a specific part of the video
|
|
238
|
+
*/
|
|
239
|
+
startTime?: number;
|
|
240
|
+
/** Opacity 0-1 (default: 1) */
|
|
241
|
+
opacity?: number;
|
|
242
|
+
/** Object fit mode for video within container */
|
|
243
|
+
fit?: 'contain' | 'cover' | 'fill';
|
|
244
|
+
/**
|
|
245
|
+
* CSS filter for color effects
|
|
246
|
+
* Example: "brightness(1.2)" or "hue-rotate(90deg)"
|
|
247
|
+
*/
|
|
248
|
+
filter?: string;
|
|
249
|
+
}
|
|
250
|
+
export type OverlayContent = TextContent | EmojiContent | ShapeContent | ImageContent | CTAContent | SpriteSequenceContent | VideoContent;
|
|
251
|
+
export interface OverlayPosition {
|
|
252
|
+
x: number;
|
|
253
|
+
y: number;
|
|
254
|
+
width: number;
|
|
255
|
+
height: number;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Animation entrance/exit type
|
|
259
|
+
* - 'none': No animation (instant appear/disappear)
|
|
260
|
+
* - 'fade': Opacity fade (current default)
|
|
261
|
+
* - 'slide-left': Slide in from left / out to left
|
|
262
|
+
* - 'slide-right': Slide in from right / out to right
|
|
263
|
+
* - 'slide-top': Slide in from top / out to top
|
|
264
|
+
* - 'slide-bottom': Slide in from bottom / out to bottom
|
|
265
|
+
*/
|
|
266
|
+
export type AnimationType = 'none' | 'fade' | 'scale' | 'slide-left' | 'slide-right' | 'slide-top' | 'slide-bottom';
|
|
267
|
+
export interface OverlayAnimation {
|
|
268
|
+
opacity: number;
|
|
269
|
+
fadeIn: number;
|
|
270
|
+
fadeOut: number;
|
|
271
|
+
/** Entrance animation type (default: 'fade') */
|
|
272
|
+
entranceType?: AnimationType;
|
|
273
|
+
/** Exit animation type (default: 'fade') */
|
|
274
|
+
exitType?: AnimationType;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Corner point in normalized coordinates (0-1 range)
|
|
278
|
+
* Relative to the video content area
|
|
279
|
+
*/
|
|
280
|
+
export interface CornerPoint {
|
|
281
|
+
x: number;
|
|
282
|
+
y: number;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Corner offset - relative adjustment from the natural corner position
|
|
286
|
+
* Values are in percentage of the overlay's dimensions
|
|
287
|
+
*/
|
|
288
|
+
export interface CornerOffset {
|
|
289
|
+
dx: number;
|
|
290
|
+
dy: number;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Four corner offsets for perspective fine-tuning
|
|
294
|
+
* These are RELATIVE adjustments on top of the overlay's position/size
|
|
295
|
+
*/
|
|
296
|
+
export interface CornerOffsets {
|
|
297
|
+
tl: CornerOffset;
|
|
298
|
+
tr: CornerOffset;
|
|
299
|
+
br: CornerOffset;
|
|
300
|
+
bl: CornerOffset;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Four corners defining perspective quad (absolute positions)
|
|
304
|
+
* Order: top-left, top-right, bottom-right, bottom-left (clockwise)
|
|
305
|
+
* @deprecated Use CornerOffsets for new code - corners are computed from position + offsets
|
|
306
|
+
*/
|
|
307
|
+
export interface CornerPoints {
|
|
308
|
+
tl: CornerPoint;
|
|
309
|
+
tr: CornerPoint;
|
|
310
|
+
br: CornerPoint;
|
|
311
|
+
bl: CornerPoint;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Perspective transform configuration for corner pinning
|
|
315
|
+
*
|
|
316
|
+
* Corner pinning is a FINE-TUNING layer on top of regular transforms:
|
|
317
|
+
* 1. Position/scale/rotate sets the base overlay bounds
|
|
318
|
+
* 2. Corner offsets apply small perspective adjustments
|
|
319
|
+
*
|
|
320
|
+
* @see https://github.com/uMe-Group/Includu/issues/58
|
|
321
|
+
*/
|
|
322
|
+
export interface PerspectiveTransform {
|
|
323
|
+
/** Whether perspective transform is enabled */
|
|
324
|
+
enabled: boolean;
|
|
325
|
+
/**
|
|
326
|
+
* Corner offsets - relative adjustments from natural corner positions
|
|
327
|
+
* Values are percentages of the overlay's dimensions
|
|
328
|
+
* Default: all zeros (no perspective adjustment)
|
|
329
|
+
* Optional for backward compatibility - if missing, use corners or default to zeros
|
|
330
|
+
*/
|
|
331
|
+
cornerOffsets?: CornerOffsets;
|
|
332
|
+
/**
|
|
333
|
+
* @deprecated Use cornerOffsets instead
|
|
334
|
+
* Kept for backward compatibility with existing saved projects
|
|
335
|
+
*/
|
|
336
|
+
corners?: CornerPoints;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Creates default corner offsets (no perspective adjustment)
|
|
340
|
+
*/
|
|
341
|
+
export declare function createDefaultCornerOffsets(): CornerOffsets;
|
|
342
|
+
/**
|
|
343
|
+
* Computes absolute corner positions from overlay position and corner offsets
|
|
344
|
+
* This is how corners are calculated for rendering
|
|
345
|
+
*/
|
|
346
|
+
export declare function computeCornersFromOffsets(position: OverlayPosition, offsets: CornerOffsets): CornerPoints;
|
|
347
|
+
/**
|
|
348
|
+
* @deprecated Use createDefaultCornerOffsets instead
|
|
349
|
+
* Creates default corner points for a rectangular overlay
|
|
350
|
+
* Uses the overlay's position to calculate initial corner positions
|
|
351
|
+
*/
|
|
352
|
+
export declare function createDefaultCornerPoints(position: OverlayPosition): CornerPoints;
|
|
353
|
+
/**
|
|
354
|
+
* Migrate old absolute corners to new offset-based format
|
|
355
|
+
* Call this when loading projects with old corner format
|
|
356
|
+
*/
|
|
357
|
+
export declare function migrateToCornerOffsets(position: OverlayPosition, corners: CornerPoints): CornerOffsets;
|
|
358
|
+
export interface Overlay {
|
|
359
|
+
id: string;
|
|
360
|
+
/** Display name in the timeline */
|
|
361
|
+
label: string;
|
|
362
|
+
type: OverlayType;
|
|
363
|
+
/** Which timeline track this overlay belongs to (default: 'overlays') */
|
|
364
|
+
track?: OverlayTrack;
|
|
365
|
+
/** First frame where overlay is visible (inclusive) */
|
|
366
|
+
startFrame: number;
|
|
367
|
+
/** First frame where overlay is NOT visible (exclusive) */
|
|
368
|
+
endFrame: number;
|
|
369
|
+
/** Timeline bar color */
|
|
370
|
+
color?: string;
|
|
371
|
+
position: OverlayPosition;
|
|
372
|
+
animation: OverlayAnimation;
|
|
373
|
+
content: OverlayContent;
|
|
374
|
+
/** Optional perspective transform for corner pinning */
|
|
375
|
+
perspective?: PerspectiveTransform;
|
|
376
|
+
/**
|
|
377
|
+
* Z-axis rotation in degrees (0-360)
|
|
378
|
+
* Only applied when rotationEnabled is true
|
|
379
|
+
*/
|
|
380
|
+
rotation?: number;
|
|
381
|
+
/**
|
|
382
|
+
* X-axis rotation in degrees (-60 to +60)
|
|
383
|
+
* Tilts forward/backward (CSS rotateX)
|
|
384
|
+
* Only applied when rotationEnabled is true
|
|
385
|
+
*/
|
|
386
|
+
rotationX?: number;
|
|
387
|
+
/**
|
|
388
|
+
* Y-axis rotation in degrees (-60 to +60)
|
|
389
|
+
* Tilts left/right (CSS rotateY)
|
|
390
|
+
* Only applied when rotationEnabled is true
|
|
391
|
+
*/
|
|
392
|
+
rotationY?: number;
|
|
393
|
+
/**
|
|
394
|
+
* Whether rotation is enabled (opt-in toggle)
|
|
395
|
+
* Default: false
|
|
396
|
+
*/
|
|
397
|
+
rotationEnabled?: boolean;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Video source reference stored with a project.
|
|
401
|
+
* Supports VMS (Cloudflare Stream), local, and R2 sources.
|
|
402
|
+
*/
|
|
403
|
+
export interface VideoSource {
|
|
404
|
+
type: 'vms' | 'local' | 'r2';
|
|
405
|
+
vmsClipId?: string;
|
|
406
|
+
vmsStreamUid?: string;
|
|
407
|
+
vmsHlsUrl?: string;
|
|
408
|
+
vmsTitle?: string;
|
|
409
|
+
vmsThumbnail?: string;
|
|
410
|
+
vmsWidth?: number;
|
|
411
|
+
vmsHeight?: number;
|
|
412
|
+
r2Key?: string;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Per-project monetization settings (creator-defined).
|
|
416
|
+
* Distinct from MonetizationConfig which is the published version.
|
|
417
|
+
*/
|
|
418
|
+
export interface MonetizationSettings {
|
|
419
|
+
enabled: boolean;
|
|
420
|
+
revenueShare?: number;
|
|
421
|
+
restrictions?: AdRestrictions;
|
|
422
|
+
/** Whether 3D ads (Layer 2) are enabled */
|
|
423
|
+
layer2Enabled?: boolean;
|
|
424
|
+
/** Whether 2D ads are enabled */
|
|
425
|
+
layer2DEnabled?: boolean;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Metadata for multipart upload requests
|
|
429
|
+
*/
|
|
430
|
+
export interface UploadMetadata {
|
|
431
|
+
projectId: string;
|
|
432
|
+
filename: string;
|
|
433
|
+
contentType: string;
|
|
434
|
+
size: number;
|
|
435
|
+
type: 'video' | 'proxy';
|
|
436
|
+
}
|
|
437
|
+
/** Subscription/access tier for a creator */
|
|
438
|
+
export type CreatorTier = 'free' | 'pro' | 'enterprise';
|
|
439
|
+
/**
|
|
440
|
+
* A creator account — the unified identity across Includu and Admetise.
|
|
441
|
+
*
|
|
442
|
+
* Auth-agnostic: the account stores profile data only.
|
|
443
|
+
* Authentication is handled externally (Cloudflare Access today, social login later).
|
|
444
|
+
*
|
|
445
|
+
* KV key patterns:
|
|
446
|
+
* - `creator:{id}` — primary record
|
|
447
|
+
* - `creator-email:{email}` — email → id index
|
|
448
|
+
* - `creator-slug:{slug}` — slug → id index
|
|
449
|
+
*/
|
|
450
|
+
export interface CreatorAccount {
|
|
451
|
+
/** Unique creator ID (generated, URL-safe) */
|
|
452
|
+
id: string;
|
|
453
|
+
/** Email address (from auth provider, used as identity key) */
|
|
454
|
+
email: string;
|
|
455
|
+
/** Display name shown on channel pages and in the editor */
|
|
456
|
+
displayName: string;
|
|
457
|
+
/** URL-friendly slug for public channel (e.g., "jorgen" → play.includu.com/@jorgen) */
|
|
458
|
+
slug: string;
|
|
459
|
+
/** Avatar/profile image URL (R2 or external) */
|
|
460
|
+
avatarUrl?: string;
|
|
461
|
+
/** Short bio for channel pages */
|
|
462
|
+
bio?: string;
|
|
463
|
+
/** Subscription tier */
|
|
464
|
+
tier: CreatorTier;
|
|
465
|
+
/** Branding settings for published content */
|
|
466
|
+
branding?: CreatorBranding;
|
|
467
|
+
/** ISO 8601 */
|
|
468
|
+
createdAt: string;
|
|
469
|
+
/** ISO 8601 */
|
|
470
|
+
updatedAt: string;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Per-creator branding for published content.
|
|
474
|
+
* Stored on CreatorAccount, applied during publish.
|
|
475
|
+
*/
|
|
476
|
+
export interface CreatorBranding {
|
|
477
|
+
/** Logo URL (R2 or external) — shown on player */
|
|
478
|
+
logoUrl?: string;
|
|
479
|
+
/** Watermark URL (R2 or external) — overlaid on recordings */
|
|
480
|
+
watermarkUrl?: string;
|
|
481
|
+
/** Primary brand color (hex, e.g. "#E53935") */
|
|
482
|
+
brandColor?: string;
|
|
483
|
+
/** Whether to show branding on published content */
|
|
484
|
+
enabled: boolean;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* An Includu project - a set of overlay events for a video clip.
|
|
488
|
+
* This is the runtime storage format used by the API worker and KV store.
|
|
489
|
+
*/
|
|
490
|
+
export interface Project {
|
|
491
|
+
id: string;
|
|
492
|
+
name: string;
|
|
493
|
+
/** Creator who owns this project (absent on legacy projects) */
|
|
494
|
+
creatorId?: string;
|
|
495
|
+
createdAt: string;
|
|
496
|
+
updatedAt: string;
|
|
497
|
+
/** R2 key for uploaded video (legacy) */
|
|
498
|
+
videoKey?: string;
|
|
499
|
+
/** R2 key for proxy video (legacy) */
|
|
500
|
+
proxyKey?: string;
|
|
501
|
+
/** Frames per second for timeline */
|
|
502
|
+
fps: number;
|
|
503
|
+
/** Video duration in seconds */
|
|
504
|
+
duration: number;
|
|
505
|
+
/** Overlay events */
|
|
506
|
+
overlays: Overlay[];
|
|
507
|
+
/** Video source reference */
|
|
508
|
+
videoSource?: VideoSource;
|
|
509
|
+
/** Ad slot placements (template-based, preferred) */
|
|
510
|
+
adPlacements?: AdSlotPlacement[];
|
|
511
|
+
/** @deprecated Use adPlacements instead - kept for backwards compatibility */
|
|
512
|
+
adSlots?: AdSlot[];
|
|
513
|
+
/** Monetization settings */
|
|
514
|
+
monetization?: MonetizationSettings;
|
|
515
|
+
/** Layer 2: 3D Composite scene. null explicitly clears the field. */
|
|
516
|
+
layer2Scene?: import('./layer2').Layer2Scene | null;
|
|
517
|
+
}
|
|
518
|
+
export interface PaginatedResponse<T> {
|
|
519
|
+
items: T[];
|
|
520
|
+
total: number;
|
|
521
|
+
page: number;
|
|
522
|
+
pageSize: number;
|
|
523
|
+
hasMore: boolean;
|
|
524
|
+
}
|
|
525
|
+
export interface ApiError {
|
|
526
|
+
error: string;
|
|
527
|
+
message: string;
|
|
528
|
+
status: number;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* An overlay as stored in a published project
|
|
532
|
+
*/
|
|
533
|
+
export interface PublishedOverlay {
|
|
534
|
+
id: string;
|
|
535
|
+
type: OverlayType;
|
|
536
|
+
/** First frame where overlay is visible (inclusive) */
|
|
537
|
+
startFrame: number;
|
|
538
|
+
/** First frame where overlay is NOT visible (exclusive) */
|
|
539
|
+
endFrame: number;
|
|
540
|
+
position: OverlayPosition;
|
|
541
|
+
animation: OverlayAnimation;
|
|
542
|
+
content: OverlayContent;
|
|
543
|
+
/** Optional perspective transform for corner pinning */
|
|
544
|
+
perspective?: PerspectiveTransform;
|
|
545
|
+
/** Z-axis rotation in degrees (0-360) */
|
|
546
|
+
rotation?: number;
|
|
547
|
+
/** X-axis rotation in degrees (-60 to +60) */
|
|
548
|
+
rotationX?: number;
|
|
549
|
+
/** Y-axis rotation in degrees (-60 to +60) */
|
|
550
|
+
rotationY?: number;
|
|
551
|
+
/** Whether rotation is enabled */
|
|
552
|
+
rotationEnabled?: boolean;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* A published (immutable) version of a project for end-user playback
|
|
556
|
+
*/
|
|
557
|
+
export interface PublishedProject {
|
|
558
|
+
/** Unique publish ID (nanoid, 10 chars) */
|
|
559
|
+
publishId: string;
|
|
560
|
+
/** Source project UUID */
|
|
561
|
+
projectId: string;
|
|
562
|
+
/** Display name */
|
|
563
|
+
name: string;
|
|
564
|
+
/** Video source information */
|
|
565
|
+
video: {
|
|
566
|
+
hlsUrl: string;
|
|
567
|
+
duration: number;
|
|
568
|
+
thumbnail?: string;
|
|
569
|
+
aspectRatio?: string;
|
|
570
|
+
};
|
|
571
|
+
/** Frames per second */
|
|
572
|
+
fps: number;
|
|
573
|
+
/** Overlay events */
|
|
574
|
+
overlays: PublishedOverlay[];
|
|
575
|
+
/** Publication timestamp (ISO 8601) */
|
|
576
|
+
publishedAt: string;
|
|
577
|
+
/** Publisher identifier (email or user ID) */
|
|
578
|
+
publishedBy: string;
|
|
579
|
+
/** Version number for tracking republishes */
|
|
580
|
+
version: number;
|
|
581
|
+
/** Optional branding configuration */
|
|
582
|
+
branding?: {
|
|
583
|
+
logo?: string;
|
|
584
|
+
accentColor?: string;
|
|
585
|
+
showPoweredBy?: boolean;
|
|
586
|
+
};
|
|
587
|
+
/** Monetization configuration (optional, for Admetise integration) */
|
|
588
|
+
monetization?: MonetizationConfig;
|
|
589
|
+
/** Layer 2 (3D composite) scene data */
|
|
590
|
+
layer2Scene?: import('./layer2').Layer2Scene;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Public manifest returned by the API for player consumption
|
|
594
|
+
*/
|
|
595
|
+
export interface PublishedManifest {
|
|
596
|
+
publishId: string;
|
|
597
|
+
name: string;
|
|
598
|
+
video: {
|
|
599
|
+
hlsUrl: string;
|
|
600
|
+
duration: number;
|
|
601
|
+
thumbnail?: string;
|
|
602
|
+
aspectRatio?: string;
|
|
603
|
+
};
|
|
604
|
+
fps: number;
|
|
605
|
+
overlays: PublishedOverlay[];
|
|
606
|
+
branding?: {
|
|
607
|
+
logo?: string;
|
|
608
|
+
accentColor?: string;
|
|
609
|
+
showPoweredBy?: boolean;
|
|
610
|
+
};
|
|
611
|
+
links: {
|
|
612
|
+
player: string;
|
|
613
|
+
embed: string;
|
|
614
|
+
embedCode: string;
|
|
615
|
+
/** Participation URL (only if participation is enabled) */
|
|
616
|
+
participate?: string;
|
|
617
|
+
};
|
|
618
|
+
/** Monetization configuration (optional, for Admetise integration) */
|
|
619
|
+
monetization?: MonetizationConfig;
|
|
620
|
+
/** Layer 2 (3D composite) scene data */
|
|
621
|
+
layer2Scene?: import('./layer2').Layer2Scene;
|
|
622
|
+
/** Layer 2 player options */
|
|
623
|
+
layer2Options?: {
|
|
624
|
+
/** Show 3D ads in view-only mode (when not participating) */
|
|
625
|
+
show3DAdsInViewMode?: boolean;
|
|
626
|
+
/** Show participation preview silhouette for non-participants */
|
|
627
|
+
showParticipationPreview?: boolean;
|
|
628
|
+
};
|
|
629
|
+
/**
|
|
630
|
+
* Creator's webcam runtime settings for preview mode.
|
|
631
|
+
* When present, the player pre-loads these settings so the creator
|
|
632
|
+
* can instantly see their work without reconfiguring from scratch.
|
|
633
|
+
* Only set during preview, never during publish.
|
|
634
|
+
*/
|
|
635
|
+
previewWebcamSettings?: import('./layer2').PreviewWebcamSettings;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Session metadata for a recorded participation.
|
|
639
|
+
*
|
|
640
|
+
* Captures everything needed to re-publish the participant's recording
|
|
641
|
+
* as a new monetizable version with dynamic overlays and ads.
|
|
642
|
+
*
|
|
643
|
+
* Classify an overlay for recording: should it be burned into the video
|
|
644
|
+
* (static visual) or kept as dynamic metadata (interactive/monetizable)?
|
|
645
|
+
*
|
|
646
|
+
* Some overlays (e.g., clickable images) are BOTH — burned visually into
|
|
647
|
+
* the recording but also preserved as dynamic metadata so their click URL
|
|
648
|
+
* can be restored when re-publishing.
|
|
649
|
+
*/
|
|
650
|
+
export declare function classifyOverlayForRecording(overlay: PublishedOverlay): {
|
|
651
|
+
burnable: boolean;
|
|
652
|
+
dynamic: boolean;
|
|
653
|
+
};
|
|
654
|
+
/**
|
|
655
|
+
* Session metadata for a participation recording.
|
|
656
|
+
*
|
|
657
|
+
* PRINCIPLES:
|
|
658
|
+
* - Static visual overlays (text, images, shapes) are BURNED into the recording
|
|
659
|
+
* - Interactive/monetizable overlays (CTAs) are stored as DYNAMIC REFERENCES
|
|
660
|
+
* - This preserves the content creator's ability to:
|
|
661
|
+
* - Update CTA links, ad content, and text after the fact
|
|
662
|
+
* - Serve different ads to different viewers
|
|
663
|
+
* - Monetize derivative content through revenue sharing
|
|
664
|
+
* - Keep interactive elements (clickable CTAs) working
|
|
665
|
+
*/
|
|
666
|
+
export interface SessionMetadata {
|
|
667
|
+
/** Schema version for forward compatibility */
|
|
668
|
+
version: 1;
|
|
669
|
+
/** When the recording was made (ISO 8601) */
|
|
670
|
+
recordedAt: string;
|
|
671
|
+
/** Recording duration in ms */
|
|
672
|
+
durationMs: number;
|
|
673
|
+
/** Output format */
|
|
674
|
+
format: {
|
|
675
|
+
mimeType: string;
|
|
676
|
+
codec: string;
|
|
677
|
+
};
|
|
678
|
+
/** Output resolution */
|
|
679
|
+
resolution: {
|
|
680
|
+
width: number;
|
|
681
|
+
height: number;
|
|
682
|
+
};
|
|
683
|
+
/** Recording FPS (matches source video) */
|
|
684
|
+
fps: number;
|
|
685
|
+
/** Background video reference (for re-compositing) */
|
|
686
|
+
background: {
|
|
687
|
+
hlsUrl: string;
|
|
688
|
+
startTimeMs: number;
|
|
689
|
+
durationMs: number;
|
|
690
|
+
aspectRatio: string;
|
|
691
|
+
};
|
|
692
|
+
/** Webcam composite settings (Gausst coordinates) */
|
|
693
|
+
participation: {
|
|
694
|
+
position: [number, number, number];
|
|
695
|
+
rotation: [number, number, number];
|
|
696
|
+
scale: number;
|
|
697
|
+
framingType: string;
|
|
698
|
+
backgroundMethod: string;
|
|
699
|
+
};
|
|
700
|
+
/**
|
|
701
|
+
* Overlay definitions — stored as REFERENCES, not burned in.
|
|
702
|
+
* These enable re-publishing with dynamic, editable, monetizable overlays.
|
|
703
|
+
*/
|
|
704
|
+
overlayDefinitions: Array<{
|
|
705
|
+
id: string;
|
|
706
|
+
type: string;
|
|
707
|
+
startFrame: number;
|
|
708
|
+
endFrame: number;
|
|
709
|
+
position: {
|
|
710
|
+
x: number;
|
|
711
|
+
y: number;
|
|
712
|
+
width: number;
|
|
713
|
+
height: number;
|
|
714
|
+
};
|
|
715
|
+
content: unknown;
|
|
716
|
+
}>;
|
|
717
|
+
/** 3D ad placement references — dynamic, can be swapped/updated */
|
|
718
|
+
adPlacements: Array<{
|
|
719
|
+
id: string;
|
|
720
|
+
startFrame: number;
|
|
721
|
+
endFrame: number;
|
|
722
|
+
position: [number, number, number];
|
|
723
|
+
rotation: [number, number, number];
|
|
724
|
+
scale: number;
|
|
725
|
+
}>;
|
|
726
|
+
/** Camera settings (Gausst coordinate system) */
|
|
727
|
+
camera: {
|
|
728
|
+
fov: number;
|
|
729
|
+
position: [number, number, number];
|
|
730
|
+
rotation: [number, number, number];
|
|
731
|
+
};
|
|
732
|
+
/** Source manifest reference */
|
|
733
|
+
sourceManifest: {
|
|
734
|
+
publishId: string;
|
|
735
|
+
name: string;
|
|
736
|
+
fps: number;
|
|
737
|
+
};
|
|
738
|
+
/** Whether audio was captured */
|
|
739
|
+
hasAudio: boolean;
|
|
740
|
+
/**
|
|
741
|
+
* Overlays that were burned into the recording video track.
|
|
742
|
+
* These are static visual overlays (text, images, shapes, emoji).
|
|
743
|
+
*/
|
|
744
|
+
burnedOverlays?: Array<{
|
|
745
|
+
id: string;
|
|
746
|
+
type: string;
|
|
747
|
+
startFrame: number;
|
|
748
|
+
endFrame: number;
|
|
749
|
+
position: {
|
|
750
|
+
x: number;
|
|
751
|
+
y: number;
|
|
752
|
+
width: number;
|
|
753
|
+
height: number;
|
|
754
|
+
};
|
|
755
|
+
content: unknown;
|
|
756
|
+
}>;
|
|
757
|
+
/**
|
|
758
|
+
* Dynamic overlays NOT burned in — interactive/monetizable.
|
|
759
|
+
* CTAs and clickable images are kept as references for re-publishing.
|
|
760
|
+
*/
|
|
761
|
+
dynamicOverlays?: Array<{
|
|
762
|
+
id: string;
|
|
763
|
+
type: string;
|
|
764
|
+
startFrame: number;
|
|
765
|
+
endFrame: number;
|
|
766
|
+
position: {
|
|
767
|
+
x: number;
|
|
768
|
+
y: number;
|
|
769
|
+
width: number;
|
|
770
|
+
height: number;
|
|
771
|
+
};
|
|
772
|
+
content: unknown;
|
|
773
|
+
}>;
|
|
774
|
+
/**
|
|
775
|
+
* Multi-camera shot cuts during the recording window.
|
|
776
|
+
* Each entry marks a camera/webcam transform change at a frame offset.
|
|
777
|
+
* Enables NLE editors to recreate camera switches in post-production.
|
|
778
|
+
*/
|
|
779
|
+
shotCuts?: Array<{
|
|
780
|
+
/** Frame offset relative to recording start (0 = first frame) */
|
|
781
|
+
frameOffset: number;
|
|
782
|
+
/** Shot preset ID from the published manifest */
|
|
783
|
+
presetId: string;
|
|
784
|
+
/** Camera settings at this cut */
|
|
785
|
+
camera: {
|
|
786
|
+
fov: number;
|
|
787
|
+
position: [number, number, number];
|
|
788
|
+
rotation: [number, number, number];
|
|
789
|
+
};
|
|
790
|
+
/** Webcam transform at this cut (if different from base) */
|
|
791
|
+
webcamTransform?: {
|
|
792
|
+
position: [number, number, number];
|
|
793
|
+
rotation: [number, number, number];
|
|
794
|
+
scale: number;
|
|
795
|
+
};
|
|
796
|
+
}>;
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Recording tier determines duration and size limits.
|
|
800
|
+
*
|
|
801
|
+
* Tier is inherited from the creator's account plan (stored on the published
|
|
802
|
+
* manifest). Until creator accounts (#134, #136) are implemented, all
|
|
803
|
+
* recordings default to 'standard'.
|
|
804
|
+
*
|
|
805
|
+
* Access model: recordings are "unlisted" — accessible by anyone with the
|
|
806
|
+
* 12-character random recordingId URL, but not discoverable via browsing
|
|
807
|
+
* or search. Similar to YouTube unlisted videos.
|
|
808
|
+
*/
|
|
809
|
+
export type RecordingTier = 'free' | 'standard' | 'professional';
|
|
810
|
+
export interface RecordingTierLimits {
|
|
811
|
+
/** Maximum recording duration in milliseconds */
|
|
812
|
+
maxDurationMs: number;
|
|
813
|
+
/** Maximum file size in bytes */
|
|
814
|
+
maxFileSize: number;
|
|
815
|
+
/** Human-readable label */
|
|
816
|
+
label: string;
|
|
817
|
+
}
|
|
818
|
+
export declare const RECORDING_TIER_LIMITS: Record<RecordingTier, RecordingTierLimits>;
|
|
819
|
+
/**
|
|
820
|
+
* Stored manifest for a participant recording.
|
|
821
|
+
* Saved in KV when a participant uploads their recording.
|
|
822
|
+
*/
|
|
823
|
+
export interface RecordingManifest {
|
|
824
|
+
/** Unique recording identifier */
|
|
825
|
+
recordingId: string;
|
|
826
|
+
/** Published video this recording was made against */
|
|
827
|
+
publishId: string;
|
|
828
|
+
/** Participant display name (optional) */
|
|
829
|
+
participantName?: string;
|
|
830
|
+
/** When the recording was uploaded (ISO 8601) */
|
|
831
|
+
uploadedAt: string;
|
|
832
|
+
/** Recording duration in ms */
|
|
833
|
+
durationMs: number;
|
|
834
|
+
/** File size in bytes */
|
|
835
|
+
fileSizeBytes: number;
|
|
836
|
+
/** Output format */
|
|
837
|
+
format: {
|
|
838
|
+
mimeType: string;
|
|
839
|
+
codec: string;
|
|
840
|
+
extension: string;
|
|
841
|
+
};
|
|
842
|
+
/** Output resolution */
|
|
843
|
+
resolution: {
|
|
844
|
+
width: number;
|
|
845
|
+
height: number;
|
|
846
|
+
};
|
|
847
|
+
/** Whether audio was captured */
|
|
848
|
+
hasAudio: boolean;
|
|
849
|
+
/** R2 key for the video file */
|
|
850
|
+
videoKey: string;
|
|
851
|
+
/** R2 key for the session metadata JSON */
|
|
852
|
+
metadataKey: string;
|
|
853
|
+
/** Full session metadata for re-compositing */
|
|
854
|
+
sessionMetadata: SessionMetadata;
|
|
855
|
+
/** Recording tier (determines duration/size limits) */
|
|
856
|
+
tier?: RecordingTier;
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Type of ad placement slot
|
|
860
|
+
*/
|
|
861
|
+
export type AdSlotType = 'preroll' | 'midroll' | 'postroll' | 'overlay' | 'companion';
|
|
862
|
+
/**
|
|
863
|
+
* Position for overlay/companion ad slots
|
|
864
|
+
*/
|
|
865
|
+
export type AdSlotPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
|
|
866
|
+
/**
|
|
867
|
+
* Category of ad template
|
|
868
|
+
*/
|
|
869
|
+
export type AdTemplateCategory = 'video' | 'display' | 'companion';
|
|
870
|
+
/**
|
|
871
|
+
* Ad slot template defined and managed by Admetise
|
|
872
|
+
*
|
|
873
|
+
* This is the SOURCE OF TRUTH for ad formats. Admetise defines what
|
|
874
|
+
* ad placements are available, and Includu content creators select
|
|
875
|
+
* from these templates when placing ads in their content.
|
|
876
|
+
*
|
|
877
|
+
* Templates follow IAB standards where applicable.
|
|
878
|
+
*
|
|
879
|
+
* @see https://github.com/uMe-Group/Includu/issues/47
|
|
880
|
+
*/
|
|
881
|
+
export interface AdSlotTemplate {
|
|
882
|
+
/** Unique template identifier (e.g., "iab-medium-rectangle") */
|
|
883
|
+
id: string;
|
|
884
|
+
/** Display name (e.g., "Medium Rectangle (300×250)") */
|
|
885
|
+
name: string;
|
|
886
|
+
/** Description of the ad format */
|
|
887
|
+
description: string;
|
|
888
|
+
/** Type of ad placement */
|
|
889
|
+
type: AdSlotType;
|
|
890
|
+
/** Category for grouping in UI */
|
|
891
|
+
category: AdTemplateCategory;
|
|
892
|
+
/** Fixed width in pixels (for display/companion ads) */
|
|
893
|
+
width?: number;
|
|
894
|
+
/** Fixed height in pixels (for display/companion ads) */
|
|
895
|
+
height?: number;
|
|
896
|
+
/** Position for overlay ads */
|
|
897
|
+
position?: AdSlotPosition;
|
|
898
|
+
/** Default duration in seconds (for video ads) */
|
|
899
|
+
duration?: number;
|
|
900
|
+
/** Minimum duration in seconds */
|
|
901
|
+
minDuration?: number;
|
|
902
|
+
/** Maximum duration in seconds */
|
|
903
|
+
maxDuration?: number;
|
|
904
|
+
/** IAB standard size identifier (e.g., "300x250") */
|
|
905
|
+
iabSize?: string;
|
|
906
|
+
/** Whether this template is currently active/available */
|
|
907
|
+
active: boolean;
|
|
908
|
+
/** Sort order for UI display */
|
|
909
|
+
sortOrder?: number;
|
|
910
|
+
/** Icon identifier for UI */
|
|
911
|
+
icon?: string;
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Ad slot placement by content creator in Includu
|
|
915
|
+
*
|
|
916
|
+
* References a template from Admetise and adds timing information.
|
|
917
|
+
* The creator controls WHEN ads appear, not WHAT format they are.
|
|
918
|
+
*/
|
|
919
|
+
export interface AdSlotPlacement {
|
|
920
|
+
/** Unique placement identifier */
|
|
921
|
+
id: string;
|
|
922
|
+
/** Reference to AdSlotTemplate.id (from Admetise) */
|
|
923
|
+
templateId: string;
|
|
924
|
+
/** Frame number when ad should trigger (for midroll/overlay) */
|
|
925
|
+
triggerFrame?: number;
|
|
926
|
+
/** Percentage of video when ad should trigger (0-100) */
|
|
927
|
+
triggerPercent?: number;
|
|
928
|
+
/** Whether this placement is required (must show ad) */
|
|
929
|
+
required?: boolean;
|
|
930
|
+
/**
|
|
931
|
+
* Center position in normalized coordinates (0-1)
|
|
932
|
+
* Default: {x: 0.5, y: 0.5} (centered)
|
|
933
|
+
*/
|
|
934
|
+
position?: {
|
|
935
|
+
x: number;
|
|
936
|
+
y: number;
|
|
937
|
+
};
|
|
938
|
+
/**
|
|
939
|
+
* Scale factor relative to template size
|
|
940
|
+
* 1.0 = template size (minimum), max 3.0 (300%)
|
|
941
|
+
* Default: 1.0
|
|
942
|
+
*/
|
|
943
|
+
scale?: number;
|
|
944
|
+
/**
|
|
945
|
+
* Z-axis rotation in degrees (0-360)
|
|
946
|
+
* Only applied when rotationEnabled is true
|
|
947
|
+
* Default: 0
|
|
948
|
+
*/
|
|
949
|
+
rotation?: number;
|
|
950
|
+
/**
|
|
951
|
+
* X-axis rotation in degrees (-60 to +60)
|
|
952
|
+
* Tilts forward/backward (CSS rotateX)
|
|
953
|
+
* Only applied when rotationEnabled is true
|
|
954
|
+
* Default: 0
|
|
955
|
+
*/
|
|
956
|
+
rotationX?: number;
|
|
957
|
+
/**
|
|
958
|
+
* Y-axis rotation in degrees (-60 to +60)
|
|
959
|
+
* Tilts left/right (CSS rotateY)
|
|
960
|
+
* Only applied when rotationEnabled is true
|
|
961
|
+
* Default: 0
|
|
962
|
+
*/
|
|
963
|
+
rotationY?: number;
|
|
964
|
+
/**
|
|
965
|
+
* Whether rotation is enabled (opt-in toggle)
|
|
966
|
+
* Default: false
|
|
967
|
+
*/
|
|
968
|
+
rotationEnabled?: boolean;
|
|
969
|
+
/**
|
|
970
|
+
* Custom duration in seconds (creator override)
|
|
971
|
+
* Must be >= template.maxDuration (can only extend, not shrink)
|
|
972
|
+
* If not set, uses template.maxDuration
|
|
973
|
+
*/
|
|
974
|
+
customDuration?: number;
|
|
975
|
+
/**
|
|
976
|
+
* Perspective transform for corner pinning (opt-in)
|
|
977
|
+
* Enables placing ads on surfaces in video (billboards, screens, etc.)
|
|
978
|
+
* When enabled, overrides position/scale/rotation transforms
|
|
979
|
+
* @see https://github.com/uMe-Group/Includu/issues/58
|
|
980
|
+
*/
|
|
981
|
+
perspective?: PerspectiveTransform;
|
|
982
|
+
/**
|
|
983
|
+
* Animation settings for ad zone entrance/exit
|
|
984
|
+
* Similar to overlay animations but simplified
|
|
985
|
+
*/
|
|
986
|
+
animation?: {
|
|
987
|
+
/** Entrance animation type (default: 'none') */
|
|
988
|
+
entranceType?: AnimationType;
|
|
989
|
+
/** Exit animation type (default: 'none') */
|
|
990
|
+
exitType?: AnimationType;
|
|
991
|
+
/** Entrance animation duration in frames (default: 0) */
|
|
992
|
+
entranceFrames?: number;
|
|
993
|
+
/** Exit animation duration in frames (default: 0) */
|
|
994
|
+
exitFrames?: number;
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* @deprecated Use AdSlotPlacement instead. Kept for backwards compatibility.
|
|
999
|
+
*/
|
|
1000
|
+
export interface AdSlot {
|
|
1001
|
+
/** Unique slot identifier */
|
|
1002
|
+
id: string;
|
|
1003
|
+
/** Type of ad placement */
|
|
1004
|
+
type: AdSlotType;
|
|
1005
|
+
/** Position for overlay/companion slots */
|
|
1006
|
+
position?: AdSlotPosition;
|
|
1007
|
+
/** Slot width in pixels (for overlay/companion) */
|
|
1008
|
+
width?: number;
|
|
1009
|
+
/** Slot height in pixels (for overlay/companion) */
|
|
1010
|
+
height?: number;
|
|
1011
|
+
/** Frame number when midroll should trigger */
|
|
1012
|
+
triggerFrame?: number;
|
|
1013
|
+
/** Percentage of video when midroll should trigger (0-100) */
|
|
1014
|
+
triggerPercent?: number;
|
|
1015
|
+
/** Maximum ad duration in seconds */
|
|
1016
|
+
maxDuration?: number;
|
|
1017
|
+
/** Whether this slot must be filled with an ad */
|
|
1018
|
+
required?: boolean;
|
|
1019
|
+
/** Reference to template (new field for migration) */
|
|
1020
|
+
templateId?: string;
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Ad zone in Admetise (created when importing from Includu)
|
|
1024
|
+
*
|
|
1025
|
+
* Represents an actual ad placement that can be filled with campaign ads.
|
|
1026
|
+
* Created by importing content from Includu and resolving template references.
|
|
1027
|
+
*/
|
|
1028
|
+
export interface AdZone {
|
|
1029
|
+
/** Zone identifier (matches source placement ID) */
|
|
1030
|
+
id: string;
|
|
1031
|
+
/** Reference to the template used */
|
|
1032
|
+
templateId: string;
|
|
1033
|
+
/** Type of ad placement (from template) */
|
|
1034
|
+
type: AdSlotType;
|
|
1035
|
+
/** Whether this zone is active */
|
|
1036
|
+
enabled: boolean;
|
|
1037
|
+
/** Preset position for overlay/companion zones (from template, used as fallback) */
|
|
1038
|
+
presetPosition?: AdSlotPosition;
|
|
1039
|
+
/** Zone width in pixels (from template, used for aspect ratio) */
|
|
1040
|
+
width?: number;
|
|
1041
|
+
/** Zone height in pixels (from template, used for aspect ratio) */
|
|
1042
|
+
height?: number;
|
|
1043
|
+
/** Trigger time in seconds (converted from frames) */
|
|
1044
|
+
triggerTime?: number;
|
|
1045
|
+
/** Percentage of video to trigger (0-100) */
|
|
1046
|
+
triggerPercent?: number;
|
|
1047
|
+
/** VAST/VPAID ad tag URL (configured by advertiser) */
|
|
1048
|
+
adTagUrl?: string;
|
|
1049
|
+
/** Max duration in seconds (from template) */
|
|
1050
|
+
maxDuration?: number;
|
|
1051
|
+
/**
|
|
1052
|
+
* Center position in normalized coordinates (0-1)
|
|
1053
|
+
* Takes precedence over presetPosition when set
|
|
1054
|
+
*/
|
|
1055
|
+
centerPosition?: {
|
|
1056
|
+
x: number;
|
|
1057
|
+
y: number;
|
|
1058
|
+
};
|
|
1059
|
+
/**
|
|
1060
|
+
* Scale factor (1.0 = base size, max 3.0)
|
|
1061
|
+
*/
|
|
1062
|
+
scale?: number;
|
|
1063
|
+
/**
|
|
1064
|
+
* Z-axis rotation in degrees (0-360)
|
|
1065
|
+
* Only applied when rotationEnabled is true
|
|
1066
|
+
*/
|
|
1067
|
+
rotation?: number;
|
|
1068
|
+
/**
|
|
1069
|
+
* X-axis rotation in degrees (-60 to +60)
|
|
1070
|
+
* Tilts forward/backward (CSS rotateX)
|
|
1071
|
+
* Only applied when rotationEnabled is true
|
|
1072
|
+
*/
|
|
1073
|
+
rotationX?: number;
|
|
1074
|
+
/**
|
|
1075
|
+
* Y-axis rotation in degrees (-60 to +60)
|
|
1076
|
+
* Tilts left/right (CSS rotateY)
|
|
1077
|
+
* Only applied when rotationEnabled is true
|
|
1078
|
+
*/
|
|
1079
|
+
rotationY?: number;
|
|
1080
|
+
/**
|
|
1081
|
+
* Whether rotation is enabled
|
|
1082
|
+
*/
|
|
1083
|
+
rotationEnabled?: boolean;
|
|
1084
|
+
/**
|
|
1085
|
+
* Perspective transform for corner pinning
|
|
1086
|
+
* When set, the ad is rendered with perspective correction to fit surfaces
|
|
1087
|
+
* @see https://github.com/uMe-Group/Includu/issues/58
|
|
1088
|
+
*/
|
|
1089
|
+
perspective?: PerspectiveTransform;
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Age rating for content
|
|
1093
|
+
*/
|
|
1094
|
+
export type AgeRating = 'G' | 'PG' | 'PG-13' | 'R';
|
|
1095
|
+
/**
|
|
1096
|
+
* Content restrictions for ad targeting
|
|
1097
|
+
*/
|
|
1098
|
+
export interface AdRestrictions {
|
|
1099
|
+
/** Categories that should not advertise on this content */
|
|
1100
|
+
blockedCategories?: string[];
|
|
1101
|
+
/** Content age rating */
|
|
1102
|
+
ageRating?: AgeRating;
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Monetization configuration for published content
|
|
1106
|
+
*
|
|
1107
|
+
* Defined by content creator in Includu, consumed by Admetise.
|
|
1108
|
+
* Uses template-based placements for consistency.
|
|
1109
|
+
*/
|
|
1110
|
+
export interface MonetizationConfig {
|
|
1111
|
+
/** Whether monetization is enabled */
|
|
1112
|
+
enabled: boolean;
|
|
1113
|
+
/** Ad slot placements (references templates) */
|
|
1114
|
+
placements: AdSlotPlacement[];
|
|
1115
|
+
/**
|
|
1116
|
+
* @deprecated Use placements instead. Kept for backwards compatibility.
|
|
1117
|
+
*/
|
|
1118
|
+
adSlots?: AdSlot[];
|
|
1119
|
+
/** Creator's revenue share percentage (0-100) */
|
|
1120
|
+
revenueShare?: number;
|
|
1121
|
+
/** Content restrictions for ad targeting */
|
|
1122
|
+
restrictions?: AdRestrictions;
|
|
1123
|
+
/** Whether 3D ads (Layer 2) are enabled */
|
|
1124
|
+
layer2Enabled?: boolean;
|
|
1125
|
+
/** Whether 2D ads are enabled */
|
|
1126
|
+
layer2DEnabled?: boolean;
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Standard ad slot templates following IAB guidelines
|
|
1130
|
+
* These are the default templates that Admetise provides.
|
|
1131
|
+
* Can be extended/modified via Admetise admin.
|
|
1132
|
+
*/
|
|
1133
|
+
export declare const STANDARD_AD_TEMPLATES: AdSlotTemplate[];
|
|
1134
|
+
/**
|
|
1135
|
+
* Find a template by ID
|
|
1136
|
+
*
|
|
1137
|
+
* @param templateId - The template ID to find
|
|
1138
|
+
* @param templates - Array of templates (defaults to STANDARD_AD_TEMPLATES)
|
|
1139
|
+
* @returns The template or undefined
|
|
1140
|
+
*/
|
|
1141
|
+
export declare function findTemplate(templateId: string, templates?: AdSlotTemplate[]): AdSlotTemplate | undefined;
|
|
1142
|
+
/**
|
|
1143
|
+
* Maps an AdSlotPlacement to an AdZone using template data
|
|
1144
|
+
*
|
|
1145
|
+
* @param placement - The placement from Includu
|
|
1146
|
+
* @param template - The template definition from Admetise
|
|
1147
|
+
* @param fps - Frames per second of the video
|
|
1148
|
+
* @returns AdZone for Admetise
|
|
1149
|
+
*/
|
|
1150
|
+
export declare function mapPlacementToZone(placement: AdSlotPlacement, template: AdSlotTemplate, fps: number): AdZone;
|
|
1151
|
+
/**
|
|
1152
|
+
* @deprecated Use mapPlacementToZone instead
|
|
1153
|
+
* Maps an Includu AdSlot to an Admetise AdZone (legacy support)
|
|
1154
|
+
*/
|
|
1155
|
+
export declare function mapAdSlotToZone(slot: AdSlot, fps: number): AdZone;
|
|
1156
|
+
/**
|
|
1157
|
+
* Maps all placements from a manifest to AdZones
|
|
1158
|
+
*
|
|
1159
|
+
* @param manifest - Published manifest with monetization config
|
|
1160
|
+
* @param templates - Available templates (defaults to STANDARD_AD_TEMPLATES)
|
|
1161
|
+
* @returns Array of AdZones, or empty array if monetization disabled
|
|
1162
|
+
*/
|
|
1163
|
+
export declare function mapManifestToZones(manifest: PublishedManifest, templates?: AdSlotTemplate[]): AdZone[];
|
|
1164
|
+
/**
|
|
1165
|
+
* Get templates grouped by category
|
|
1166
|
+
*
|
|
1167
|
+
* @param templates - Array of templates (defaults to STANDARD_AD_TEMPLATES)
|
|
1168
|
+
* @returns Object with templates grouped by category
|
|
1169
|
+
*/
|
|
1170
|
+
export declare function getTemplatesByCategory(templates?: AdSlotTemplate[]): Record<AdTemplateCategory, AdSlotTemplate[]>;
|
|
1171
|
+
/**
|
|
1172
|
+
* Get templates filtered by type
|
|
1173
|
+
*
|
|
1174
|
+
* @param type - The ad slot type to filter by
|
|
1175
|
+
* @param templates - Array of templates (defaults to STANDARD_AD_TEMPLATES)
|
|
1176
|
+
* @returns Filtered templates
|
|
1177
|
+
*/
|
|
1178
|
+
export declare function getTemplatesByType(type: AdSlotType, templates?: AdSlotTemplate[]): AdSlotTemplate[];
|
|
1179
|
+
export { computeMatrix3d, isValidQuad } from './perspective';
|
|
1180
|
+
export * from './layer2';
|
|
1181
|
+
export * from './campaigns';
|
|
1182
|
+
export * from './adserving';
|
|
1183
|
+
export * from './gausst';
|
|
1184
|
+
/**
|
|
1185
|
+
* Category for overlay templates
|
|
1186
|
+
*/
|
|
1187
|
+
export type OverlayTemplateCategory = 'titles' | 'lower-thirds' | 'badges' | 'cta' | 'social' | 'graphics' | 'motion-gfx';
|
|
1188
|
+
/**
|
|
1189
|
+
* Overlay template preset definition
|
|
1190
|
+
* Used to quickly create common overlay patterns
|
|
1191
|
+
*/
|
|
1192
|
+
export interface OverlayTemplatePreset {
|
|
1193
|
+
/** Unique template identifier */
|
|
1194
|
+
id: string;
|
|
1195
|
+
/** Display name */
|
|
1196
|
+
name: string;
|
|
1197
|
+
/** Short description */
|
|
1198
|
+
description: string;
|
|
1199
|
+
/** Category for grouping */
|
|
1200
|
+
category: OverlayTemplateCategory;
|
|
1201
|
+
/** Icon/emoji for quick visual identification */
|
|
1202
|
+
icon: string;
|
|
1203
|
+
/** Overlay type */
|
|
1204
|
+
type: 'text' | 'cta' | 'shape' | 'emoji' | 'image' | 'sprite-sequence' | 'video';
|
|
1205
|
+
/** Default position (percentage 0-100) */
|
|
1206
|
+
position: {
|
|
1207
|
+
x: number;
|
|
1208
|
+
y: number;
|
|
1209
|
+
width: number;
|
|
1210
|
+
height: number;
|
|
1211
|
+
};
|
|
1212
|
+
/** Default duration in seconds */
|
|
1213
|
+
durationSeconds: number;
|
|
1214
|
+
/** Text content defaults (for text overlays) */
|
|
1215
|
+
textDefaults?: {
|
|
1216
|
+
text: string;
|
|
1217
|
+
fontSize: number;
|
|
1218
|
+
fontFamily: string;
|
|
1219
|
+
fontWeight: 'normal' | 'bold';
|
|
1220
|
+
color: string;
|
|
1221
|
+
textAlign: 'left' | 'center' | 'right';
|
|
1222
|
+
background?: {
|
|
1223
|
+
color: string;
|
|
1224
|
+
opacity: number;
|
|
1225
|
+
padding: {
|
|
1226
|
+
x: number;
|
|
1227
|
+
y: number;
|
|
1228
|
+
};
|
|
1229
|
+
scale: number;
|
|
1230
|
+
borderRadius: number;
|
|
1231
|
+
};
|
|
1232
|
+
};
|
|
1233
|
+
/** CTA content defaults (for CTA overlays) */
|
|
1234
|
+
ctaDefaults?: {
|
|
1235
|
+
text: string;
|
|
1236
|
+
url: string;
|
|
1237
|
+
style: {
|
|
1238
|
+
backgroundColor: string;
|
|
1239
|
+
textColor: string;
|
|
1240
|
+
borderRadius: number;
|
|
1241
|
+
fontSize: number;
|
|
1242
|
+
fontWeight: 'normal' | 'bold';
|
|
1243
|
+
padding: {
|
|
1244
|
+
x: number;
|
|
1245
|
+
y: number;
|
|
1246
|
+
};
|
|
1247
|
+
};
|
|
1248
|
+
};
|
|
1249
|
+
/** Emoji content defaults (for emoji overlays) */
|
|
1250
|
+
emojiDefaults?: {
|
|
1251
|
+
emoji: string;
|
|
1252
|
+
size: number;
|
|
1253
|
+
};
|
|
1254
|
+
/** Image content defaults (for image overlays) */
|
|
1255
|
+
imageDefaults?: {
|
|
1256
|
+
src: string;
|
|
1257
|
+
alt: string;
|
|
1258
|
+
fit: 'contain' | 'cover' | 'fill';
|
|
1259
|
+
opacity: number;
|
|
1260
|
+
borderRadius: number;
|
|
1261
|
+
/** Optional click URL to make the image clickable */
|
|
1262
|
+
clickUrl?: string;
|
|
1263
|
+
};
|
|
1264
|
+
/**
|
|
1265
|
+
* Whether this template should have perspective/corner pinning enabled by default
|
|
1266
|
+
* Used for templates like Picture Frame / Screen Replace
|
|
1267
|
+
*/
|
|
1268
|
+
perspectiveEnabled?: boolean;
|
|
1269
|
+
/** Sprite sequence content defaults (for sprite-sequence overlays) */
|
|
1270
|
+
spriteDefaults?: {
|
|
1271
|
+
spritesheetUrl: string;
|
|
1272
|
+
frameWidth: number;
|
|
1273
|
+
frameHeight: number;
|
|
1274
|
+
frameCount: number;
|
|
1275
|
+
columns: number;
|
|
1276
|
+
framesPerSecond: number;
|
|
1277
|
+
loop: boolean;
|
|
1278
|
+
pingPong?: boolean;
|
|
1279
|
+
startFrame?: number;
|
|
1280
|
+
opacity?: number;
|
|
1281
|
+
};
|
|
1282
|
+
/** Video content defaults (for video overlays with alpha) */
|
|
1283
|
+
videoDefaults?: {
|
|
1284
|
+
videoUrl: string;
|
|
1285
|
+
loop: boolean;
|
|
1286
|
+
muted: boolean;
|
|
1287
|
+
playbackRate?: number;
|
|
1288
|
+
startTime?: number;
|
|
1289
|
+
opacity?: number;
|
|
1290
|
+
fit?: 'contain' | 'cover' | 'fill';
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Standard overlay template presets
|
|
1295
|
+
* Designed for ease of use across all devices
|
|
1296
|
+
*/
|
|
1297
|
+
export declare const OVERLAY_TEMPLATE_PRESETS: OverlayTemplatePreset[];
|
|
1298
|
+
/**
|
|
1299
|
+
* Get overlay templates by category
|
|
1300
|
+
*/
|
|
1301
|
+
export declare function getOverlayTemplatesByCategory(category: OverlayTemplateCategory): OverlayTemplatePreset[];
|
|
1302
|
+
/**
|
|
1303
|
+
* Find an overlay template by ID
|
|
1304
|
+
*/
|
|
1305
|
+
export declare function findOverlayTemplate(id: string): OverlayTemplatePreset | undefined;
|
|
1306
|
+
/**
|
|
1307
|
+
* Get all overlay template categories with their templates
|
|
1308
|
+
*/
|
|
1309
|
+
export declare function getOverlayTemplateCategoriesWithTemplates(): {
|
|
1310
|
+
category: OverlayTemplateCategory;
|
|
1311
|
+
label: string;
|
|
1312
|
+
templates: OverlayTemplatePreset[];
|
|
1313
|
+
}[];
|
|
1314
|
+
/**
|
|
1315
|
+
* Get overlay template categories for the Overlays track (excludes branding categories)
|
|
1316
|
+
*/
|
|
1317
|
+
export declare function getOverlayTrackCategories(): {
|
|
1318
|
+
category: OverlayTemplateCategory;
|
|
1319
|
+
label: string;
|
|
1320
|
+
templates: OverlayTemplatePreset[];
|
|
1321
|
+
}[];
|
|
1322
|
+
/**
|
|
1323
|
+
* Get branding template categories for the Branding track
|
|
1324
|
+
*/
|
|
1325
|
+
export declare function getBrandingTrackCategories(): {
|
|
1326
|
+
category: OverlayTemplateCategory;
|
|
1327
|
+
label: string;
|
|
1328
|
+
templates: OverlayTemplatePreset[];
|
|
1329
|
+
}[];
|
|
1330
|
+
/**
|
|
1331
|
+
* Get Motion Graphics template categories for the Motion GFX track
|
|
1332
|
+
*/
|
|
1333
|
+
export declare function getMotionGfxTrackCategories(): {
|
|
1334
|
+
category: OverlayTemplateCategory;
|
|
1335
|
+
label: string;
|
|
1336
|
+
templates: OverlayTemplatePreset[];
|
|
1337
|
+
}[];
|
|
1338
|
+
/**
|
|
1339
|
+
* @deprecated Use getMotionGfxTrackCategories instead
|
|
1340
|
+
*/
|
|
1341
|
+
export declare function get3DTrackCategories(): {
|
|
1342
|
+
category: OverlayTemplateCategory;
|
|
1343
|
+
label: string;
|
|
1344
|
+
templates: OverlayTemplatePreset[];
|
|
1345
|
+
}[];
|
|
1346
|
+
/**
|
|
1347
|
+
* Coordinate system constants for Three.js video compositing
|
|
1348
|
+
*
|
|
1349
|
+
* Based on Gausst legacy code (Patent US8761580B2):
|
|
1350
|
+
* - Y-up axis (Three.js default)
|
|
1351
|
+
* - Metric units: 1 unit = 1 meter
|
|
1352
|
+
* - Reference: 1920 video pixels = 1 meter
|
|
1353
|
+
*
|
|
1354
|
+
* @see docs/architecture/coordinate-system-design.md
|
|
1355
|
+
*/
|
|
1356
|
+
export declare const COORDINATE_SYSTEM: {
|
|
1357
|
+
/**
|
|
1358
|
+
* Reference scale: 1920 pixels = 1 meter in world space
|
|
1359
|
+
* This ensures a standard 1920×1080 video is 1m × 0.5625m
|
|
1360
|
+
*/
|
|
1361
|
+
readonly PIXELS_PER_METER: 1920;
|
|
1362
|
+
/**
|
|
1363
|
+
* Layer Z positions in meters
|
|
1364
|
+
* - VIDEO: Background video plane
|
|
1365
|
+
* - THREE_D_MIN/MAX: 3D tracked surfaces, webcam
|
|
1366
|
+
* - HUD_MIN/MAX: HTML overlays via CSS2DRenderer
|
|
1367
|
+
*/
|
|
1368
|
+
readonly LAYER_Z: {
|
|
1369
|
+
readonly VIDEO: 0;
|
|
1370
|
+
readonly THREE_D_MIN: 0.01;
|
|
1371
|
+
readonly THREE_D_MAX: 10;
|
|
1372
|
+
readonly HUD_MIN: 10.1;
|
|
1373
|
+
readonly HUD_MAX: 100;
|
|
1374
|
+
};
|
|
1375
|
+
/**
|
|
1376
|
+
* Camera defaults for orthographic rendering (video plane)
|
|
1377
|
+
*/
|
|
1378
|
+
readonly CAMERA: {
|
|
1379
|
+
readonly NEAR: 0.01;
|
|
1380
|
+
readonly FAR: 1000;
|
|
1381
|
+
readonly POSITION_Z: 50;
|
|
1382
|
+
};
|
|
1383
|
+
/**
|
|
1384
|
+
* Orthographic camera settings for HUD overlays (Layer 3)
|
|
1385
|
+
* Provides predictable 2D positioning for sprites, text, CTAs
|
|
1386
|
+
*
|
|
1387
|
+
* Bounds are set dynamically based on video dimensions.
|
|
1388
|
+
* Objects are positioned in meters relative to center (0,0).
|
|
1389
|
+
*/
|
|
1390
|
+
readonly HUD_CAMERA: {
|
|
1391
|
+
/** Camera Z position (arbitrary for orthographic) */
|
|
1392
|
+
readonly POSITION_Z: 10;
|
|
1393
|
+
/** Near clipping plane */
|
|
1394
|
+
readonly NEAR: 0.1;
|
|
1395
|
+
/** Far clipping plane */
|
|
1396
|
+
readonly FAR: 100;
|
|
1397
|
+
/** Default object Z position */
|
|
1398
|
+
readonly OBJECT_Z: 0;
|
|
1399
|
+
};
|
|
1400
|
+
/**
|
|
1401
|
+
* Perspective camera settings for webcam composite layer (Layer 2)
|
|
1402
|
+
* Camera positioned at eye height for 3D scene placement
|
|
1403
|
+
* Reserved for future webcam/chroma key compositing
|
|
1404
|
+
*/
|
|
1405
|
+
readonly SCENE_CAMERA: {
|
|
1406
|
+
/** Camera X position (centered) */
|
|
1407
|
+
readonly POSITION_X: 0;
|
|
1408
|
+
/** Camera Y position (eye height) */
|
|
1409
|
+
readonly POSITION_Y: 1.2;
|
|
1410
|
+
/** Camera Z position (distance from scene) */
|
|
1411
|
+
readonly POSITION_Z: 4;
|
|
1412
|
+
/** Vertical field of view in degrees (~43mm equivalent) */
|
|
1413
|
+
readonly FOV: 47;
|
|
1414
|
+
/** Near clipping plane */
|
|
1415
|
+
readonly NEAR: 0.1;
|
|
1416
|
+
/** Far clipping plane */
|
|
1417
|
+
readonly FAR: 100;
|
|
1418
|
+
/** Look-at target Y position */
|
|
1419
|
+
readonly LOOK_AT_Y: 1.2;
|
|
1420
|
+
};
|
|
1421
|
+
/**
|
|
1422
|
+
* Film gate constants (for future camera matching)
|
|
1423
|
+
* Based on 35mm full-frame sensor
|
|
1424
|
+
*/
|
|
1425
|
+
readonly FILM_GATE: {
|
|
1426
|
+
readonly HORIZONTAL_APERTURE: 1.417;
|
|
1427
|
+
readonly VERTICAL_APERTURE: 0.945;
|
|
1428
|
+
};
|
|
1429
|
+
};
|
|
1430
|
+
/**
|
|
1431
|
+
* Convert video pixel dimensions to world-space meters
|
|
1432
|
+
*
|
|
1433
|
+
* @param pixelWidth - Video width in pixels
|
|
1434
|
+
* @param pixelHeight - Video height in pixels
|
|
1435
|
+
* @returns World-space dimensions in meters
|
|
1436
|
+
*/
|
|
1437
|
+
export declare function pixelsToMeters(pixelWidth: number, pixelHeight: number): {
|
|
1438
|
+
width: number;
|
|
1439
|
+
height: number;
|
|
1440
|
+
};
|
|
1441
|
+
/**
|
|
1442
|
+
* Convert world-space meters to video pixels
|
|
1443
|
+
*
|
|
1444
|
+
* @param meterWidth - Width in meters
|
|
1445
|
+
* @param meterHeight - Height in meters
|
|
1446
|
+
* @returns Pixel dimensions
|
|
1447
|
+
*/
|
|
1448
|
+
export declare function metersToPixels(meterWidth: number, meterHeight: number): {
|
|
1449
|
+
width: number;
|
|
1450
|
+
height: number;
|
|
1451
|
+
};
|
|
1452
|
+
/**
|
|
1453
|
+
* Convert overlay percentage position (0-100) to world-space meters
|
|
1454
|
+
*
|
|
1455
|
+
* @param percentX - X position as percentage (0-100, left to right)
|
|
1456
|
+
* @param percentY - Y position as percentage (0-100, top to bottom)
|
|
1457
|
+
* @param videoWidthMeters - Video width in meters
|
|
1458
|
+
* @param videoHeightMeters - Video height in meters
|
|
1459
|
+
* @returns World-space position {x, y} in meters, centered at origin
|
|
1460
|
+
*/
|
|
1461
|
+
export declare function percentToWorldSpace(percentX: number, percentY: number, videoWidthMeters: number, videoHeightMeters: number): {
|
|
1462
|
+
x: number;
|
|
1463
|
+
y: number;
|
|
1464
|
+
};
|
|
1465
|
+
/**
|
|
1466
|
+
* Convert world-space meters to overlay percentage position (0-100)
|
|
1467
|
+
*
|
|
1468
|
+
* @param worldX - X position in meters (origin = center)
|
|
1469
|
+
* @param worldY - Y position in meters (origin = center)
|
|
1470
|
+
* @param videoWidthMeters - Video width in meters
|
|
1471
|
+
* @param videoHeightMeters - Video height in meters
|
|
1472
|
+
* @returns Percentage position {x, y} (0-100)
|
|
1473
|
+
*/
|
|
1474
|
+
export declare function worldSpaceToPercent(worldX: number, worldY: number, videoWidthMeters: number, videoHeightMeters: number): {
|
|
1475
|
+
x: number;
|
|
1476
|
+
y: number;
|
|
1477
|
+
};
|
|
1478
|
+
/**
|
|
1479
|
+
* Camera tracking data format (from Gausst legacy)
|
|
1480
|
+
* Position: mm × 100, Rotation: degrees × 1000
|
|
1481
|
+
*/
|
|
1482
|
+
export interface TrackingPacket {
|
|
1483
|
+
x: number;
|
|
1484
|
+
y: number;
|
|
1485
|
+
z: number;
|
|
1486
|
+
pan: number;
|
|
1487
|
+
tilt: number;
|
|
1488
|
+
roll: number;
|
|
1489
|
+
fov: number;
|
|
1490
|
+
focus: number;
|
|
1491
|
+
}
|
|
1492
|
+
/**
|
|
1493
|
+
* Convert Gausst tracking packet to world-space transform
|
|
1494
|
+
*
|
|
1495
|
+
* @param packet - Raw tracking data from hardware
|
|
1496
|
+
* @returns Position in meters, rotation in radians, FOV in degrees
|
|
1497
|
+
*/
|
|
1498
|
+
export declare function trackingPacketToWorldSpace(packet: TrackingPacket): {
|
|
1499
|
+
position: {
|
|
1500
|
+
x: number;
|
|
1501
|
+
y: number;
|
|
1502
|
+
z: number;
|
|
1503
|
+
};
|
|
1504
|
+
rotation: {
|
|
1505
|
+
x: number;
|
|
1506
|
+
y: number;
|
|
1507
|
+
z: number;
|
|
1508
|
+
};
|
|
1509
|
+
fov: number;
|
|
1510
|
+
};
|
|
1511
|
+
/**
|
|
1512
|
+
* Convert FOV to focal length (for matching real camera optics)
|
|
1513
|
+
*
|
|
1514
|
+
* Formula from Gausst: focalLength = (aperture / 2) / tan(fov / 2) * 25.4
|
|
1515
|
+
*
|
|
1516
|
+
* @param fovDegrees - Field of view in degrees
|
|
1517
|
+
* @param filmApertureInches - Horizontal film aperture (default: 1.417" = 36mm)
|
|
1518
|
+
* @returns Focal length in millimeters
|
|
1519
|
+
*/
|
|
1520
|
+
export declare function fovToFocalLength(fovDegrees: number, filmApertureInches?: number): number;
|
|
1521
|
+
/**
|
|
1522
|
+
* Convert focal length to FOV
|
|
1523
|
+
*
|
|
1524
|
+
* @param focalLengthMM - Focal length in millimeters
|
|
1525
|
+
* @param filmApertureInches - Horizontal film aperture (default: 1.417" = 36mm)
|
|
1526
|
+
* @returns Field of view in degrees
|
|
1527
|
+
*/
|
|
1528
|
+
export declare function focalLengthToFov(focalLengthMM: number, filmApertureInches?: number): number;
|
|
1529
|
+
export { webcamVertexShader, webcamFragmentShader, getDefaultPlayerUniforms, getDefaultEditorUniforms, type WebcamShaderUniforms } from './layer2/shaders';
|
|
1530
|
+
export { WEBCAM_BASE_HEIGHT_METERS, SILHOUETTE_HEIGHT_RATIO, getWebcamBaseDimensions, getWebcamMeshYOffset, getObjectEuler, getCameraEuler, GAM_PIXELS_TO_METERS, AD_TEMPLATE_DIMENSIONS, getAdDimensions, CHROMA_KEY_COLORS, getChromaKeyColorHex, featherToUV, featherEdgesToUV } from './layer2/webcam-utils';
|
|
1531
|
+
//# sourceMappingURL=index.d.ts.map
|