@designcombo/video 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +63 -0
  2. package/dist/SharedSystems-BSw9neqH.js +2691 -0
  3. package/dist/WebGLRenderer-BrabW-VK.js +2639 -0
  4. package/dist/WebGPURenderer-BKwBKkzk.js +1655 -0
  5. package/dist/browserAll-C7HVZtqZ.js +1876 -0
  6. package/dist/clips/audio-clip.d.ts +132 -0
  7. package/dist/clips/base-clip.d.ts +86 -0
  8. package/dist/clips/caption-clip.d.ts +257 -0
  9. package/dist/clips/iclip.d.ts +120 -0
  10. package/dist/clips/image-clip.d.ts +110 -0
  11. package/dist/clips/index.d.ts +8 -0
  12. package/dist/clips/text-clip.d.ts +192 -0
  13. package/dist/clips/video-clip.d.ts +200 -0
  14. package/dist/colorToUniform-Du0ROyNd.js +274 -0
  15. package/dist/compositor.d.ts +111 -0
  16. package/dist/index-CjzowIhV.js +28270 -0
  17. package/dist/index.d.ts +14 -0
  18. package/dist/index.es.js +20 -0
  19. package/dist/index.umd.js +1295 -0
  20. package/dist/internal-utils/event-tool.d.ts +50 -0
  21. package/dist/internal-utils/index.d.ts +14 -0
  22. package/dist/internal-utils/log.d.ts +34 -0
  23. package/dist/internal-utils/meta-box.d.ts +1 -0
  24. package/dist/internal-utils/recodemux.d.ts +65 -0
  25. package/dist/internal-utils/stream-utils.d.ts +43 -0
  26. package/dist/internal-utils/worker-timer.d.ts +8 -0
  27. package/dist/json-serialization.d.ts +142 -0
  28. package/dist/mp4-utils/index.d.ts +31 -0
  29. package/dist/mp4-utils/mp4box-utils.d.ts +36 -0
  30. package/dist/mp4-utils/sample-transform.d.ts +23 -0
  31. package/dist/sprite/base-sprite.d.ts +147 -0
  32. package/dist/sprite/pixi-sprite-renderer.d.ts +48 -0
  33. package/dist/studio.d.ts +142 -0
  34. package/dist/transfomer/parts/handle.d.ts +17 -0
  35. package/dist/transfomer/parts/wireframe.d.ts +5 -0
  36. package/dist/transfomer/transformer.d.ts +21 -0
  37. package/dist/utils/audio.d.ts +82 -0
  38. package/dist/utils/chromakey.d.ts +24 -0
  39. package/dist/utils/color.d.ts +4 -0
  40. package/dist/utils/common.d.ts +7 -0
  41. package/dist/utils/dom.d.ts +48 -0
  42. package/dist/utils/fonts.d.ts +16 -0
  43. package/dist/utils/index.d.ts +5 -0
  44. package/dist/utils/srt-parser.d.ts +15 -0
  45. package/dist/utils/video.d.ts +18 -0
  46. package/dist/webworkerAll-DsE6HIYE.js +2497 -0
  47. package/package.json +53 -0
