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.
- package/LICENSE +63 -0
- package/dist/SharedSystems-pXK0PjzC.js +2691 -0
- package/dist/WebGLRenderer-B_y7ugdK.js +2639 -0
- package/dist/WebGPURenderer-ByeYcldK.js +1655 -0
- package/dist/browserAll-lTqv9nwW.js +1876 -0
- package/dist/clips/audio-clip.d.ts +128 -0
- package/dist/clips/base-clip.d.ts +116 -0
- package/dist/clips/caption-clip.d.ts +392 -0
- package/dist/clips/effect-clip.d.ts +37 -0
- package/dist/clips/iclip.d.ts +178 -0
- package/dist/clips/image-clip.d.ts +115 -0
- package/dist/clips/index.d.ts +14 -0
- package/dist/clips/placeholder-clip.d.ts +15 -0
- package/dist/clips/text-clip.d.ts +266 -0
- package/dist/clips/transition-clip.d.ts +45 -0
- package/dist/clips/video-clip.d.ts +238 -0
- package/dist/colorToUniform-C2jGzNe1.js +97 -0
- package/dist/compositor.d.ts +107 -0
- package/dist/effect/effect.d.ts +6 -0
- package/dist/effect/glsl/custom-glsl.d.ts +1017 -0
- package/dist/effect/glsl/gl-effect.d.ts +16 -0
- package/dist/effect/types.d.ts +24 -0
- package/dist/effect/vertex.d.ts +1 -0
- package/dist/event-emitter.d.ts +55 -0
- package/dist/index-CIRqJXOw.js +41882 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.es.js +28 -0
- package/dist/index.umd.js +7741 -0
- package/dist/json-serialization.d.ts +222 -0
- package/dist/mp4-utils/index.d.ts +31 -0
- package/dist/mp4-utils/mp4box-utils.d.ts +44 -0
- package/dist/mp4-utils/sample-transform.d.ts +26 -0
- package/dist/sprite/base-sprite.d.ts +183 -0
- package/dist/sprite/pixi-sprite-renderer.d.ts +49 -0
- package/dist/studio/history-manager.d.ts +46 -0
- package/dist/studio/resource-manager.d.ts +53 -0
- package/dist/studio/resource-manager.spec.d.ts +1 -0
- package/dist/studio/selection-manager.d.ts +50 -0
- package/dist/studio/timeline-model.d.ts +110 -0
- package/dist/studio/transport.d.ts +44 -0
- package/dist/studio.d.ts +380 -0
- package/dist/studio.spec.d.ts +1 -0
- package/dist/transfomer/parts/handle.d.ts +17 -0
- package/dist/transfomer/parts/snapping.d.ts +41 -0
- package/dist/transfomer/parts/wireframe.d.ts +5 -0
- package/dist/transfomer/transformer.d.ts +31 -0
- package/dist/transition/fragment.d.ts +1 -0
- package/dist/transition/glsl/custom-glsl.d.ts +231 -0
- package/dist/transition/glsl/gl-transition.d.ts +18 -0
- package/dist/transition/transition.d.ts +6 -0
- package/dist/transition/types.d.ts +29 -0
- package/dist/transition/uniforms.d.ts +35 -0
- package/dist/transition/vertex.d.ts +1 -0
- package/dist/utils/asset-manager.d.ts +6 -0
- package/dist/utils/audio-codec-detector.d.ts +28 -0
- package/dist/utils/audio.d.ts +82 -0
- package/dist/utils/chromakey.d.ts +24 -0
- package/dist/utils/color.d.ts +9 -0
- package/dist/utils/common.d.ts +7 -0
- package/dist/utils/dom.d.ts +48 -0
- package/dist/utils/fonts.d.ts +16 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/log.d.ts +27 -0
- package/dist/utils/srt-parser.d.ts +15 -0
- package/dist/utils/stream-utils.d.ts +9 -0
- package/dist/utils/video.d.ts +16 -0
- package/dist/utils/worker-timer.d.ts +1 -0
- package/dist/webworkerAll-BsrA7oC4.js +2670 -0
- package/package.json +63 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { BaseSprite, BaseSpriteEvents } from '../sprite/base-sprite';
|
|
2
|
+
export interface IClipMeta {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
duration: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ITransitionInfo {
|
|
8
|
+
name: string;
|
|
9
|
+
duration: number;
|
|
10
|
+
textureUrl?: string;
|
|
11
|
+
prevClipId?: string;
|
|
12
|
+
fromClipId?: string;
|
|
13
|
+
toClipId?: string;
|
|
14
|
+
start?: number;
|
|
15
|
+
end?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Interface that all clips must implement
|
|
19
|
+
*
|
|
20
|
+
* Clips are abstractions of different data types, providing data to other modules
|
|
21
|
+
*
|
|
22
|
+
*
|
|
23
|
+
* 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
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
export interface IClip<T extends BaseSpriteEvents = BaseSpriteEvents> extends Omit<BaseSprite<T>, 'destroy' | 'ready'> {
|
|
27
|
+
destroy: () => void;
|
|
28
|
+
readonly ready: Promise<IClipMeta>;
|
|
29
|
+
/**
|
|
30
|
+
* Clip type (e.g., 'video', 'image', 'text', 'audio')
|
|
31
|
+
*/
|
|
32
|
+
readonly type: string;
|
|
33
|
+
/**
|
|
34
|
+
* Source URL or identifier for this clip
|
|
35
|
+
*/
|
|
36
|
+
src: string;
|
|
37
|
+
/**
|
|
38
|
+
* Extract data from clip at specified time
|
|
39
|
+
* @param time Time in microseconds
|
|
40
|
+
*/
|
|
41
|
+
tick: (time: number) => Promise<{
|
|
42
|
+
video?: VideoFrame | ImageBitmap | null;
|
|
43
|
+
audio?: Float32Array[];
|
|
44
|
+
state: 'done' | 'success';
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Get video frame and audio at specified time
|
|
48
|
+
* This method is provided by BaseClip and used by Compositor
|
|
49
|
+
*/
|
|
50
|
+
getFrame(time: number): Promise<{
|
|
51
|
+
video: ImageBitmap | null;
|
|
52
|
+
audio: Float32Array[];
|
|
53
|
+
done: boolean;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Data metadata
|
|
57
|
+
*/
|
|
58
|
+
readonly meta: IClipMeta;
|
|
59
|
+
/**
|
|
60
|
+
* Clone and return a new clip
|
|
61
|
+
*/
|
|
62
|
+
clone: () => Promise<this>;
|
|
63
|
+
/**
|
|
64
|
+
* Split at specified time, return two new clips before and after that moment, commonly used in editing scenarios to split clips by time
|
|
65
|
+
*
|
|
66
|
+
* This method will not corrupt original clip data
|
|
67
|
+
*
|
|
68
|
+
* @param time Time in microseconds
|
|
69
|
+
* @returns
|
|
70
|
+
*/
|
|
71
|
+
split?: (time: number) => Promise<[this, this]>;
|
|
72
|
+
/**
|
|
73
|
+
* Serialize clip to JSON format
|
|
74
|
+
* Returns a plain object with only serializable data (no circular references)
|
|
75
|
+
* @param main Whether this is the main clip (for Compositor)
|
|
76
|
+
*/
|
|
77
|
+
toJSON(main?: boolean): any;
|
|
78
|
+
/**
|
|
79
|
+
* Set an external renderer (e.g., from Studio)
|
|
80
|
+
* This is called by Studio when adding clips to provide a shared renderer
|
|
81
|
+
* @param renderer The PixiJS renderer to use
|
|
82
|
+
*/
|
|
83
|
+
setRenderer?(renderer: any): void;
|
|
84
|
+
/**
|
|
85
|
+
* Transition info (optional)
|
|
86
|
+
*/
|
|
87
|
+
transition?: ITransitionInfo;
|
|
88
|
+
/**
|
|
89
|
+
* Audio volume level (0-1)
|
|
90
|
+
*/
|
|
91
|
+
volume: number;
|
|
92
|
+
/**
|
|
93
|
+
* Styling properties (e.g., stroke, dropShadow, borderRadius)
|
|
94
|
+
*/
|
|
95
|
+
style: any;
|
|
96
|
+
/**
|
|
97
|
+
* Get the list of visible transformer handles for this clip type
|
|
98
|
+
* Similar to Fabric.js v6 controls visibility pattern
|
|
99
|
+
* @returns Array of handle kinds that should be visible
|
|
100
|
+
*/
|
|
101
|
+
getVisibleHandles?: () => Array<'tl' | 'tr' | 'bl' | 'br' | 'ml' | 'mr' | 'mt' | 'mb' | 'rot'>;
|
|
102
|
+
/**
|
|
103
|
+
* Scale clip to fit within the scene dimensions while maintaining aspect ratio
|
|
104
|
+
*/
|
|
105
|
+
scaleToFit(sceneWidth: number, sceneHeight: number): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Scale clip to fill the scene dimensions while maintaining aspect ratio
|
|
108
|
+
*/
|
|
109
|
+
scaleToFill(sceneWidth: number, sceneHeight: number): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Center the clip within the scene dimensions
|
|
112
|
+
*/
|
|
113
|
+
centerInScene(sceneWidth: number, sceneHeight: number): void;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Optional interface for clips that support HTML media element playback
|
|
117
|
+
* Used by Studio for interactive preview
|
|
118
|
+
*/
|
|
119
|
+
export interface IPlaybackCapable {
|
|
120
|
+
/**
|
|
121
|
+
* Create and initialize HTML media element for playback
|
|
122
|
+
* @returns Promise resolving to the media element and optional object URL for cleanup
|
|
123
|
+
*/
|
|
124
|
+
createPlaybackElement(): Promise<{
|
|
125
|
+
element: HTMLVideoElement | HTMLAudioElement;
|
|
126
|
+
objectUrl?: string;
|
|
127
|
+
}>;
|
|
128
|
+
/**
|
|
129
|
+
* Start playback at a specific time
|
|
130
|
+
* @param element The HTML media element
|
|
131
|
+
* @param timeSeconds Time in seconds (relative to clip start)
|
|
132
|
+
*/
|
|
133
|
+
play(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Pause playback
|
|
136
|
+
* @param element The HTML media element
|
|
137
|
+
*/
|
|
138
|
+
pause(element: HTMLVideoElement | HTMLAudioElement): void;
|
|
139
|
+
/**
|
|
140
|
+
* Seek to a specific time
|
|
141
|
+
* @param element The HTML media element
|
|
142
|
+
* @param timeSeconds Time in seconds (relative to clip start)
|
|
143
|
+
*/
|
|
144
|
+
seek(element: HTMLVideoElement | HTMLAudioElement, timeSeconds: number): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Sync playback state during preview
|
|
147
|
+
* @param element The HTML media element
|
|
148
|
+
* @param isPlaying Whether playback should be active
|
|
149
|
+
* @param timeSeconds Current time in seconds (relative to clip start)
|
|
150
|
+
*/
|
|
151
|
+
syncPlayback(element: HTMLVideoElement | HTMLAudioElement, isPlaying: boolean, timeSeconds: number): void;
|
|
152
|
+
/**
|
|
153
|
+
* Clean up playback element and resources
|
|
154
|
+
* @param element The HTML media element
|
|
155
|
+
* @param objectUrl Optional object URL to revoke
|
|
156
|
+
*/
|
|
157
|
+
cleanupPlayback(element: HTMLVideoElement | HTMLAudioElement, objectUrl?: string): void;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get the default audio configuration
|
|
161
|
+
* This function returns a promise that resolves to the best supported audio codec
|
|
162
|
+
*/
|
|
163
|
+
export declare function getDefaultAudioConf(): Promise<{
|
|
164
|
+
codec: string;
|
|
165
|
+
sampleRate: number;
|
|
166
|
+
channelCount: number;
|
|
167
|
+
}>;
|
|
168
|
+
/**
|
|
169
|
+
* Synchronous version that returns cached codec or a default fallback
|
|
170
|
+
* Use this only when you need synchronous access (e.g., in constants)
|
|
171
|
+
* Prefer getDefaultAudioConf() for async contexts
|
|
172
|
+
*/
|
|
173
|
+
export declare const DEFAULT_AUDIO_CONF: {
|
|
174
|
+
readonly codec: string;
|
|
175
|
+
readonly codecType: "aac" | "opus";
|
|
176
|
+
readonly sampleRate: number;
|
|
177
|
+
readonly channelCount: number;
|
|
178
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Texture } from 'pixi.js';
|
|
2
|
+
import { BaseClip } from './base-clip';
|
|
3
|
+
import { IClip } from './iclip';
|
|
4
|
+
import { ClipJSON, ImageJSON } 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 Image.fromUrl('path/to/image.png');
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Traditional approach (for Compositor/export)
|
|
17
|
+
* new Image((await fetch('<img url>')).body);
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* new Image(
|
|
21
|
+
* await renderTxt2ImgBitmap(
|
|
22
|
+
* 'Watermark',
|
|
23
|
+
* `font-size:40px; color: white; text-shadow: 2px 2px 6px red;`,
|
|
24
|
+
* )
|
|
25
|
+
* )
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
export declare class Image extends BaseClip implements IClip {
|
|
29
|
+
readonly type = "Image";
|
|
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
|
+
* Unique identifier for this clip instance
|
|
48
|
+
*/
|
|
49
|
+
id: string;
|
|
50
|
+
/**
|
|
51
|
+
* Array of effects to be applied to this clip
|
|
52
|
+
* Each effect specifies key, startTime, duration, and optional targets
|
|
53
|
+
*/
|
|
54
|
+
effects: Array<{
|
|
55
|
+
id: string;
|
|
56
|
+
key: string;
|
|
57
|
+
startTime: number;
|
|
58
|
+
duration: number;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Load an image clip from a URL using PixiJS Assets
|
|
62
|
+
* This is optimized for Studio as it uses Texture directly
|
|
63
|
+
*
|
|
64
|
+
* @param url Image URL
|
|
65
|
+
* @param src Optional source identifier for serialization
|
|
66
|
+
* @returns Promise that resolves to an Image instance
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* const imgClip = await Image.fromUrl('path/to/image.png');
|
|
70
|
+
*/
|
|
71
|
+
static fromUrl(url: string, src?: string): Promise<Image>;
|
|
72
|
+
/**
|
|
73
|
+
* Get the PixiJS Texture (if available)
|
|
74
|
+
* This is used for optimized rendering in Studio
|
|
75
|
+
*/
|
|
76
|
+
getTexture(): Texture | null;
|
|
77
|
+
/**
|
|
78
|
+
* Static images can be initialized using stream or ImageBitmap
|
|
79
|
+
*
|
|
80
|
+
* Animated images need to use VideoFrame[] or provide image type
|
|
81
|
+
*/
|
|
82
|
+
constructor(dataSource: ReadableStream | ImageBitmap | VideoFrame[] | {
|
|
83
|
+
type: `image/${AnimateImgType}`;
|
|
84
|
+
stream: ReadableStream;
|
|
85
|
+
}, src?: string);
|
|
86
|
+
private initAnimateImg;
|
|
87
|
+
tickInterceptor: <T extends Awaited<ReturnType<Image['tick']>>>(time: number, tickRet: T) => Promise<T>;
|
|
88
|
+
tick(time: number): Promise<{
|
|
89
|
+
video: ImageBitmap | VideoFrame;
|
|
90
|
+
state: 'success';
|
|
91
|
+
}>;
|
|
92
|
+
split(time: number): Promise<[this, this]>;
|
|
93
|
+
clone(): Promise<this>;
|
|
94
|
+
addEffect(effect: {
|
|
95
|
+
id: string;
|
|
96
|
+
key: string;
|
|
97
|
+
startTime: number;
|
|
98
|
+
duration: number;
|
|
99
|
+
}): void;
|
|
100
|
+
editEffect(effectId: string, newEffectData: Partial<{
|
|
101
|
+
key: string;
|
|
102
|
+
startTime: number;
|
|
103
|
+
duration: number;
|
|
104
|
+
}>): void;
|
|
105
|
+
removeEffect(effectId: string): void;
|
|
106
|
+
destroy(): void;
|
|
107
|
+
toJSON(main?: boolean): ImageJSON;
|
|
108
|
+
/**
|
|
109
|
+
* Create an Image instance from a JSON object (fabric.js pattern)
|
|
110
|
+
* @param json The JSON object representing the clip
|
|
111
|
+
* @returns Promise that resolves to an Image instance
|
|
112
|
+
*/
|
|
113
|
+
static fromObject(json: ClipJSON): Promise<Image>;
|
|
114
|
+
}
|
|
115
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './audio-clip';
|
|
2
|
+
export * from './caption-clip';
|
|
3
|
+
export * from './iclip';
|
|
4
|
+
export * from './image-clip';
|
|
5
|
+
export * from './video-clip';
|
|
6
|
+
export { Video } from './video-clip';
|
|
7
|
+
export type { IMP4ClipOpts } from './video-clip';
|
|
8
|
+
export * from './text-clip';
|
|
9
|
+
export * from './effect-clip';
|
|
10
|
+
export { Effect } from './effect-clip';
|
|
11
|
+
export * from './placeholder-clip';
|
|
12
|
+
export { Placeholder } from './placeholder-clip';
|
|
13
|
+
export * from './transition-clip';
|
|
14
|
+
export { Transition } from './transition-clip';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseClip } from './base-clip';
|
|
2
|
+
import { IClipMeta } from './iclip';
|
|
3
|
+
export declare class Placeholder extends BaseClip {
|
|
4
|
+
type: string;
|
|
5
|
+
meta: IClipMeta;
|
|
6
|
+
constructor(src: string, meta?: Partial<IClipMeta>, type?: string);
|
|
7
|
+
private placeholderFrame;
|
|
8
|
+
tick(time: number): Promise<{
|
|
9
|
+
video?: ImageBitmap | null;
|
|
10
|
+
audio?: Float32Array[];
|
|
11
|
+
state: 'done' | 'success';
|
|
12
|
+
}>;
|
|
13
|
+
clone(): Promise<this>;
|
|
14
|
+
split(time: number): Promise<[this, this]>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { Application, Texture } from 'pixi.js';
|
|
2
|
+
import { BaseClip } from './base-clip';
|
|
3
|
+
import { IClip } from './iclip';
|
|
4
|
+
import { TextJSON } from '../json-serialization';
|
|
5
|
+
export interface ITextOpts {
|
|
6
|
+
/**
|
|
7
|
+
* Font size in pixels
|
|
8
|
+
* @default 40
|
|
9
|
+
*/
|
|
10
|
+
fontSize?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Font family
|
|
13
|
+
* @default 'Roboto'
|
|
14
|
+
*/
|
|
15
|
+
fontFamily?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Font weight (e.g., 'normal', 'bold', '400', '700')
|
|
18
|
+
* @default 'normal'
|
|
19
|
+
*/
|
|
20
|
+
fontWeight?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Font style (e.g., 'normal', 'italic')
|
|
23
|
+
* @default 'normal'
|
|
24
|
+
*/
|
|
25
|
+
fontStyle?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Font URL for custom fonts
|
|
28
|
+
*/
|
|
29
|
+
fontUrl?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Text color (hex string, color name, or gradient object)
|
|
32
|
+
* @default '#ffffff'
|
|
33
|
+
*/
|
|
34
|
+
fill?: string | number | {
|
|
35
|
+
type: 'gradient';
|
|
36
|
+
x0: number;
|
|
37
|
+
y0: number;
|
|
38
|
+
x1: number;
|
|
39
|
+
y1: number;
|
|
40
|
+
colors: Array<{
|
|
41
|
+
ratio: number;
|
|
42
|
+
color: string | number;
|
|
43
|
+
}>;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Stroke color (hex string or color name) or stroke object with advanced options
|
|
47
|
+
*/
|
|
48
|
+
stroke?: string | number | {
|
|
49
|
+
color: string | number;
|
|
50
|
+
width: number;
|
|
51
|
+
join?: 'miter' | 'round' | 'bevel';
|
|
52
|
+
cap?: 'butt' | 'round' | 'square';
|
|
53
|
+
miterLimit?: number;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Stroke width in pixels (used when stroke is a simple color)
|
|
57
|
+
* @default 0
|
|
58
|
+
*/
|
|
59
|
+
strokeWidth?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Text alignment ('left', 'center', 'right')
|
|
62
|
+
* @default 'left'
|
|
63
|
+
*/
|
|
64
|
+
align?: 'left' | 'center' | 'right';
|
|
65
|
+
/**
|
|
66
|
+
* Alias for align to match UI property naming
|
|
67
|
+
*/
|
|
68
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
69
|
+
/**
|
|
70
|
+
* Vertical alignment ('top', 'center', 'bottom')
|
|
71
|
+
* @default 'top'
|
|
72
|
+
*/
|
|
73
|
+
verticalAlign?: 'top' | 'center' | 'bottom' | 'underline' | 'overline' | 'strikethrough';
|
|
74
|
+
/**
|
|
75
|
+
* Drop shadow configuration
|
|
76
|
+
*/
|
|
77
|
+
dropShadow?: {
|
|
78
|
+
color?: string | number;
|
|
79
|
+
alpha?: number;
|
|
80
|
+
blur?: number;
|
|
81
|
+
angle?: number;
|
|
82
|
+
distance?: number;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Word wrap width (0 = no wrap)
|
|
86
|
+
* @default 0
|
|
87
|
+
*/
|
|
88
|
+
wordWrapWidth?: number;
|
|
89
|
+
/**
|
|
90
|
+
* Word wrap mode ('break-word' or 'normal')
|
|
91
|
+
* @default 'break-word'
|
|
92
|
+
*/
|
|
93
|
+
wordWrap?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Line height (multiplier)
|
|
96
|
+
* @default 1
|
|
97
|
+
*/
|
|
98
|
+
lineHeight?: number;
|
|
99
|
+
/**
|
|
100
|
+
* Letter spacing in pixels
|
|
101
|
+
* @default 0
|
|
102
|
+
*/
|
|
103
|
+
letterSpacing?: number;
|
|
104
|
+
/**
|
|
105
|
+
* Text case transformation
|
|
106
|
+
* @default 'none'
|
|
107
|
+
*/
|
|
108
|
+
textCase?: 'none' | 'uppercase' | 'lowercase' | 'title';
|
|
109
|
+
/**
|
|
110
|
+
* Text decoration ('none', 'underline', 'line-through', 'overline')
|
|
111
|
+
* @default 'none'
|
|
112
|
+
*/
|
|
113
|
+
textDecoration?: 'none' | 'underline' | 'line-through' | 'overline';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Text clip using PixiJS Text for rendering
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* const textClip = new Text('Hello World', {
|
|
120
|
+
* fontSize: 48,
|
|
121
|
+
* fill: '#ffffff',
|
|
122
|
+
* stroke: '#000000',
|
|
123
|
+
* strokeWidth: 2,
|
|
124
|
+
* dropShadow: {
|
|
125
|
+
* color: '#000000',
|
|
126
|
+
* alpha: 0.5,
|
|
127
|
+
* blur: 4,
|
|
128
|
+
* distance: 2,
|
|
129
|
+
* },
|
|
130
|
+
* });
|
|
131
|
+
* textClip.duration = 5e6; // 5 seconds
|
|
132
|
+
*/
|
|
133
|
+
export declare class Text extends BaseClip {
|
|
134
|
+
readonly type = "Text";
|
|
135
|
+
ready: IClip['ready'];
|
|
136
|
+
private _meta;
|
|
137
|
+
get meta(): {
|
|
138
|
+
duration: number;
|
|
139
|
+
width: number;
|
|
140
|
+
height: number;
|
|
141
|
+
};
|
|
142
|
+
get width(): number;
|
|
143
|
+
set width(v: number);
|
|
144
|
+
get height(): number;
|
|
145
|
+
set height(v: number);
|
|
146
|
+
private _lastContentWidth;
|
|
147
|
+
private _lastContentHeight;
|
|
148
|
+
private _text;
|
|
149
|
+
/**
|
|
150
|
+
* Text content (hybrid JSON structure)
|
|
151
|
+
*/
|
|
152
|
+
get text(): string;
|
|
153
|
+
set text(v: string);
|
|
154
|
+
/**
|
|
155
|
+
* Text styling (hybrid JSON structure)
|
|
156
|
+
* Provides direct access to styling properties
|
|
157
|
+
*/
|
|
158
|
+
/**
|
|
159
|
+
* Text styling (hybrid JSON structure)
|
|
160
|
+
* Provides direct access to styling properties
|
|
161
|
+
*/
|
|
162
|
+
get style(): any;
|
|
163
|
+
set style(opts: Partial<ITextOpts>);
|
|
164
|
+
/**
|
|
165
|
+
* Text alignment proxy for compatibility with UI
|
|
166
|
+
*/
|
|
167
|
+
get textAlign(): 'left' | 'center' | 'right';
|
|
168
|
+
set textAlign(v: 'left' | 'center' | 'right');
|
|
169
|
+
/**
|
|
170
|
+
* Vertical alignment or decoration proxy
|
|
171
|
+
*/
|
|
172
|
+
get verticalAlign(): string;
|
|
173
|
+
set verticalAlign(v: string);
|
|
174
|
+
/**
|
|
175
|
+
* Text case proxy
|
|
176
|
+
*/
|
|
177
|
+
get textCase(): string;
|
|
178
|
+
set textCase(v: 'none' | 'uppercase' | 'lowercase' | 'title');
|
|
179
|
+
private pixiTextContainer;
|
|
180
|
+
private wordTexts;
|
|
181
|
+
private textStyle;
|
|
182
|
+
private textStyleBase;
|
|
183
|
+
private renderTexture;
|
|
184
|
+
private externalRenderer;
|
|
185
|
+
private pixiApp;
|
|
186
|
+
private originalOpts;
|
|
187
|
+
/**
|
|
188
|
+
* Unique identifier for this clip instance
|
|
189
|
+
*/
|
|
190
|
+
id: string;
|
|
191
|
+
/**
|
|
192
|
+
* Array of effects to be applied to this clip
|
|
193
|
+
* Each effect specifies key, startTime, duration, and optional targets
|
|
194
|
+
*/
|
|
195
|
+
effects: Array<{
|
|
196
|
+
id: string;
|
|
197
|
+
key: string;
|
|
198
|
+
startTime: number;
|
|
199
|
+
duration: number;
|
|
200
|
+
}>;
|
|
201
|
+
constructor(text: string, opts?: ITextOpts, renderer?: Application['renderer']);
|
|
202
|
+
/**
|
|
203
|
+
* Set an external renderer (e.g., from Studio) to avoid creating our own Pixi App
|
|
204
|
+
* This is an optimization for Studio preview
|
|
205
|
+
* Can be called before ready() completes
|
|
206
|
+
*/
|
|
207
|
+
setRenderer(renderer: Application['renderer']): void;
|
|
208
|
+
/**
|
|
209
|
+
* Get the renderer for rendering text to RenderTexture
|
|
210
|
+
* Creates a minimal renderer as fallback if no external renderer is provided
|
|
211
|
+
*/
|
|
212
|
+
private getRenderer;
|
|
213
|
+
/**
|
|
214
|
+
* Get the PixiJS Texture (RenderTexture) for optimized rendering in Studio
|
|
215
|
+
* This avoids ImageBitmap → Canvas → Texture conversion
|
|
216
|
+
*
|
|
217
|
+
* @returns The RenderTexture containing the rendered text, or null if not ready
|
|
218
|
+
*/
|
|
219
|
+
getTexture(): Promise<Texture | null>;
|
|
220
|
+
tick(_time: number): Promise<{
|
|
221
|
+
video: ImageBitmap;
|
|
222
|
+
state: 'success';
|
|
223
|
+
}>;
|
|
224
|
+
split(_time: number): Promise<[this, this]>;
|
|
225
|
+
addEffect(effect: {
|
|
226
|
+
id: string;
|
|
227
|
+
key: string;
|
|
228
|
+
startTime: number;
|
|
229
|
+
duration: number;
|
|
230
|
+
}): void;
|
|
231
|
+
editEffect(effectId: string, newEffectData: Partial<{
|
|
232
|
+
key: string;
|
|
233
|
+
startTime: number;
|
|
234
|
+
duration: number;
|
|
235
|
+
}>): void;
|
|
236
|
+
removeEffect(effectId: string): void;
|
|
237
|
+
clone(): Promise<this>;
|
|
238
|
+
/**
|
|
239
|
+
* Update text styling options and refresh the texture
|
|
240
|
+
* This is used for dynamic updates like resizing with text reflow
|
|
241
|
+
*/
|
|
242
|
+
updateStyle(opts: Partial<ITextOpts>): Promise<void>;
|
|
243
|
+
/**
|
|
244
|
+
* Refresh the internal Pixi Text and RenderTexture
|
|
245
|
+
* Calculates dimensions based on text bounds and wrapping options
|
|
246
|
+
*/
|
|
247
|
+
private refreshText;
|
|
248
|
+
/**
|
|
249
|
+
* Helper to create PixiJS TextStyle options from Text options
|
|
250
|
+
*/
|
|
251
|
+
private createStyleFromOpts;
|
|
252
|
+
destroy(): void;
|
|
253
|
+
toJSON(main?: boolean): TextJSON;
|
|
254
|
+
/**
|
|
255
|
+
* Create a Text instance from a JSON object (fabric.js pattern)
|
|
256
|
+
* @param json The JSON object representing the clip
|
|
257
|
+
* @returns Promise that resolves to a Text instance
|
|
258
|
+
*/
|
|
259
|
+
static fromObject(json: TextJSON): Promise<Text>;
|
|
260
|
+
/**
|
|
261
|
+
* Override handle visibility for text clips
|
|
262
|
+
* Text clips should only show: mr (mid-right), mb (mid-bottom), br (bottom-right), and rot (rotation)
|
|
263
|
+
* This allows resizing width and height independently while preventing corner handles that might distort text
|
|
264
|
+
*/
|
|
265
|
+
getVisibleHandles(): Array<'tl' | 'tr' | 'bl' | 'br' | 'ml' | 'mr' | 'mt' | 'mb' | 'rot'>;
|
|
266
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BaseClip } from './base-clip';
|
|
2
|
+
import { IClip } from './iclip';
|
|
3
|
+
import { TransitionKey } from '../transition/glsl/gl-transition';
|
|
4
|
+
export declare class Transition extends BaseClip {
|
|
5
|
+
readonly type = "Transition";
|
|
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 transition configuration
|
|
19
|
+
*/
|
|
20
|
+
transitionEffect: {
|
|
21
|
+
id: string;
|
|
22
|
+
key: TransitionKey;
|
|
23
|
+
name: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* ID of the clip from which the transition starts
|
|
27
|
+
*/
|
|
28
|
+
fromClipId: string | null;
|
|
29
|
+
/**
|
|
30
|
+
* ID of the clip to which the transition ends
|
|
31
|
+
*/
|
|
32
|
+
toClipId: string | null;
|
|
33
|
+
constructor(transitionKey: TransitionKey);
|
|
34
|
+
clone(): Promise<this>;
|
|
35
|
+
tick(_time: number): Promise<{
|
|
36
|
+
video: ImageBitmap | undefined;
|
|
37
|
+
state: 'success';
|
|
38
|
+
}>;
|
|
39
|
+
split(_time: number): Promise<[this, this]>;
|
|
40
|
+
toJSON(main?: boolean): any;
|
|
41
|
+
/**
|
|
42
|
+
* Create a Transition instance from a JSON object
|
|
43
|
+
*/
|
|
44
|
+
static fromObject(json: any): Promise<Transition>;
|
|
45
|
+
}
|