openvideo 0.0.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.
Files changed (69) hide show
  1. package/LICENSE +63 -0
  2. package/dist/SharedSystems-pXK0PjzC.js +2691 -0
  3. package/dist/WebGLRenderer-B_y7ugdK.js +2639 -0
  4. package/dist/WebGPURenderer-ByeYcldK.js +1655 -0
  5. package/dist/browserAll-lTqv9nwW.js +1876 -0
  6. package/dist/clips/audio-clip.d.ts +128 -0
  7. package/dist/clips/base-clip.d.ts +116 -0
  8. package/dist/clips/caption-clip.d.ts +392 -0
  9. package/dist/clips/effect-clip.d.ts +37 -0
  10. package/dist/clips/iclip.d.ts +178 -0
  11. package/dist/clips/image-clip.d.ts +115 -0
  12. package/dist/clips/index.d.ts +14 -0
  13. package/dist/clips/placeholder-clip.d.ts +15 -0
  14. package/dist/clips/text-clip.d.ts +266 -0
  15. package/dist/clips/transition-clip.d.ts +45 -0
  16. package/dist/clips/video-clip.d.ts +238 -0
  17. package/dist/colorToUniform-C2jGzNe1.js +97 -0
  18. package/dist/compositor.d.ts +107 -0
  19. package/dist/effect/effect.d.ts +6 -0
  20. package/dist/effect/glsl/custom-glsl.d.ts +1017 -0
  21. package/dist/effect/glsl/gl-effect.d.ts +16 -0
  22. package/dist/effect/types.d.ts +24 -0
  23. package/dist/effect/vertex.d.ts +1 -0
  24. package/dist/event-emitter.d.ts +55 -0
  25. package/dist/index-CIRqJXOw.js +41882 -0
  26. package/dist/index.d.ts +20 -0
  27. package/dist/index.es.js +28 -0
  28. package/dist/index.umd.js +7741 -0
  29. package/dist/json-serialization.d.ts +222 -0
  30. package/dist/mp4-utils/index.d.ts +31 -0
  31. package/dist/mp4-utils/mp4box-utils.d.ts +44 -0
  32. package/dist/mp4-utils/sample-transform.d.ts +26 -0
  33. package/dist/sprite/base-sprite.d.ts +183 -0
  34. package/dist/sprite/pixi-sprite-renderer.d.ts +49 -0
  35. package/dist/studio/history-manager.d.ts +46 -0
  36. package/dist/studio/resource-manager.d.ts +53 -0
  37. package/dist/studio/resource-manager.spec.d.ts +1 -0
  38. package/dist/studio/selection-manager.d.ts +50 -0
  39. package/dist/studio/timeline-model.d.ts +110 -0
  40. package/dist/studio/transport.d.ts +44 -0
  41. package/dist/studio.d.ts +380 -0
  42. package/dist/studio.spec.d.ts +1 -0
  43. package/dist/transfomer/parts/handle.d.ts +17 -0
  44. package/dist/transfomer/parts/snapping.d.ts +41 -0
  45. package/dist/transfomer/parts/wireframe.d.ts +5 -0
  46. package/dist/transfomer/transformer.d.ts +31 -0
  47. package/dist/transition/fragment.d.ts +1 -0
  48. package/dist/transition/glsl/custom-glsl.d.ts +231 -0
  49. package/dist/transition/glsl/gl-transition.d.ts +18 -0
  50. package/dist/transition/transition.d.ts +6 -0
  51. package/dist/transition/types.d.ts +29 -0
  52. package/dist/transition/uniforms.d.ts +35 -0
  53. package/dist/transition/vertex.d.ts +1 -0
  54. package/dist/utils/asset-manager.d.ts +6 -0
  55. package/dist/utils/audio-codec-detector.d.ts +28 -0
  56. package/dist/utils/audio.d.ts +82 -0
  57. package/dist/utils/chromakey.d.ts +24 -0
  58. package/dist/utils/color.d.ts +9 -0
  59. package/dist/utils/common.d.ts +7 -0
  60. package/dist/utils/dom.d.ts +48 -0
  61. package/dist/utils/fonts.d.ts +16 -0
  62. package/dist/utils/index.d.ts +6 -0
  63. package/dist/utils/log.d.ts +27 -0
  64. package/dist/utils/srt-parser.d.ts +15 -0
  65. package/dist/utils/stream-utils.d.ts +9 -0
  66. package/dist/utils/video.d.ts +16 -0
  67. package/dist/utils/worker-timer.d.ts +1 -0
  68. package/dist/webworkerAll-BsrA7oC4.js +2670 -0
  69. package/package.json +63 -0