@@ -0,0 +1,132 @@
1
+ import { BaseClip } from './base-clip';
2
+ import { IClip, IPlaybackCapable } from './iclip';
3
+ import { AudioClipJSON } from '../json-serialization';
4
+ interface IAudioClipOpts {
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 AudioClip.fromUrl('path/to/audio.mp3', {
14
+ * loop: true,
15
+ * });
16
+ *
17
+ * @example
18
+ * // Traditional approach (for advanced use)
19
+ * new AudioClip((await fetch('<mp3 url>')).body, {
20
+ * loop: true,
21
+ * }),
22
+ */
23
+ export declare class AudioClip extends BaseClip implements IPlaybackCapable {
24
+ static ctx: AudioContext | null;
25
+ ready: IClip['ready'];
26
+ private _meta;
27
+ /**
28
+ * Audio metadata
29
+ *
30
+ * ⚠️ Note, these are converted (normalized) metadata, not original audio metadata
31
+ */
32
+ get meta(): {
33
+ sampleRate: 48000;
34
+ chanCount: number;
35
+ duration: number;
36
+ width: number;
37
+ height: number;
38
+ };
39
+ private chan0Buf;
40
+ private chan1Buf;
41
+ /**
42
+ * Get complete PCM data from audio clip
43
+ */
44
+ getPCMData(): Float32Array[];
45
+ private opts;
46
+ /**
47
+ * Whether to loop the audio (hybrid JSON structure)
48
+ */
49
+ loop: boolean;
50
+ /**
51
+ * Audio volume level (0-1) (hybrid JSON structure)
52
+ */
53
+ volume: number;
54
+ /**
55
+ * Load an audio clip from a URL
56
+ * @param url Audio URL
57
+ * @param opts Audio configuration (loop, volume)
58
+ * @returns Promise that resolves to an audio clip
59
+ *
60
+ * @example
61
+ * const audioClip = await AudioClip.fromUrl('path/to/audio.mp3', {
62
+ * loop: true,
63
+ * volume: 0.8,
64
+ * });
65
+ */
66
+ static fromUrl(url: string, opts?: IAudioClipOpts): Promise<AudioClip>;
67
+ /**
68
+ * Create an AudioClip instance from a JSON object (fabric.js pattern)
69
+ * @param json The JSON object representing the clip
70
+ * @returns Promise that resolves to an AudioClip instance
71
+ */
72
+ static fromObject(json: AudioClipJSON): Promise<AudioClip>;
73
+ /**
74
+ *
75
+ * @param dataSource Audio file stream
76
+ * @param opts Audio configuration, controls volume and whether to loop
77
+ */
78
+ constructor(dataSource: ReadableStream<Uint8Array> | Float32Array[], opts?: IAudioClipOpts, src?: string);
79
+ private init;
80
+ /**
81
+ * Intercept data returned by {@link AudioClip.tick} method for secondary processing of audio data
82
+ * @param time Time when tick was called
83
+ * @param tickRet Data returned by tick
84
+ *
85
+ * @see [Remove video green screen background](https://webav-tech.github.io/WebAV/demo/3_2-chromakey-video)
86
+ */
87
+ tickInterceptor: <T extends Awaited<ReturnType<AudioClip['tick']>>>(time: number, tickRet: T) => Promise<T>;
88
+ private timestamp;
89
+ private frameOffset;
90
+ /**
91
+ * Return audio PCM data corresponding to the time difference between last and current moments
92
+ *
93
+ * If the difference exceeds 3s or current time is less than last time, reset state
94
+ * @example
95
+ * tick(0) // => []
96
+ * tick(1e6) // => [leftChanPCM(1s), rightChanPCM(1s)]
97
+ *
98
+ */
99
+ tick(time: number): Promise<{
100
+ audio: Float32Array[];
101
+ state: 'success' | 'done';
102
+ }>;
103
+ /**
104
+ * Split at specified time, return two audio clips before and after
105
+ * @param time Time in microseconds
106
+ */
107
+ split(time: number): Promise<[this, this]>;
108
+ clone(): Promise<this>;
109
+ /**
110
+ * Destroy instance and release resources
111
+ */
112
+ destroy(): void;
113
+ toJSON(main?: boolean): AudioClipJSON;
114
+ static concatAudioClip: typeof concatAudioClip;
115
+ /**
116
+ * Create HTMLAudioElement for playback
117
+ */
118
+ createPlaybackElement(): Promise<{
119
+ element: HTMLAudioElement;
120
+ objectUrl?: string;
121
+ }>;
122
+ play(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
123
+ pause(element: HTMLVideoElement | HTMLAudioElement): void;
124
+ seek(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
125
+ syncPlayback(element: HTMLVideoElement | HTMLAudioElement, isPlaying: boolean, timeSeconds: number): void;
126
+ cleanupPlayback(element: HTMLVideoElement | HTMLAudioElement, objectUrl?: string): void;
127
+ }
128
+ /**
129
+ * Concatenate multiple AudioClips
130
+ */
131
+ export declare function concatAudioClip(clips: AudioClip[], opts?: IAudioClipOpts): Promise<AudioClip>;
132
+ export {};
@@ -0,0 +1,86 @@
1
+ import { BaseSprite } from '../sprite/base-sprite';
2
+ import { IClip, IClipMeta } 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 extends BaseSprite implements IClip {
10
+ private lastVf;
11
+ protected destroyed: boolean;
12
+ /**
13
+ * Source URL or identifier for this clip
14
+ * Used for serialization and reloading from JSON
15
+ */
16
+ src: string;
17
+ abstract tick(time: number): Promise<{
18
+ video?: VideoFrame | ImageBitmap | null;
19
+ audio?: Float32Array[];
20
+ state: 'done' | 'success';
21
+ }>;
22
+ ready: Promise<IClipMeta>;
23
+ abstract readonly meta: IClipMeta;
24
+ abstract clone(): Promise<this>;
25
+ abstract split?(time: number): Promise<[this, this]>;
26
+ constructor();
27
+ /**
28
+ * Get video frame and audio at specified time without rendering to canvas
29
+ * Useful for Pixi.js rendering where canvas context is not needed
30
+ * @param time Specified time in microseconds
31
+ */
32
+ getFrame(time: number): Promise<{
33
+ video: ImageBitmap | null;
34
+ audio: Float32Array[];
35
+ done: boolean;
36
+ }>;
37
+ /**
38
+ * Draw image at specified time to canvas context and return corresponding audio data
39
+ * @param time Specified time in microseconds
40
+ */
41
+ offscreenRender(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, time: number): Promise<{
42
+ audio: Float32Array[];
43
+ done: boolean;
44
+ }>;
45
+ /**
46
+ * Set clip properties (position, size, display timeline)
47
+ * @param props Properties to set
48
+ * @param fps Optional FPS for frame-to-time conversion (default: 30)
49
+ * @returns this for method chaining
50
+ *
51
+ * @example
52
+ * // Using frames (will be converted to microseconds)
53
+ * clip.set({
54
+ * display: {
55
+ * from: 150, // frames
56
+ * to: 450, // frames (10 seconds at 30fps)
57
+ * },
58
+ * }, 30);
59
+ *
60
+ * // Using microseconds directly
61
+ * clip.set({
62
+ * display: {
63
+ * from: 5000000, // microseconds
64
+ * to: 15000000, // microseconds
65
+ * },
66
+ * });
67
+ */
68
+ set(props: {
69
+ display?: {
70
+ from?: number;
71
+ to?: number;
72
+ };
73
+ x?: number;
74
+ y?: number;
75
+ width?: number;
76
+ height?: number;
77
+ duration?: number;
78
+ }, fps?: number): this;
79
+ /**
80
+ * Base implementation of toJSON that handles common clip properties
81
+ * Subclasses should override to add their specific options
82
+ * @param main Whether this is the main clip (for Compositor)
83
+ */
84
+ toJSON(main?: boolean): ClipJSON;
85
+ destroy(): void;
86
+ }
@@ -0,0 +1,257 @@
1
+ import { BaseClip } from './base-clip';
2
+ import { IClip } from './iclip';
3
+ import { CaptionClipJSON } from '../json-serialization';
4
+ import { Application, Texture } from 'pixi.js';
5
+ export interface ICaptionClipOpts {
6
+ /**
7
+ * Font size in pixels
8
+ * @default 30
9
+ */
10
+ fontSize?: number;
11
+ /**
12
+ * Font family
13
+ * @default 'Arial'
14
+ */
15
+ fontFamily?: string;
16
+ fontUrl?: string;
17
+ /**
18
+ * Font weight (e.g., 'normal', 'bold', '400', '700')
19
+ * @default 'normal'
20
+ */
21
+ fontWeight?: string;
22
+ /**
23
+ * Font style (e.g., 'normal', 'italic')
24
+ * @default 'normal'
25
+ */
26
+ fontStyle?: string;
27
+ /**
28
+ * Text color (hex string, color name, or gradient object)
29
+ * @default '#ffffff'
30
+ */
31
+ fill?: string | number | {
32
+ type: 'gradient';
33
+ x0: number;
34
+ y0: number;
35
+ x1: number;
36
+ y1: number;
37
+ colors: Array<{
38
+ ratio: number;
39
+ color: string | number;
40
+ }>;
41
+ };
42
+ /**
43
+ * Caption data (matches caption object in JSON)
44
+ */
45
+ caption?: {
46
+ words?: Array<{
47
+ text: string;
48
+ from: number;
49
+ to: number;
50
+ isKeyWord: boolean;
51
+ }>;
52
+ colors?: {
53
+ appeared?: string;
54
+ active?: string;
55
+ activeFill?: string;
56
+ background?: string;
57
+ keyword?: string;
58
+ };
59
+ preserveKeywordColor?: boolean;
60
+ positioning?: {
61
+ videoWidth?: number;
62
+ videoHeight?: number;
63
+ bottomOffset?: number;
64
+ };
65
+ };
66
+ /**
67
+ * @deprecated Use caption.words instead
68
+ */
69
+ words?: Array<{
70
+ text: string;
71
+ from: number;
72
+ to: number;
73
+ isKeyWord: boolean;
74
+ }>;
75
+ /**
76
+ * @deprecated Use caption.colors instead
77
+ */
78
+ colors?: {
79
+ appeared?: string;
80
+ active?: string;
81
+ activeFill?: string;
82
+ background?: string;
83
+ keyword?: string;
84
+ };
85
+ /**
86
+ * @deprecated Use caption.preserveKeywordColor instead
87
+ */
88
+ preserveKeywordColor?: boolean;
89
+ /**
90
+ * @deprecated Use caption.positioning.videoWidth instead
91
+ */
92
+ videoWidth?: number;
93
+ /**
94
+ * @deprecated Use caption.positioning.videoHeight instead
95
+ */
96
+ videoHeight?: number;
97
+ /**
98
+ * @deprecated Use caption.positioning.bottomOffset instead
99
+ */
100
+ bottomOffset?: number;
101
+ /**
102
+ * Stroke color (hex string or color name) or stroke object with advanced options
103
+ */
104
+ stroke?: string | number | {
105
+ color: string | number;
106
+ width: number;
107
+ join?: 'miter' | 'round' | 'bevel';
108
+ };
109
+ /**
110
+ * Stroke width in pixels (used when stroke is a simple color)
111
+ * @default 0
112
+ */
113
+ strokeWidth?: number;
114
+ /**
115
+ * Text alignment ('left', 'center', 'right')
116
+ * @default 'center'
117
+ */
118
+ align?: 'left' | 'center' | 'right';
119
+ /**
120
+ * Drop shadow configuration
121
+ */
122
+ dropShadow?: {
123
+ color?: string | number;
124
+ alpha?: number;
125
+ blur?: number;
126
+ angle?: number;
127
+ distance?: number;
128
+ };
129
+ /**
130
+ * Word wrap width (0 = no wrap)
131
+ * @default 0
132
+ */
133
+ wordWrapWidth?: number;
134
+ /**
135
+ * Word wrap mode ('break-word' or 'normal')
136
+ * @default 'break-word'
137
+ */
138
+ wordWrap?: boolean;
139
+ /**
140
+ * Line height (multiplier)
141
+ * @default 1
142
+ */
143
+ lineHeight?: number;
144
+ /**
145
+ * Letter spacing in pixels
146
+ * @default 0
147
+ */
148
+ letterSpacing?: number;
149
+ }
150
+ /**
151
+ * Caption clip using Canvas 2D for rendering
152
+ * Each instance represents a single caption segment
153
+ *
154
+ * @example
155
+ * const captionClip = new CaptionClip('Hello World', {
156
+ * fontSize: 44,
157
+ * fontFamily: 'Arial',
158
+ * fill: '#ffffff',
159
+ * videoWidth: 1280,
160
+ * videoHeight: 720,
161
+ * });
162
+ * captionClip.display.from = 0;
163
+ * captionClip.duration = 3e6; // 3 seconds
164
+ */
165
+ export declare class CaptionClip extends BaseClip implements IClip {
166
+ ready: IClip['ready'];
167
+ private _meta;
168
+ get meta(): {
169
+ duration: number;
170
+ width: number;
171
+ height: number;
172
+ };
173
+ /**
174
+ * Caption text content (hybrid JSON structure)
175
+ */
176
+ text: string;
177
+ get style(): {
178
+ fontSize?: undefined;
179
+ fontFamily?: undefined;
180
+ fontWeight?: undefined;
181
+ fontStyle?: undefined;
182
+ color?: undefined;
183
+ align?: undefined;
184
+ stroke?: undefined;
185
+ shadow?: undefined;
186
+ } | {
187
+ fontSize: number | undefined;
188
+ fontFamily: string | undefined;
189
+ fontWeight: string | undefined;
190
+ fontStyle: string | undefined;
191
+ color: string | number | {
192
+ type: "gradient";
193
+ x0: number;
194
+ y0: number;
195
+ x1: number;
196
+ y1: number;
197
+ colors: Array<{
198
+ ratio: number;
199
+ color: string | number;
200
+ }>;
201
+ } | undefined;
202
+ align: "center" | "left" | "right" | undefined;
203
+ stroke: {
204
+ color: string | number;
205
+ width: number;
206
+ } | undefined;
207
+ shadow: {
208
+ color: string | number;
209
+ alpha: number;
210
+ blur: number;
211
+ offsetX: number;
212
+ offsetY: number;
213
+ } | undefined;
214
+ };
215
+ /**
216
+ * Bottom offset from video bottom (hybrid JSON structure)
217
+ */
218
+ bottomOffset?: number;
219
+ private opts;
220
+ private pixiTextContainer;
221
+ private renderTexture;
222
+ private wordTexts;
223
+ private extraPadding;
224
+ private textStyle;
225
+ private externalRenderer;
226
+ private pixiApp;
227
+ private originalOpts;
228
+ constructor(text: string, opts?: ICaptionClipOpts, renderer?: Application['renderer']);
229
+ private lastLoggedTime;
230
+ updateState(currentTime: number): void;
231
+ /**
232
+ * Get the PixiJS Texture (RenderTexture) for optimized rendering in Studio
233
+ * This avoids ImageBitmap → Canvas → Texture conversion
234
+ *
235
+ * @returns The RenderTexture containing the rendered caption, or null if not ready
236
+ */
237
+ getTexture(): Promise<Texture | null>;
238
+ /**
239
+ * Set an external renderer (e.g., from Studio) to avoid creating our own Pixi App
240
+ */
241
+ setRenderer(renderer: Application['renderer']): void;
242
+ private getRenderer;
243
+ tick(time: number): Promise<{
244
+ video: ImageBitmap;
245
+ state: 'success';
246
+ }>;
247
+ split(_time: number): Promise<[this, this]>;
248
+ clone(): Promise<this>;
249
+ destroy(): void;
250
+ toJSON(main?: boolean): CaptionClipJSON;
251
+ /**
252
+ * Create a CaptionClip instance from a JSON object (fabric.js pattern)
253
+ * @param json The JSON object representing the clip
254
+ * @returns Promise that resolves to a CaptionClip instance
255
+ */
256
+ static fromObject(json: CaptionClipJSON): Promise<CaptionClip>;
257
+ }
@@ -0,0 +1,120 @@
1
+ import { BaseSprite } from '../sprite/base-sprite';
2
+ export interface IClipMeta {
3
+ width: number;
4
+ height: number;
5
+ duration: number;
6
+ }
7
+ /**
8
+ * Interface that all clips must implement
9
+ *
10
+ * Clips are abstractions of different data types, providing data to other modules
11
+ *
12
+ * WebAV provides built-in {@link VideoClip}, {@link AudioClip}, {@link ImageClip} and other common clips for providing data to {@link Compositor} and {@link AVCanvas}
13
+ *
14
+ * You only need to implement this interface to create custom clips, giving you maximum flexibility to generate video content such as animations and transition effects
15
+ * @see [Custom Clip](https://webav-tech.github.io/WebAV/demo/2_6-custom-clip)
16
+ *
17
+ */
18
+ export interface IClip extends Omit<BaseSprite, 'destroy' | 'ready'> {
19
+ destroy: () => void;
20
+ readonly ready: Promise<IClipMeta>;
21
+ /**
22
+ * Extract data from clip at specified time
23
+ * @param time Time in microseconds
24
+ */
25
+ tick: (time: number) => Promise<{
26
+ video?: VideoFrame | ImageBitmap | null;
27
+ audio?: Float32Array[];
28
+ state: 'done' | 'success';
29
+ }>;
30
+ /**
31
+ * Get video frame and audio at specified time
32
+ * This method is provided by BaseClip and used by Compositor
33
+ */
34
+ getFrame(time: number): Promise<{
35
+ video: ImageBitmap | null;
36
+ audio: Float32Array[];
37
+ done: boolean;
38
+ }>;
39
+ /**
40
+ * Data metadata
41
+ */
42
+ readonly meta: IClipMeta;
43
+ /**
44
+ * Clone and return a new clip
45
+ */
46
+ clone: () => Promise<this>;
47
+ /**
48
+ * Split at specified time, return two new clips before and after that moment, commonly used in editing scenarios to split clips by time
49
+ *
50
+ * This method will not corrupt original clip data
51
+ *
52
+ * @param time Time in microseconds
53
+ * @returns
54
+ */
55
+ split?: (time: number) => Promise<[this, this]>;
56
+ /**
57
+ * Serialize clip to JSON format
58
+ * Returns a plain object with only serializable data (no circular references)
59
+ * @param main Whether this is the main clip (for Compositor)
60
+ */
61
+ toJSON(main?: boolean): any;
62
+ /**
63
+ * Set an external renderer (e.g., from Studio)
64
+ * This is called by Studio when adding clips to provide a shared renderer
65
+ * @param renderer The PixiJS renderer to use
66
+ */
67
+ setRenderer?(renderer: any): void;
68
+ }
69
+ /**
70
+ * Optional interface for clips that support HTML media element playback
71
+ * Used by Studio for interactive preview
72
+ */
73
+ export interface IPlaybackCapable {
74
+ /**
75
+ * Create and initialize HTML media element for playback
76
+ * @returns Promise resolving to the media element and optional object URL for cleanup
77
+ */
78
+ createPlaybackElement(): Promise<{
79
+ element: HTMLVideoElement | HTMLAudioElement;
80
+ objectUrl?: string;
81
+ }>;
82
+ /**
83
+ * Start playback at a specific time
84
+ * @param element The HTML media element
85
+ * @param timeSeconds Time in seconds (relative to clip start)
86
+ */
87
+ play(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
88
+ /**
89
+ * Pause playback
90
+ * @param element The HTML media element
91
+ */
92
+ pause(element: HTMLVideoElement | HTMLAudioElement): void;
93
+ /**
94
+ * Seek to a specific time
95
+ * @param element The HTML media element
96
+ * @param timeSeconds Time in seconds (relative to clip start)
97
+ */
98
+ seek(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
99
+ /**
100
+ * Sync playback state during preview
101
+ * @param element The HTML media element
102
+ * @param isPlaying Whether playback should be active
103
+ * @param timeSeconds Current time in seconds (relative to clip start)
104
+ */
105
+ syncPlayback(element: HTMLVideoElement | HTMLAudioElement, isPlaying: boolean, timeSeconds: number): void;
106
+ /**
107
+ * Clean up playback element and resources
108
+ * @param element The HTML media element
109
+ * @param objectUrl Optional object URL to revoke
110
+ */
111
+ cleanupPlayback(element: HTMLVideoElement | HTMLAudioElement, objectUrl?: string): void;
112
+ }
113
+ /**
114
+ * Default audio settings, ⚠️ do not change its values ⚠️
115
+ */
116
+ export declare const DEFAULT_AUDIO_CONF: {
117
+ readonly sampleRate: 48000;
118
+ readonly channelCount: 2;
119
+ readonly codec: "mp4a.40.2";
120
+ };
@@ -0,0 +1,110 @@
1
+ import { Texture } from 'pixi.js';
2
+ import { BaseClip } from './base-clip';
3
+ import { IClip } from './iclip';
4
+ import { ClipJSON, ImageClipJSON } from '../json-serialization';
5
+ type AnimateImgType = 'avif' | 'webp' | 'png' | 'gif';
6
+ /**
7
+ * Image clip supporting animated images
8
+ *
9
+ * Ordinary text can be converted to image clip using {@link renderTxt2ImgBitmap}
10
+ *
11
+ * @example
12
+ * // Load from URL using PixiJS Assets (optimized for Studio)
13
+ * const imgClip = await ImageClip.fromUrl('path/to/image.png');
14
+ *
15
+ * @example
16
+ * // Traditional approach (for Compositor/export)
17
+ * new ImageClip((await fetch('<img url>')).body);
18
+ *
19
+ * @example
20
+ * new ImageClip(
21
+ * await renderTxt2ImgBitmap(
22
+ * 'Watermark',
23
+ * `font-size:40px; color: white; text-shadow: 2px 2px 6px red;`,
24
+ * )
25
+ * )
26
+ *
27
+ * @see [Video composition](https://webav-tech.github.io/WebAV/demo/2_1-concat-video)
28
+ */
29
+ export declare class ImageClip extends BaseClip {
30
+ ready: IClip['ready'];
31
+ private _meta;
32
+ /**
33
+ * ⚠️ Static images have duration of Infinity
34
+ *
35
+ * When wrapping with Sprite, you need to set its duration to a finite number
36
+ *
37
+ */
38
+ get meta(): {
39
+ duration: number;
40
+ width: number;
41
+ height: number;
42
+ };
43
+ private img;
44
+ private pixiTexture;
45
+ private frames;
46
+ /**
47
+ * Load an image clip from a URL using PixiJS Assets
48
+ * This is optimized for Studio as it uses Texture directly
49
+ *
50
+ * @param url Image URL
51
+ * @param src Optional source identifier for serialization
52
+ * @returns Promise that resolves to an ImageClip instance
53
+ *
54
+ * @example
55
+ * const imgClip = await ImageClip.fromUrl('path/to/image.png');
56
+ */
57
+ static fromUrl(url: string, src?: string): Promise<ImageClip>;
58
+ /**
59
+ * Get the PixiJS Texture (if available)
60
+ * This is used for optimized rendering in Studio
61
+ */
62
+ getTexture(): Texture | null;
63
+ /**
64
+ * Static images can be initialized using stream or ImageBitmap
65
+ *
66
+ * Animated images need to use VideoFrame[] or provide image type
67
+ */
68
+ constructor(dataSource: ReadableStream | ImageBitmap | VideoFrame[] | {
69
+ type: `image/${AnimateImgType}`;
70
+ stream: ReadableStream;
71
+ }, src?: string);
72
+ private initAnimateImg;
73
+ tickInterceptor: <T extends Awaited<ReturnType<ImageClip['tick']>>>(time: number, tickRet: T) => Promise<T>;
74
+ tick(time: number): Promise<{
75
+ video: ImageBitmap | VideoFrame;
76
+ state: 'success';
77
+ }>;
78
+ split(time: number): Promise<[this, this]>;
79
+ clone(): Promise<this>;
80
+ destroy(): void;
81
+ toJSON(main?: boolean): ImageClipJSON;
82
+ /**
83
+ * Create an ImageClip instance from a JSON object (fabric.js pattern)
84
+ * @param json The JSON object representing the clip
85
+ * @returns Promise that resolves to an ImageClip instance
86
+ */
87
+ static fromObject(json: ClipJSON): Promise<ImageClip>;
88
+ /**
89
+ * Scale clip to fit within the scene dimensions while maintaining aspect ratio
90
+ * Similar to fabric.js scaleToFit
91
+ * @param sceneWidth Scene width
92
+ * @param sceneHeight Scene height
93
+ */
94
+ scaleToFit(sceneWidth: number, sceneHeight: number): Promise<void>;
95
+ /**
96
+ * Scale clip to fill the scene dimensions while maintaining aspect ratio
97
+ * May crop parts of the clip. Similar to fabric.js scaleToFill
98
+ * @param sceneWidth Scene width
99
+ * @param sceneHeight Scene height
100
+ */
101
+ scaleToFill(sceneWidth: number, sceneHeight: number): Promise<void>;
102
+ /**
103
+ * Center the clip within the scene dimensions
104
+ * Similar to fabric.js center
105
+ * @param sceneWidth Scene width
106
+ * @param sceneHeight Scene height
107
+ */
108
+ centerInScene(sceneWidth: number, sceneHeight: number): void;
109
+ }
110
+ export {};