@linker-design-plus/timeline-track 2.2.0 → 2.2.2
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/dist/core/controllers/previewBackend.d.ts +1 -0
- package/dist/core/facade/timelineManager.d.ts +2 -0
- package/dist/core/models/types.d.ts +24 -0
- package/dist/core/preview/mediaHelpers.d.ts +3 -0
- package/dist/core/preview/previewDomCompositor.d.ts +4 -1
- package/dist/core/preview/previewEngine.d.ts +3 -0
- package/dist/core/preview/previewPlaybackSlot.d.ts +7 -1
- package/dist/core/preview/previewSourceService.d.ts +1 -2
- package/dist/core/preview/previewSyncCoordinator.d.ts +1 -1
- package/dist/core/preview/previewTextLayer.d.ts +7 -0
- package/dist/core/preview/textClipExportLayout.d.ts +5 -0
- package/dist/core/preview/textPreviewLayout.d.ts +25 -1
- package/dist/core/preview/types.d.ts +1 -0
- package/dist/core/resources/resourceCache/resourceCacheManager.d.ts +10 -0
- package/dist/index.cjs.js +48 -48
- package/dist/index.es.js +2474 -2171
- package/package.json +1 -1
|
@@ -27,6 +27,7 @@ export interface TimelinePreviewBackendCallbacks {
|
|
|
27
27
|
layoutWidth: number;
|
|
28
28
|
layoutHeight: number;
|
|
29
29
|
}) => void;
|
|
30
|
+
onTextLayoutResolved?: (clipId: string, layout: import('../models/types').TextClipResolvedLayout) => void;
|
|
30
31
|
onPendingPreviewRetry?: () => void;
|
|
31
32
|
onRuntimeError?: (error: unknown) => void;
|
|
32
33
|
/** 预览层文字交互(点击字幕或文字变换控件)时若时间线处于播放中,用于请求暂停 */
|
|
@@ -349,6 +349,7 @@ export declare class TimelineManager {
|
|
|
349
349
|
private clearTimelineClipMediaStatus;
|
|
350
350
|
private getFailedPreviewClipIds;
|
|
351
351
|
private getExportComposition;
|
|
352
|
+
private resolveTextClipExportLayout;
|
|
352
353
|
private getExportCoverUrl;
|
|
353
354
|
exportTimeline(): TimelineExportData;
|
|
354
355
|
importTimeline(data: TimelineExportData): Promise<void>;
|
|
@@ -641,6 +642,7 @@ export declare class TimelineManager {
|
|
|
641
642
|
private resolveSelectionChangeData;
|
|
642
643
|
private commitPreviewVisualTransform;
|
|
643
644
|
private commitPreviewTextLayout;
|
|
645
|
+
private commitPreviewTextResolvedLayout;
|
|
644
646
|
private commitPreviewTextFontSize;
|
|
645
647
|
private commitPreviewTextRotation;
|
|
646
648
|
clearAllTracksAndClips(): void;
|
|
@@ -32,6 +32,26 @@ export interface TextClipStyle {
|
|
|
32
32
|
}
|
|
33
33
|
export declare const DEFAULT_TEXT_CLIP_STYLE: TextClipStyle;
|
|
34
34
|
export declare function resolveTextClipStyle(style?: Partial<TextClipStyle> | null): TextClipStyle;
|
|
35
|
+
export type TextClipLayoutMode = 'auto' | 'manual';
|
|
36
|
+
/** 预览层布局完成后的归一化快照,供导出与后端渲染。 */
|
|
37
|
+
export interface TextClipResolvedLayout {
|
|
38
|
+
/** 与 export composition 一致的 baseline 画布尺寸(短边 720)。 */
|
|
39
|
+
compositionWidth: number;
|
|
40
|
+
compositionHeight: number;
|
|
41
|
+
/** 文本框宽(baseline 参考画布 px,非最终成片 px)。 */
|
|
42
|
+
layoutWidth: number;
|
|
43
|
+
/** 文本框高(baseline 参考画布 px,非最终成片 px)。 */
|
|
44
|
+
layoutHeight: number;
|
|
45
|
+
/** layoutWidth / compositionWidth */
|
|
46
|
+
layoutWidthRatio: number;
|
|
47
|
+
/** layoutHeight / compositionHeight */
|
|
48
|
+
layoutHeightRatio: number;
|
|
49
|
+
/** 框中心锚点,画幅归一化 0–1(已从 legacy 底锚迁移)。 */
|
|
50
|
+
centerX: number;
|
|
51
|
+
centerY: number;
|
|
52
|
+
layoutMode: TextClipLayoutMode;
|
|
53
|
+
anchorVersion: 1;
|
|
54
|
+
}
|
|
35
55
|
export type PreviewBackendType = 'dom' | 'canvas' | 'auto';
|
|
36
56
|
export interface Mp4PreviewMediaSource {
|
|
37
57
|
url: string;
|
|
@@ -108,6 +128,7 @@ export interface ClipConfig {
|
|
|
108
128
|
volume?: number;
|
|
109
129
|
textContent?: string;
|
|
110
130
|
textStyle?: Partial<TextClipStyle>;
|
|
131
|
+
textResolvedLayout?: TextClipResolvedLayout;
|
|
111
132
|
ttsSourceTextClipId?: string;
|
|
112
133
|
ttsVoiceId?: string;
|
|
113
134
|
ttsVoiceName?: string;
|
|
@@ -136,6 +157,7 @@ export interface ClipEntity {
|
|
|
136
157
|
volume?: number;
|
|
137
158
|
textContent?: string;
|
|
138
159
|
textStyle?: TextClipStyle;
|
|
160
|
+
textResolvedLayout?: TextClipResolvedLayout;
|
|
139
161
|
ttsSourceTextClipId?: string;
|
|
140
162
|
ttsVoiceId?: string;
|
|
141
163
|
ttsVoiceName?: string;
|
|
@@ -518,6 +540,7 @@ export interface TimelineCompositionExportData {
|
|
|
518
540
|
height: number;
|
|
519
541
|
aspectRatio: string;
|
|
520
542
|
mode: PreviewAspectRatioMode;
|
|
543
|
+
textPreviewFont?: TextPreviewFontConfig;
|
|
521
544
|
}
|
|
522
545
|
export interface TrackExportData {
|
|
523
546
|
id: string;
|
|
@@ -548,6 +571,7 @@ export interface ClipExportData {
|
|
|
548
571
|
volume?: number;
|
|
549
572
|
textContent?: string;
|
|
550
573
|
textStyle?: TextClipStyle;
|
|
574
|
+
textResolvedLayout?: TextClipResolvedLayout;
|
|
551
575
|
ttsSourceTextClipId?: string;
|
|
552
576
|
ttsVoiceId?: string;
|
|
553
577
|
ttsVoiceName?: string;
|
|
@@ -22,3 +22,6 @@ export declare function getMediaDebugState(element: HTMLMediaElement): Diagnosti
|
|
|
22
22
|
export declare function doesSlotSourceMatchDesired(configuredSource: string | null, assignedSource: string | null, desiredSource: string | null): boolean;
|
|
23
23
|
export declare function getSlotSeekThresholdSeconds(role: 'current' | 'preload', playbackRate: number): number;
|
|
24
24
|
export declare function buildPreviewSourceCacheKey(clip: ActiveClipPlaybackInfo['clip']): string;
|
|
25
|
+
export declare function buildObjectUrlHolderId(clipId: string | undefined | null): string | null;
|
|
26
|
+
export declare function isBlobObjectUrl(url: string | null | undefined): url is string;
|
|
27
|
+
export declare function resolveBlobObjectUrl(objectUrl: string | null | undefined, playbackUrl: string): string | null;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { ActiveClipPlaybackInfo, PreviewAspectRatio } from '../models/types';
|
|
2
2
|
import { resolveClipVisualTransform, type PreviewFrameSize } from '../controllers/previewTransformMath';
|
|
3
3
|
import { PreviewTransformOverlay, type PreviewTransformOverlayState } from '../controllers/previewTransformOverlay';
|
|
4
|
-
import { type TextLayoutStyleOverride } from './textPreviewLayout';
|
|
4
|
+
import { type TextLayoutStyleOverride, type TextPreviewBoxLayout } from './textPreviewLayout';
|
|
5
5
|
import type { PreviewPlaybackSlot } from './previewPlaybackSlot';
|
|
6
6
|
export declare class PreviewDomCompositor {
|
|
7
7
|
private container;
|
|
8
8
|
private rootElement;
|
|
9
9
|
private frameElement;
|
|
10
10
|
private resizeObserver;
|
|
11
|
+
private onFrameLayoutChange;
|
|
11
12
|
private requestedAspectRatio;
|
|
12
13
|
private resolvedAutoAspectRatio;
|
|
13
14
|
readonly transformOverlay: PreviewTransformOverlay;
|
|
@@ -15,6 +16,7 @@ export declare class PreviewDomCompositor {
|
|
|
15
16
|
attach(container: HTMLElement, options: {
|
|
16
17
|
rootClassName?: string;
|
|
17
18
|
frameClassName?: string;
|
|
19
|
+
onFrameLayoutChange?: () => void;
|
|
18
20
|
}): void;
|
|
19
21
|
detach(): void;
|
|
20
22
|
getFrameElement(): HTMLDivElement | null;
|
|
@@ -29,6 +31,7 @@ export declare class PreviewDomCompositor {
|
|
|
29
31
|
entry: ActiveClipPlaybackInfo;
|
|
30
32
|
element: HTMLElement;
|
|
31
33
|
} | undefined;
|
|
34
|
+
getLayout?: (clipId: string) => TextPreviewBoxLayout | null;
|
|
32
35
|
getTransientFontSize: (clipId: string) => number | null;
|
|
33
36
|
getTransientRotation: (clipId: string) => number | null;
|
|
34
37
|
getTextLayoutOverride?: (clipId: string) => TextLayoutStyleOverride | null;
|
|
@@ -60,6 +60,8 @@ export declare class PreviewEngine {
|
|
|
60
60
|
get lastRuntimeState(): PreviewRuntimeState;
|
|
61
61
|
refreshRuntimeState(): void;
|
|
62
62
|
private applyTrackPlan;
|
|
63
|
+
private readonly releaseTrackedObjectUrl;
|
|
64
|
+
private rememberSlotObjectUrl;
|
|
63
65
|
private getTrackSlots;
|
|
64
66
|
private collectSlots;
|
|
65
67
|
private buildLoadingState;
|
|
@@ -76,6 +78,7 @@ export declare class PreviewEngine {
|
|
|
76
78
|
private getTextLayoutOptions;
|
|
77
79
|
private handlePreviewTransformChange;
|
|
78
80
|
refreshVisualLayout(): void;
|
|
81
|
+
private refreshTextSelectionOverlay;
|
|
79
82
|
private refreshPendingOverlay;
|
|
80
83
|
private syncLoadingProbe;
|
|
81
84
|
private syncClockProbe;
|
|
@@ -21,6 +21,11 @@ export declare class PreviewPlaybackSlot implements PlaybackSlotState {
|
|
|
21
21
|
boundStableKey: string | null;
|
|
22
22
|
desiredSource: string | null;
|
|
23
23
|
objectUrl: string | null;
|
|
24
|
+
objectUrlHolderId: string | null;
|
|
25
|
+
takeTrackedObjectUrl(): {
|
|
26
|
+
url: string | null;
|
|
27
|
+
holderId: string | null;
|
|
28
|
+
};
|
|
24
29
|
requestedPlayState: PlayState;
|
|
25
30
|
isActive: boolean;
|
|
26
31
|
isLoading: boolean;
|
|
@@ -32,6 +37,7 @@ export declare class PreviewPlaybackSlot implements PlaybackSlotState {
|
|
|
32
37
|
hasReadyEventSinceSourceChange: boolean;
|
|
33
38
|
pendingClockAlignmentMediaTime: number | null;
|
|
34
39
|
sourceGen: number;
|
|
40
|
+
private loadSourceGen;
|
|
35
41
|
sourceNode: MediaElementAudioSourceNode | null;
|
|
36
42
|
gainNode: GainNode | null;
|
|
37
43
|
audioRoutingFailed: boolean;
|
|
@@ -48,7 +54,7 @@ export declare class PreviewPlaybackSlot implements PlaybackSlotState {
|
|
|
48
54
|
applyPlayback(entry: ActiveClipPlaybackInfo, playState: PlayState, speed: number, visible: boolean, zIndex: number): void;
|
|
49
55
|
sourceMatchesDesired(): boolean;
|
|
50
56
|
maybeResumePlayback(reason: 'canplay' | 'seeked' | 'runtime-check'): void;
|
|
51
|
-
destroy(releaseObjectUrl: (url: string | null) => void): void;
|
|
57
|
+
destroy(releaseObjectUrl: (url: string | null, holderId: string | null) => void): void;
|
|
52
58
|
private syncCurrentPlayback;
|
|
53
59
|
private preparePreload;
|
|
54
60
|
private setVisible;
|
|
@@ -10,7 +10,7 @@ export interface PreviewSourceServiceDependencies {
|
|
|
10
10
|
}
|
|
11
11
|
export declare class PreviewSourceService {
|
|
12
12
|
private readonly dependencies;
|
|
13
|
-
private readonly
|
|
13
|
+
private readonly pendingCacheRuntime;
|
|
14
14
|
constructor(dependencies?: PreviewSourceServiceDependencies);
|
|
15
15
|
resolve(entry: ActiveClipPlaybackInfo, options: {
|
|
16
16
|
sourceGen: number;
|
|
@@ -18,7 +18,6 @@ export declare class PreviewSourceService {
|
|
|
18
18
|
reuse?: ResolvedSlotSource | null;
|
|
19
19
|
}): Promise<ResolvedSlotSource | null> | ResolvedSlotSource | null;
|
|
20
20
|
getReusableSource(boundStableKey: string | null, stableSourceUrl: string | null, desiredSource: string | null, objectUrl: string | null, entry: ActiveClipPlaybackInfo): ResolvedSlotSource | null;
|
|
21
|
-
revokeObjectUrl(objectUrl: string | null | undefined): void;
|
|
22
21
|
private resolvePlayable;
|
|
23
22
|
private normalizeCachedResult;
|
|
24
23
|
private emit;
|
|
@@ -12,7 +12,7 @@ export interface PreviewSyncCoordinatorOptions {
|
|
|
12
12
|
onAsyncWorkStarted: () => void;
|
|
13
13
|
onAsyncWorkFinished: () => void;
|
|
14
14
|
onStateChange: () => void;
|
|
15
|
-
releaseObjectUrl: (url: string | null) => void;
|
|
15
|
+
releaseObjectUrl: (url: string | null, holderId: string | null) => void;
|
|
16
16
|
rememberObjectUrl: (slot: PreviewPlaybackSlot, url: string | null) => void;
|
|
17
17
|
configureAudio: (slot: PreviewPlaybackSlot, entry: ActiveClipPlaybackInfo) => void;
|
|
18
18
|
syncClockAlignment: (slot: PreviewPlaybackSlot, target: PreviewSlotTarget, clipChanged: boolean) => void;
|
|
@@ -19,6 +19,7 @@ export declare class PreviewTextLayer {
|
|
|
19
19
|
private textPreviewFont;
|
|
20
20
|
private readonly compositor;
|
|
21
21
|
private readonly callbacks;
|
|
22
|
+
private autoRemeasureScheduled;
|
|
22
23
|
constructor(compositor: PreviewDomCompositor, callbacks: PreviewTextLayer['callbacks']);
|
|
23
24
|
mount(frameElement: HTMLDivElement): HTMLDivElement;
|
|
24
25
|
destroy(): void;
|
|
@@ -36,6 +37,12 @@ export declare class PreviewTextLayer {
|
|
|
36
37
|
private reapplyAllContent;
|
|
37
38
|
private applyBoxLayout;
|
|
38
39
|
private applyContent;
|
|
40
|
+
private usesManualTextLayout;
|
|
41
|
+
private emitResolvedLayout;
|
|
42
|
+
private finalizeTextBoxLayout;
|
|
43
|
+
private applyManualTextBoxLayout;
|
|
44
|
+
private applyAutoTextBoxLayout;
|
|
45
|
+
private scheduleAutoRemeasure;
|
|
39
46
|
private getFontFamily;
|
|
40
47
|
private ensureFontReady;
|
|
41
48
|
private resetFontState;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Clip, TextClipResolvedLayout, TextPreviewFontConfig } from '../models/types';
|
|
2
|
+
export declare function measureTextClipResolvedLayoutForExport(clip: Pick<Clip, 'textContent' | 'textStyle' | 'visualTransform' | 'name'>, composition: {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
}, textPreviewFont?: TextPreviewFontConfig | null): TextClipResolvedLayout | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClipVisualTransform, TextClipStyle } from '../models/types';
|
|
1
|
+
import type { ClipVisualTransform, TextClipLayoutMode, TextClipResolvedLayout, TextClipStyle } from '../models/types';
|
|
2
2
|
import { type PreviewFrameSize, type PreviewRect } from '../controllers/previewTransformMath';
|
|
3
3
|
/** 文本 visualTransform 使用框中心锚点。 */
|
|
4
4
|
export declare const TEXT_CLIP_ANCHOR_VERSION_CENTER = 1;
|
|
@@ -33,8 +33,13 @@ export declare function resolveTextEntryMaxWidthPx(frameWidth: number, baselineS
|
|
|
33
33
|
export declare function estimateTextLayoutHeightBaseline(fontSize: number, contentText: string, layoutWidthBaseline: number, paddingX: number): number;
|
|
34
34
|
export declare function resolveDefaultTextCenterTransform(frameSize: PreviewFrameSize, layoutHeightBaseline: number, baselineScale: number): ClipVisualTransform;
|
|
35
35
|
export declare function resolveDefaultTextCenterTransformForBaselineFrame(baselineFrameHeight: number, layoutHeightBaseline?: number): ClipVisualTransform;
|
|
36
|
+
export declare function usesLegacyBottomAnchorY(textStyle: TextClipStyle, transformY: number): boolean;
|
|
37
|
+
export declare function resolveTextBoxCenterY(frameSize: PreviewFrameSize, transform: ClipVisualTransform, textStyle: TextClipStyle, displayHeightPx: number): number;
|
|
36
38
|
export declare function migrateBottomAnchorTransformToCenter(transform: ClipVisualTransform, frameSize: PreviewFrameSize, displayHeightPx: number): ClipVisualTransform;
|
|
37
39
|
export declare function resolveTextVisualTransformForPreview(transform: Partial<ClipVisualTransform> | null | undefined, textStyle: TextClipStyle, frameSize: PreviewFrameSize, displayHeightPx: number): ClipVisualTransform;
|
|
40
|
+
/** clip 已持久化 layoutHeight 表示用户手动调整过文本框,预览应固定高度并截断溢出。 */
|
|
41
|
+
export declare function hasManualTextLayoutSize(textStyle: TextClipStyle): boolean;
|
|
42
|
+
export declare function resolveTextClipLayoutMode(textStyle?: Partial<TextClipStyle> | null): TextClipLayoutMode;
|
|
38
43
|
export declare function resolveTextLayoutDimensions(input: ComputeTextPreviewBoxInput): {
|
|
39
44
|
layoutWidth: number;
|
|
40
45
|
layoutHeight: number;
|
|
@@ -53,3 +58,22 @@ export declare function buildTextPreviewBoxForEntry(entry: {
|
|
|
53
58
|
visualTransform?: Partial<ClipVisualTransform> | null;
|
|
54
59
|
};
|
|
55
60
|
}, frameSize: PreviewFrameSize, baselineScale: number, styleOverride?: TextLayoutStyleOverride | null): TextPreviewBoxLayout;
|
|
61
|
+
export interface BuildTextClipResolvedLayoutInput {
|
|
62
|
+
frameSize: PreviewFrameSize;
|
|
63
|
+
composition: {
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
};
|
|
67
|
+
lastLayout: TextPreviewBoxLayout;
|
|
68
|
+
layoutMode: TextClipLayoutMode;
|
|
69
|
+
}
|
|
70
|
+
export declare function buildAutoMeasuredTextPreviewBoxLayout(input: {
|
|
71
|
+
layout: TextPreviewBoxLayout;
|
|
72
|
+
frameSize: PreviewFrameSize;
|
|
73
|
+
baselineScale: number;
|
|
74
|
+
visualTransform: ClipVisualTransform;
|
|
75
|
+
textStyle: TextClipStyle;
|
|
76
|
+
measuredHeightPx: number;
|
|
77
|
+
}): TextPreviewBoxLayout;
|
|
78
|
+
export declare function buildTextClipResolvedLayout(input: BuildTextClipResolvedLayoutInput): TextClipResolvedLayout;
|
|
79
|
+
export declare function areTextClipResolvedLayoutsEqual(left?: TextClipResolvedLayout | null, right?: TextClipResolvedLayout | null, epsilon?: number): boolean;
|
|
@@ -59,6 +59,7 @@ export interface PreviewEngineCallbacks {
|
|
|
59
59
|
layoutWidth: number;
|
|
60
60
|
layoutHeight: number;
|
|
61
61
|
}) => void;
|
|
62
|
+
onTextLayoutResolved?: (clipId: string, layout: import('../models/types').TextClipResolvedLayout) => void;
|
|
62
63
|
onPendingPreviewRetry?: () => void;
|
|
63
64
|
onPauseIfPlaying?: () => void;
|
|
64
65
|
}
|
|
@@ -19,11 +19,18 @@ export declare class ResourceCacheManager {
|
|
|
19
19
|
private readonly cacheKeyBuilder;
|
|
20
20
|
private readonly onEvent?;
|
|
21
21
|
private readonly objectUrls;
|
|
22
|
+
private readonly objectUrlByCacheKey;
|
|
23
|
+
private readonly cacheKeyByObjectUrl;
|
|
24
|
+
private readonly objectUrlHolders;
|
|
22
25
|
private readonly inflightDownloads;
|
|
23
26
|
constructor(dependencies?: ResourceCacheManagerDependencies);
|
|
24
27
|
resolve(input: ResolveResourceInput): Promise<ResolvedCachedResource>;
|
|
25
28
|
resolvePlayableUrl(input: ResolveResourceInput): Promise<ResolvedCachedResource>;
|
|
29
|
+
retainObjectUrl(url: string, holderId: string): void;
|
|
30
|
+
releaseObjectUrl(url: string, holderId: string): void;
|
|
31
|
+
/** @deprecated Prefer releaseObjectUrl with a clip holder id. */
|
|
26
32
|
revokeObjectUrl(url: string): void;
|
|
33
|
+
forceRevokeObjectUrl(url: string): void;
|
|
27
34
|
cleanupExpired(): Promise<void>;
|
|
28
35
|
clear(): Promise<void>;
|
|
29
36
|
getStats(): Promise<ResourceCacheStats>;
|
|
@@ -34,6 +41,9 @@ export declare class ResourceCacheManager {
|
|
|
34
41
|
private downloadAndStore;
|
|
35
42
|
private evictForWrite;
|
|
36
43
|
private deleteEntry;
|
|
44
|
+
private registerObjectUrl;
|
|
45
|
+
private revokeTrackedObjectUrl;
|
|
37
46
|
private blobResult;
|
|
47
|
+
private toResolvedBlob;
|
|
38
48
|
private emitEvent;
|
|
39
49
|
}
|