@@ -0,0 +1,128 @@
1
+ import { BaseClip } from './base-clip';
2
+ import { IClip, IPlaybackCapable } from './iclip';
3
+ import { AudioJSON } from '../json-serialization';
4
+ interface IAudioOpts {
5
+ loop?: boolean;
6
+ volume?: number;
7
+ }
8
+ /**
9
+ * Audio clip providing audio data for creating and editing audio/video
10
+ *
11
+ * @example
12
+ * // Load audio clip asynchronously
13
+ * const audioClip = await Audio.fromUrl('path/to/audio.mp3', {
14
+ * loop: true,
15
+ * });
16
+ *
17
+ * @example
18
+ * // Traditional approach (for advanced use)
19
+ * new Audio((await fetch('<mp3 url>')).body, {
20
+ * loop: true,
21
+ * }),
22
+ */
23
+ export declare class Audio extends BaseClip implements IPlaybackCapable {
24
+ readonly type = "Audio";
25
+ static ctx: AudioContext | null;
26
+ ready: IClip['ready'];
27
+ private _meta;
28
+ /**
29
+ * Audio metadata
30
+ *
31
+ * ⚠️ Note, these are converted (normalized) metadata, not original audio metadata
32
+ */
33
+ get meta(): {
34
+ sampleRate: number;
35
+ chanCount: number;
36
+ duration: number;
37
+ width: number;
38
+ height: number;
39
+ };
40
+ private chan0Buf;
41
+ private chan1Buf;
42
+ /**
43
+ * Get complete PCM data from audio clip
44
+ */
45
+ getPCMData(): Float32Array[];
46
+ private opts;
47
+ /**
48
+ * Whether to loop the audio (hybrid JSON structure)
49
+ */
50
+ loop: boolean;
51
+ /**
52
+ * Load an audio clip from a URL
53
+ * @param url Audio URL
54
+ * @param opts Audio configuration (loop, volume)
55
+ * @returns Promise that resolves to an audio clip
56
+ *
57
+ * @example
58
+ * const audioClip = await Audio.fromUrl('path/to/audio.mp3', {
59
+ * loop: true,
60
+ * volume: 0.8,
61
+ * });
62
+ */
63
+ static fromUrl(url: string, opts?: IAudioOpts): Promise<Audio>;
64
+ /**
65
+ * Create an Audio instance from a JSON object (fabric.js pattern)
66
+ * @param json The JSON object representing the clip
67
+ * @returns Promise that resolves to an Audio instance
68
+ */
69
+ static fromObject(json: AudioJSON): Promise<Audio>;
70
+ /**
71
+ *
72
+ * @param dataSource Audio file stream
73
+ * @param opts Audio configuration, controls volume and whether to loop
74
+ */
75
+ constructor(dataSource: ReadableStream<Uint8Array> | Float32Array[], opts?: IAudioOpts, src?: string);
76
+ private init;
77
+ /**
78
+ * Intercept data returned by {@link Audio.tick} method for secondary processing of audio data
79
+ * @param time Time when tick was called
80
+ * @param tickRet Data returned by tick
81
+ *
82
+ */
83
+ tickInterceptor: <T extends Awaited<ReturnType<Audio['tick']>>>(time: number, tickRet: T) => Promise<T>;
84
+ private timestamp;
85
+ private frameOffset;
86
+ /**
87
+ * Return audio PCM data corresponding to the time difference between last and current moments
88
+ *
89
+ * If the difference exceeds 3s or current time is less than last time, reset state
90
+ * @example
91
+ * tick(0) // => []
92
+ * tick(1e6) // => [leftChanPCM(1s), rightChanPCM(1s)]
93
+ *
94
+ */
95
+ tick(time: number): Promise<{
96
+ audio: Float32Array[];
97
+ state: 'success' | 'done';
98
+ }>;
99
+ /**
100
+ * Split at specified time, return two audio clips before and after
101
+ * @param time Time in microseconds
102
+ */
103
+ split(time: number): Promise<[this, this]>;
104
+ clone(): Promise<this>;
105
+ /**
106
+ * Destroy instance and release resources
107
+ */
108
+ destroy(): void;
109
+ toJSON(main?: boolean): AudioJSON;
110
+ static concatAudio: typeof concatAudioClip;
111
+ /**
112
+ * Create HTMLAudioElement for playback
113
+ */
114
+ createPlaybackElement(): Promise<{
115
+ element: HTMLAudioElement;
116
+ objectUrl?: string;
117
+ }>;
118
+ play(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
119
+ pause(element: HTMLVideoElement | HTMLAudioElement): void;
120
+ seek(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
121
+ syncPlayback(element: HTMLVideoElement | HTMLAudioElement, isPlaying: boolean, timeSeconds: number): void;
122
+ cleanupPlayback(element: HTMLVideoElement | HTMLAudioElement, objectUrl?: string): void;
123
+ }
124
+ /**
125
+ * Concatenate multiple AudioClips
126
+ */
127
+ export declare function concatAudioClip(clips: Audio[], opts?: IAudioOpts): Promise<Audio>;
128
+ export {};
@@ -0,0 +1,116 @@
1
+ import { BaseSprite, BaseSpriteEvents } from '../sprite/base-sprite';
2
+ import { IClip, IClipMeta, ITransitionInfo } from './iclip';
3
+ import { ClipJSON } from '../json-serialization';
4
+ /**
5
+ * Base class for all clips that extends BaseSprite
6
+ * Provides common functionality for sprite operations (position, animation, timing)
7
+ * and frame management
8
+ */
9
+ export declare abstract class BaseClip<T extends BaseSpriteEvents = BaseSpriteEvents> extends BaseSprite<T> implements IClip<T> {
10
+ abstract readonly type: string;
11
+ private lastVf;
12
+ protected destroyed: boolean;
13
+ /**
14
+ * Source URL or identifier for this clip
15
+ * Used for serialization and reloading from JSON
16
+ */
17
+ src: string;
18
+ /**
19
+ * Transition info (optional)
20
+ */
21
+ transition?: ITransitionInfo;
22
+ abstract tick(time: number): Promise<{
23
+ video?: VideoFrame | ImageBitmap | null;
24
+ audio?: Float32Array[];
25
+ state: 'done' | 'success';
26
+ }>;
27
+ ready: Promise<IClipMeta>;
28
+ abstract readonly meta: IClipMeta;
29
+ abstract clone(): Promise<this>;
30
+ abstract split?(time: number): Promise<[this, this]>;
31
+ constructor();
32
+ /**
33
+ * Get video frame and audio at specified time without rendering to canvas
34
+ * Useful for Pixi.js rendering where canvas context is not needed
35
+ * @param time Specified time in microseconds
36
+ */
37
+ getFrame(time: number): Promise<{
38
+ video: ImageBitmap | null;
39
+ audio: Float32Array[];
40
+ done: boolean;
41
+ }>;
42
+ /**
43
+ * Draw image at specified time to canvas context and return corresponding audio data
44
+ * @param time Specified time in microseconds
45
+ */
46
+ offscreenRender(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, time: number): Promise<{
47
+ audio: Float32Array[];
48
+ done: boolean;
49
+ }>;
50
+ /**
51
+ * Set clip properties (position, size, display timeline)
52
+ * @param props Properties to set
53
+ * @param fps Optional FPS for frame-to-time conversion (default: 30)
54
+ * @returns this for method chaining
55
+ *
56
+ * @example
57
+ * // Using frames (will be converted to microseconds)
58
+ * clip.set({
59
+ * display: {
60
+ * from: 150, // frames
61
+ * to: 450, // frames (10 seconds at 30fps)
62
+ * },
63
+ * }, 30);
64
+ *
65
+ * // Using microseconds directly
66
+ * clip.set({
67
+ * display: {
68
+ * from: 5000000, // microseconds
69
+ * to: 15000000, // microseconds
70
+ * },
71
+ * });
72
+ */
73
+ set(props: {
74
+ display?: {
75
+ from?: number;
76
+ to?: number;
77
+ };
78
+ x?: number;
79
+ y?: number;
80
+ width?: number;
81
+ height?: number;
82
+ duration?: number;
83
+ }, fps?: number): this;
84
+ /**
85
+ * Base implementation of toJSON that handles common clip properties
86
+ * Subclasses should override to add their specific options
87
+ * @param main Whether this is the main clip (for Compositor)
88
+ */
89
+ toJSON(main?: boolean): ClipJSON;
90
+ /**
91
+ * Get the list of visible transformer handles for this clip type
92
+ * Default implementation returns all handles
93
+ * Override in subclasses to customize handle visibility (e.g., TextClip)
94
+ */
95
+ getVisibleHandles(): Array<'tl' | 'tr' | 'bl' | 'br' | 'ml' | 'mr' | 'mt' | 'mb' | 'rot'>;
96
+ /**
97
+ * Scale clip to fit within the scene dimensions while maintaining aspect ratio
98
+ * @param sceneWidth Scene width
99
+ * @param sceneHeight Scene height
100
+ */
101
+ scaleToFit(sceneWidth: number, sceneHeight: number): Promise<void>;
102
+ /**
103
+ * Scale clip to fill the scene dimensions while maintaining aspect ratio
104
+ * May crop parts of the clip.
105
+ * @param sceneWidth Scene width
106
+ * @param sceneHeight Scene height
107
+ */
108
+ scaleToFill(sceneWidth: number, sceneHeight: number): Promise<void>;
109
+ /**
110
+ * Center the clip within the scene dimensions
111
+ * @param sceneWidth Scene width
112
+ * @param sceneHeight Scene height
113
+ */
114
+ centerInScene(sceneWidth: number, sceneHeight: number): void;
115
+ destroy(): void;
116
+ }
@@ -0,0 +1,392 @@
1
+ import { BaseClip } from './base-clip';
2
+ import { IClip } from './iclip';
3
+ import { CaptionJSON } from '../json-serialization';
4
+ import { Application, Texture } from 'pixi.js';
5
+ import { BaseSpriteEvents } from '../sprite/base-sprite';
6
+ export interface ICaptionStyle {
7
+ fontSize?: number;
8
+ fontFamily?: string;
9
+ fontWeight?: string | number;
10
+ fontStyle?: string;
11
+ color?: ICaptionOpts['fill'];
12
+ align?: ICaptionOpts['align'];
13
+ textCase?: ICaptionOpts['textCase'];
14
+ verticalAlign?: ICaptionOpts['verticalAlign'];
15
+ wordsPerLine?: ICaptionOpts['wordsPerLine'];
16
+ stroke?: {
17
+ color: string | number;
18
+ width: number;
19
+ };
20
+ shadow?: {
21
+ color: string | number;
22
+ alpha: number;
23
+ blur: number;
24
+ distance: number;
25
+ angle: number;
26
+ };
27
+ }
28
+ export interface ICaptionEvents extends BaseSpriteEvents {
29
+ propsChange: Partial<{
30
+ left: number;
31
+ top: number;
32
+ width: number;
33
+ height: number;
34
+ angle: number;
35
+ zIndex: number;
36
+ opacity: number;
37
+ volume: number;
38
+ text: string;
39
+ words: ICaptionOpts['words'];
40
+ fill: ICaptionOpts['fill'];
41
+ align: ICaptionOpts['align'];
42
+ textCase: ICaptionOpts['textCase'];
43
+ stroke: ICaptionOpts['stroke'];
44
+ dropShadow: ICaptionOpts['dropShadow'];
45
+ caption: ICaptionOpts['caption'];
46
+ wordsPerLine: ICaptionOpts['wordsPerLine'];
47
+ }>;
48
+ }
49
+ export interface ICaptionOpts {
50
+ /**
51
+ * Font size in pixels
52
+ * @default 30
53
+ */
54
+ fontSize?: number;
55
+ /**
56
+ * Font family
57
+ * @default 'Arial'
58
+ */
59
+ fontFamily?: string;
60
+ fontUrl?: string;
61
+ /**
62
+ * Font weight (e.g., 'normal', 'bold', '400', '700')
63
+ * @default 'normal'
64
+ */
65
+ fontWeight?: string | number;
66
+ /**
67
+ * Font style (e.g., 'normal', 'italic')
68
+ * @default 'normal'
69
+ */
70
+ fontStyle?: string;
71
+ /**
72
+ * Text color (hex string, color name, or gradient object)
73
+ * @default '#ffffff'
74
+ */
75
+ fill?: string | number | {
76
+ type: 'gradient';
77
+ x0: number;
78
+ y0: number;
79
+ x1: number;
80
+ y1: number;
81
+ colors: Array<{
82
+ ratio: number;
83
+ color: string | number;
84
+ }>;
85
+ };
86
+ /**
87
+ * Caption data (matches caption object in JSON)
88
+ */
89
+ caption?: {
90
+ words?: Array<{
91
+ text: string;
92
+ from: number;
93
+ to: number;
94
+ isKeyWord: boolean;
95
+ paragraphIndex?: number;
96
+ }>;
97
+ colors?: {
98
+ appeared?: string;
99
+ active?: string;
100
+ activeFill?: string;
101
+ background?: string;
102
+ keyword?: string;
103
+ };
104
+ preserveKeywordColor?: boolean;
105
+ positioning?: {
106
+ videoWidth?: number;
107
+ videoHeight?: number;
108
+ bottomOffset?: number;
109
+ };
110
+ };
111
+ /**
112
+ * @deprecated Use caption.words instead
113
+ */
114
+ words?: Array<{
115
+ text: string;
116
+ from: number;
117
+ to: number;
118
+ isKeyWord: boolean;
119
+ paragraphIndex?: number;
120
+ }>;
121
+ /**
122
+ * @deprecated Use caption.colors instead
123
+ */
124
+ colors?: {
125
+ appeared?: string;
126
+ active?: string;
127
+ activeFill?: string;
128
+ background?: string;
129
+ keyword?: string;
130
+ };
131
+ /**
132
+ * @deprecated Use caption.preserveKeywordColor instead
133
+ */
134
+ preserveKeywordColor?: boolean;
135
+ /**
136
+ * @deprecated Use caption.positioning.videoWidth instead
137
+ */
138
+ videoWidth?: number;
139
+ /**
140
+ * @deprecated Use caption.positioning.videoHeight instead
141
+ */
142
+ videoHeight?: number;
143
+ /**
144
+ * @deprecated Use caption.positioning.bottomOffset instead
145
+ */
146
+ bottomOffset?: number;
147
+ /**
148
+ * Stroke color (hex string or color name) or stroke object with advanced options
149
+ */
150
+ stroke?: string | number | {
151
+ color: string | number;
152
+ width: number;
153
+ join?: 'miter' | 'round' | 'bevel';
154
+ };
155
+ /**
156
+ * Stroke width in pixels (used when stroke is a simple color)
157
+ * @default 0
158
+ */
159
+ strokeWidth?: number;
160
+ /**
161
+ * Text alignment ('left', 'center', 'right')
162
+ * @default 'center'
163
+ */
164
+ align?: 'left' | 'center' | 'right';
165
+ /**
166
+ * Drop shadow configuration
167
+ */
168
+ dropShadow?: {
169
+ color?: string | number;
170
+ alpha?: number;
171
+ blur?: number;
172
+ angle?: number;
173
+ distance?: number;
174
+ };
175
+ /**
176
+ * Word wrap width (0 = no wrap)
177
+ * @default 0
178
+ */
179
+ wordWrapWidth?: number;
180
+ /**
181
+ * Word wrap mode ('break-word' or 'normal')
182
+ * @default 'break-word'
183
+ */
184
+ wordWrapMode?: 'break-word' | 'normal';
185
+ /**
186
+ * Whether to enable word wrap
187
+ * @default true
188
+ */
189
+ wordWrap?: boolean;
190
+ /**
191
+ * Vertical alignment ('top', 'center', 'bottom')
192
+ * @default 'bottom'
193
+ */
194
+ verticalAlign?: 'top' | 'center' | 'bottom';
195
+ /**
196
+ * Line height (multiplier)
197
+ * @default 1
198
+ */
199
+ lineHeight?: number;
200
+ /**
201
+ * Letter spacing in pixels
202
+ * @default 0
203
+ */
204
+ letterSpacing?: number;
205
+ /**
206
+ * Text case transformation
207
+ * @default 'none'
208
+ */
209
+ textCase?: 'none' | 'uppercase' | 'lowercase' | 'title';
210
+ /**
211
+ * Media ID to which the captions were applied
212
+ */
213
+ mediaId?: string;
214
+ /**
215
+ * Internal flag to skip automatic positioning
216
+ */
217
+ initialLayoutApplied?: boolean;
218
+ /**
219
+ * Words per line mode ('single' or 'multiple')
220
+ * @default 'multiple'
221
+ */
222
+ wordsPerLine?: 'single' | 'multiple';
223
+ }
224
+ /**
225
+ * Caption clip using Canvas 2D for rendering
226
+ * Each instance represents a single caption segment
227
+ *
228
+ * @example
229
+ * const captionClip = new CaptionClip('Hello World', {
230
+ * fontSize: 44,
231
+ * fontFamily: 'Arial',
232
+ * fill: '#ffffff',
233
+ * videoWidth: 1280,
234
+ * videoHeight: 720,
235
+ * });
236
+ * captionClip.display.from = 0;
237
+ * captionClip.duration = 3e6; // 3 seconds
238
+ */
239
+ export declare class Caption extends BaseClip<ICaptionEvents> implements IClip {
240
+ readonly type = "Caption";
241
+ ready: IClip['ready'];
242
+ private _meta;
243
+ get meta(): {
244
+ duration: number;
245
+ width: number;
246
+ height: number;
247
+ };
248
+ private _visualPaddingX;
249
+ private _visualPaddingY;
250
+ private _lastTickTime;
251
+ get width(): number;
252
+ set width(v: number);
253
+ get height(): number;
254
+ set height(v: number);
255
+ get left(): number;
256
+ set left(v: number);
257
+ get top(): number;
258
+ set top(v: number);
259
+ private _initialLayoutApplied;
260
+ private _isXPositionedManually;
261
+ private _isWidthConstrained;
262
+ private _lastContentWidth;
263
+ private _lastContentHeight;
264
+ private _lastProcessedText;
265
+ private _text;
266
+ /**
267
+ * Caption text content (hybrid JSON structure)
268
+ */
269
+ get text(): string;
270
+ set text(v: string);
271
+ get style(): ICaptionStyle;
272
+ set style(v: Partial<ICaptionOpts> | ICaptionStyle);
273
+ get wordsPerLine(): 'single' | 'multiple';
274
+ set wordsPerLine(v: 'single' | 'multiple');
275
+ get fontFamily(): string;
276
+ set fontFamily(v: string);
277
+ get fontUrl(): string;
278
+ set fontUrl(v: string);
279
+ get fontSize(): number;
280
+ set fontSize(v: number);
281
+ get fontWeight(): string | number;
282
+ set fontWeight(v: string | number);
283
+ get fontStyle(): 'normal' | 'italic' | 'oblique';
284
+ set fontStyle(v: 'normal' | 'italic' | 'oblique');
285
+ get fill(): ICaptionOpts['fill'];
286
+ set fill(v: ICaptionOpts['fill']);
287
+ get align(): 'left' | 'center' | 'right';
288
+ set align(v: 'left' | 'center' | 'right');
289
+ get stroke(): ICaptionOpts['stroke'];
290
+ set stroke(v: ICaptionOpts['stroke']);
291
+ get strokeWidth(): number;
292
+ set strokeWidth(v: number);
293
+ get dropShadow(): ICaptionOpts['dropShadow'];
294
+ set dropShadow(v: ICaptionOpts['dropShadow']);
295
+ get caption(): ICaptionOpts['caption'];
296
+ set caption(v: ICaptionOpts['caption']);
297
+ /**
298
+ * Bottom offset from video bottom (hybrid JSON structure)
299
+ */
300
+ bottomOffset?: number;
301
+ /**
302
+ * Text case proxy
303
+ */
304
+ get textCase(): string;
305
+ set textCase(v: 'none' | 'uppercase' | 'lowercase' | 'title');
306
+ /**
307
+ * Unique identifier for this clip instance
308
+ */
309
+ id: string;
310
+ /**
311
+ * Media ID of the source clip
312
+ */
313
+ get mediaId(): string | undefined;
314
+ set mediaId(v: string | undefined);
315
+ /**
316
+ * Array of effects to be applied to this clip
317
+ * Each effect specifies key, startTime, duration, and optional targets
318
+ */
319
+ effects: Array<{
320
+ id: string;
321
+ key: string;
322
+ startTime: number;
323
+ duration: number;
324
+ }>;
325
+ /**
326
+ * Words getter for the clip
327
+ */
328
+ get words(): ICaptionOpts["words"];
329
+ /**
330
+ * Words setter that triggers re-render and ensures consistency
331
+ */
332
+ set words(v: ICaptionOpts['words']);
333
+ private opts;
334
+ private pixiTextContainer;
335
+ private renderTexture;
336
+ private wordTexts;
337
+ private textStyle;
338
+ private textStyleBase;
339
+ private _refreshing;
340
+ private _needsRefresh;
341
+ private externalRenderer;
342
+ private pixiApp;
343
+ private originalOpts;
344
+ constructor(text: string, opts?: ICaptionOpts, renderer?: Application['renderer']);
345
+ /**
346
+ * Update text styling options and refresh the caption rendering
347
+ */
348
+ updateStyle(opts: Partial<ICaptionOpts>): Promise<void>;
349
+ private refreshCaptions;
350
+ private lastLoggedTime;
351
+ updateState(currentTime: number): void;
352
+ /**
353
+ * Get the PixiJS Texture (RenderTexture) for optimized rendering in Studio
354
+ */
355
+ getTexture(): Promise<Texture | null>;
356
+ offscreenRender(ctx: CanvasRenderingContext2D, time: number): Promise<{
357
+ audio: Float32Array[];
358
+ done: boolean;
359
+ }>;
360
+ /**
361
+ * Set an external renderer (e.g., from Studio) to avoid creating our own Pixi App
362
+ */
363
+ setRenderer(renderer: Application['renderer']): void;
364
+ private getRenderer;
365
+ tick(time: number): Promise<{
366
+ video: ImageBitmap;
367
+ state: 'success';
368
+ }>;
369
+ split(_time: number): Promise<[this, this]>;
370
+ addEffect(effect: {
371
+ id: string;
372
+ key: string;
373
+ startTime: number;
374
+ duration: number;
375
+ }): void;
376
+ editEffect(effectId: string, newEffectData: Partial<{
377
+ key: string;
378
+ startTime: number;
379
+ duration: number;
380
+ }>): void;
381
+ removeEffect(effectId: string): void;
382
+ clone(): Promise<this>;
383
+ destroy(): void;
384
+ toJSON(main?: boolean): CaptionJSON;
385
+ /**
386
+ * Create a Caption instance from a JSON object (fabric.js pattern)
387
+ * @param json The JSON object representing the clip
388
+ * @returns Promise that resolves to a Caption instance
389
+ */
390
+ static fromObject(json: CaptionJSON): Promise<Caption>;
391
+ getVisibleHandles(): Array<'tl' | 'tr' | 'bl' | 'br' | 'ml' | 'mr' | 'mt' | 'mb' | 'rot'>;
392
+ }
@@ -0,0 +1,37 @@
1
+ import { BaseClip } from './base-clip';
2
+ import { IClip } from './iclip';
3
+ import { EffectKey } from '../effect/glsl/gl-effect';
4
+ export declare class Effect extends BaseClip {
5
+ readonly type = "Effect";
6
+ ready: IClip['ready'];
7
+ private _meta;
8
+ get meta(): {
9
+ duration: number;
10
+ width: number;
11
+ height: number;
12
+ };
13
+ /**
14
+ * Unique identifier for this clip instance
15
+ */
16
+ id: string;
17
+ /**
18
+ * The effect configuration
19
+ */
20
+ effect: {
21
+ id: string;
22
+ key: EffectKey;
23
+ name: string;
24
+ };
25
+ constructor(effectKey: EffectKey);
26
+ clone(): Promise<this>;
27
+ tick(_time: number): Promise<{
28
+ video: ImageBitmap | undefined;
29
+ state: 'success';
30
+ }>;
31
+ split(_time: number): Promise<[this, this]>;
32
+ toJSON(main?: boolean): any;
33
+ /**
34
+ * Create an Effect instance from a JSON object
35
+ */
36
+ static fromObject(json: any): Promise<Effect>;
37
+ }