@taole/giftstage 0.1.36 → 0.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.
Files changed (51) hide show
  1. package/README.md +770 -694
  2. package/dist/core/audio-manager.d.ts +10 -1
  3. package/dist/core/gift-stage.d.ts +63 -1
  4. package/dist/core/index.d.ts +4 -4
  5. package/dist/core/post-animator.d.ts +1 -1
  6. package/dist/core/render-manager.d.ts +55 -6
  7. package/dist/{gift-stage.cjs.js → gift-stage.cjs} +1401 -287
  8. package/dist/gift-stage.es.js +11500 -6094
  9. package/dist/gpu/backend-operation-result.d.ts +6 -0
  10. package/dist/gpu/detect.d.ts +1 -1
  11. package/dist/gpu/index.d.ts +3 -3
  12. package/dist/gpu/webgl1-backend.d.ts +8 -4
  13. package/dist/gpu/webgl2-backend.d.ts +154 -4
  14. package/dist/gpu/webgpu-backend.d.ts +130 -4
  15. package/dist/index.d.ts +36 -27
  16. package/dist/parsers/atlas-builder.d.ts +1 -1
  17. package/dist/parsers/index.d.ts +7 -7
  18. package/dist/parsers/svga-parser-worker-client.d.ts +1 -1
  19. package/dist/parsers/svga-parser.d.ts +1 -1
  20. package/dist/parsers/svga-proto-js.d.ts +1 -1
  21. package/dist/parsers/svga-sprite-table-binary.d.ts +1 -1
  22. package/dist/parsers/svga-sprite-table.d.ts +1 -1
  23. package/dist/parsers/svga-worker-payload-binary.d.ts +3 -3
  24. package/dist/parsers/vap-config-parser.d.ts +1 -1
  25. package/dist/plugin/motion-track.d.ts +19 -0
  26. package/dist/plugin/playback-scope.d.ts +42 -0
  27. package/dist/plugin/types.d.ts +183 -0
  28. package/dist/public.d.ts +2 -0
  29. package/dist/renderers/alpha-video-renderer.d.ts +1 -1
  30. package/dist/renderers/image-renderer.d.ts +1 -1
  31. package/dist/renderers/index.d.ts +4 -4
  32. package/dist/renderers/particle-batch-renderer.d.ts +19 -0
  33. package/dist/renderers/svga-batch-renderer.d.ts +140 -7
  34. package/dist/renderers/vap-renderer.d.ts +1 -1
  35. package/dist/shaders/index.d.ts +20 -0
  36. package/dist/types/index.d.ts +357 -6
  37. package/dist/utils/clip-mesh.d.ts +13 -0
  38. package/dist/utils/gift-object-fit.d.ts +2 -2
  39. package/dist/utils/gift-transform.d.ts +3 -1
  40. package/dist/utils/resource-cache.d.ts +1 -1
  41. package/dist/utils/slot-content.d.ts +1 -1
  42. package/dist/utils/svga-binary-cache.d.ts +2 -2
  43. package/dist/utils/svga-frame-timeline.d.ts +95 -0
  44. package/dist/utils/svga-hybrid-command-table.d.ts +12 -0
  45. package/dist/utils/svga-slot-state-schema.d.ts +28 -0
  46. package/dist/utils/vap-mix-composer.d.ts +1 -1
  47. package/dist/utils/wc-atlas-upload-size.d.ts +1 -1
  48. package/dist/wasm/wasm-bridge.d.ts +1 -1
  49. package/dist/workers/svga-atlas-worker-client.d.ts +1 -1
  50. package/dist/workers/svga-clip-worker-client.d.ts +1 -1
  51. package/package.json +81 -76
@@ -1,9 +1,10 @@
1
- import type { GiftSlot } from '../types';
1
+ import type { GiftSlot } from '../types/index.js';
2
2
  export declare class AudioManager {
3
3
  private ctx;
4
4
  private decodedCache;
5
5
  private activeSources;
6
6
  private globalMute;
7
+ private suspended;
7
8
  private gainNode;
8
9
  private ensureContext;
9
10
  decodeAudio(key: string, data: ArrayBuffer): Promise<void>;
@@ -19,8 +20,16 @@ export declare class AudioManager {
19
20
  * sibling audio that already played this frame if called again with an unchanged frame number.
20
21
  */
21
22
  tickFrameForKey(slot: GiftSlot, currentFrame: number, audioKey: string): void;
23
+ /**
24
+ * Reconciles SVGA audio with a PlaybackScope-owned absolute frame clock. Unlike the ordinary
25
+ * frame-edge trigger, this also restores an audio clip at the correct offset after a seek,
26
+ * resume or skipped start frame, and replaces sources when the absolute loop changes.
27
+ */
28
+ syncPlaybackScopeFrame(slot: GiftSlot, absoluteFrame: number, discontinuous?: boolean): void;
22
29
  private startAudio;
30
+ private stopSourceAt;
23
31
  stopAllForGift(giftId: string): void;
24
32
  setMute(mute: boolean): void;
33
+ setSuspended(suspended: boolean): void;
25
34
  destroy(): void;
26
35
  }
@@ -1,4 +1,5 @@
1
- import type { GiftStageOptions, AddGiftOptions, GiftHandle, BackendType } from '../types';
1
+ import type { GiftStageOptions, AddGiftOptions, GiftHandle, BackendType, GiftStageRuntimeDiagnostics } from '../types/index.js';
2
+ import { type GiftAssetLease, type GiftStageCapabilities, type GiftStagePlugin, type MountedGiftStagePlugin, type PlaybackScope } from '../plugin/types.js';
2
3
  export declare function resolveResourcePipelineConcurrency(explicit: number | undefined, hardwareConcurrency?: number | undefined): number;
3
4
  export declare class GiftStage {
4
5
  private static readonly SVGA_ATLAS_MAX_SIZE;
@@ -40,6 +41,25 @@ export declare class GiftStage {
40
41
  private nextRenderOrder;
41
42
  private nextSharedWebCodecsPlaybackId;
42
43
  private nextSharedWebCodecsSurfaceId;
44
+ private readonly playbackScopes;
45
+ private readonly mountedPlugins;
46
+ /** Last path reported per slot, so asynchronous table promotion emits exactly once. */
47
+ private svgaReportedPathKeys;
48
+ /** One asynchronous table preparation per shared parsed entity. */
49
+ private svgaFrameTablePromises;
50
+ private svgaFrameTableResidentBytes;
51
+ private svgaFrameTableReservedBytes;
52
+ private releasedSVGATimelineEntities;
53
+ private activeSVGAGpuFrameTableBytes;
54
+ private reservedSVGAGpuFrameTableBytes;
55
+ private svgaBackendLost;
56
+ private svgaPreparingEntities;
57
+ private activeSVGATimelineEntities;
58
+ private svgaEntitySources;
59
+ private runtimeFallbackCount;
60
+ private runtimeObserverErrorCount;
61
+ private lastRuntimeDiagnostic;
62
+ private playbackPaused;
43
63
  private readonly onWindowLayout;
44
64
  private readonly onVisibilityChange;
45
65
  constructor(options: GiftStageOptions);
@@ -59,6 +79,8 @@ export declare class GiftStage {
59
79
  private resolveAnimationStepTarget;
60
80
  private runGiftAnimationStep;
61
81
  private createGiftAnimationChain;
82
+ private getGiftRenderInfo;
83
+ private reportSVGARenderPath;
62
84
  addGift(options: AddGiftOptions): Promise<GiftHandle>;
63
85
  private loadSVGA;
64
86
  private acquireSharedSVGAEntity;
@@ -66,6 +88,34 @@ export declare class GiftStage {
66
88
  private buildSharedSVGAEntity;
67
89
  private releaseSharedSVGAEntity;
68
90
  private createCachedSVGAAtlasTextures;
91
+ private svgaGpuFrameTableBudgetBytes;
92
+ /**
93
+ * A few integration tests intentionally construct a lightweight stage via
94
+ * `Object.create(GiftStage.prototype)`. Keep the resource bookkeeping lazy
95
+ * so those focused harnesses exercise SVGA loading without having to mirror
96
+ * every constructor-only field.
97
+ */
98
+ private ensureSVGATimelineBookkeeping;
99
+ private emitRuntimeDiagnostic;
100
+ private recordObserverError;
101
+ private runtimeErrorMessage;
102
+ private handleSVGABackendLoss;
103
+ private reserveSVGAFrameTableBytes;
104
+ private rollbackSVGAFrameTableReservation;
105
+ private commitSVGAFrameTableReservation;
106
+ private buildSVGATimelineDrawPlan;
107
+ private createSVGATimelineState;
108
+ /**
109
+ * Starts one resource-level immutable table upload. The first addGift frame
110
+ * remains on the reference path; preload awaits this same promise so later
111
+ * playbacks can start directly on the selected GPU path.
112
+ */
113
+ private ensureSVGAFrameTable;
114
+ private refreshSVGATimelineSlots;
115
+ private assignSVGATimelineStateToSlot;
116
+ private releaseSVGAFrameTable;
117
+ private fallbackSVGAFrameTable;
118
+ private getSVGAEntityDiagnosticContext;
69
119
  private deleteSVGAAtlasTextures;
70
120
  private deleteSVGAAtlasResultTextures;
71
121
  private finishLoadSVGA;
@@ -88,6 +138,11 @@ export declare class GiftStage {
88
138
  * slot's abort signal: shared entities can outlive the slot that first requested the work.
89
139
  */
90
140
  private ensureSVGAFullClipPrewarm;
141
+ /**
142
+ * Completes the immutable CPU draw schedule required by Hybrid before the
143
+ * resource is atomically promoted from the reference renderer.
144
+ */
145
+ private ensureSVGAHybridSchedulePrepared;
91
146
  private queueSVGAPersistentCacheWrite;
92
147
  private svgaAtlasMaxSize;
93
148
  private buildSVGAAtlasIfNeeded;
@@ -117,6 +172,8 @@ export declare class GiftStage {
117
172
  */
118
173
  private bindVideoLoopOnEnded;
119
174
  private clearHtmlVideoPlaybackWatchdog;
175
+ private clearAllHtmlVideoPlaybackWatchdogs;
176
+ private rearmHtmlVideoPlaybackWatchdogs;
120
177
  private completeHtmlVideoPlayback;
121
178
  private armHtmlVideoPlaybackWatchdog;
122
179
  private createVideo;
@@ -138,12 +195,17 @@ export declare class GiftStage {
138
195
  */
139
196
  private waitForFirstVideoFrame;
140
197
  private waitVideoReady;
198
+ get capabilities(): GiftStageCapabilities;
199
+ preload(type: 'svga' | 'image', source: string | ArrayBuffer, signal?: AbortSignal): Promise<GiftAssetLease>;
200
+ createPlaybackScope(id?: string): PlaybackScope;
201
+ mount<TApi>(plugin: GiftStagePlugin<TApi>): Promise<MountedGiftStagePlugin<TApi>>;
141
202
  removeGift(id: string): void;
142
203
  removeAll(): void;
143
204
  pause(): void;
144
205
  resume(): void;
145
206
  get activeCount(): number;
146
207
  get backendType(): BackendType;
208
+ getDiagnostics(): GiftStageRuntimeDiagnostics;
147
209
  destroy(): void;
148
210
  private markGiftPlaybackComplete;
149
211
  private resolveGiftPlaybackWaiters;
@@ -1,4 +1,4 @@
1
- export { GiftStage } from './gift-stage';
2
- export { RenderManager } from './render-manager';
3
- export { AudioManager } from './audio-manager';
4
- export { PostAnimator } from './post-animator';
1
+ export { GiftStage } from './gift-stage.js';
2
+ export { RenderManager } from './render-manager.js';
3
+ export { AudioManager } from './audio-manager.js';
4
+ export { PostAnimator } from './post-animator.js';
@@ -1,4 +1,4 @@
1
- import type { GiftSlot } from '../types';
1
+ import type { GiftSlot } from '../types/index.js';
2
2
  export interface PostAnimationTarget {
3
3
  targetX: number;
4
4
  targetY: number;
@@ -1,14 +1,26 @@
1
- import type { GPUBackend, GiftSlot, GiftHandle, GPUTextureHandle } from '../types';
2
- import { type SVGAClipMeshMap } from '../renderers/svga-batch-renderer';
3
- import { PostAnimator } from './post-animator';
4
- import { AudioManager } from './audio-manager';
5
- import { type WebCodecsAtlasRect } from './webcodecs-video-atlas';
1
+ import type { GPUBackend, GiftSlot, GiftHandle, GPUTextureHandle, VideoEntity } from '../types/index.js';
2
+ import { type SVGAClipMeshMap } from '../renderers/svga-batch-renderer.js';
3
+ import { PostAnimator } from './post-animator.js';
4
+ import { AudioManager } from './audio-manager.js';
5
+ import { type WebCodecsAtlasRect } from './webcodecs-video-atlas.js';
6
+ import type { PlaybackFrameController } from '../plugin/types.js';
7
+ import type { ParticleBatchDescriptor, ParticleBatchHandle } from '../plugin/types.js';
8
+ export interface RenderManagerRuntimeDiagnostics {
9
+ frameAbortCount: number;
10
+ replayFailureCount: number;
11
+ retryFrameCount: number;
12
+ }
13
+ export interface RenderManagerRuntimeDiagnosticEvent {
14
+ type: 'svga-frame-abort' | 'svga-frame-replay-failed' | 'svga-frame-retry' | 'backend-operation-rejected' | 'backend-quarantined' | 'stencil-transaction-failure' | 'clip-protocol-error' | 'clip-mesh-invalid' | 'atlas-command-invalid';
15
+ message?: string;
16
+ }
6
17
  export declare class RenderManager {
7
18
  private backend;
8
19
  private svgaBatch;
9
20
  private vapRenderer;
10
21
  private alphaVideoRenderer;
11
22
  private imageRenderer;
23
+ private particleBatchRenderer;
12
24
  readonly postAnimator: PostAnimator;
13
25
  readonly audioManager: AudioManager;
14
26
  private slots;
@@ -16,10 +28,19 @@ export declare class RenderManager {
16
28
  private rafId;
17
29
  private lastTime;
18
30
  private running;
31
+ private destroyed;
19
32
  private globallyPaused;
20
33
  /** Set while the document is hidden (`GiftStage.setHidden`); suppresses rAF independent of `globallyPaused`. */
21
34
  private suspendedForHidden;
22
35
  private forceNextDraw;
36
+ private pendingAtomicFrameRetry;
37
+ private atomicRetryUsedForGenericFailure;
38
+ private readonly atomicRetryProgressEntities;
39
+ private runtimeFrameAbortCount;
40
+ private runtimeReplayFailureCount;
41
+ private runtimeRetryFrameCount;
42
+ private backendQuarantined;
43
+ private readonly onRuntimeDiagnostic?;
23
44
  private readonly onAnimationFrame;
24
45
  private readonly onHtmlVideoFrame;
25
46
  private readonly finishedSlotIdsScratch;
@@ -35,7 +56,11 @@ export declare class RenderManager {
35
56
  private readonly wcDbgTickOnce;
36
57
  private readonly advancedSharedWebCodecsScratch;
37
58
  private readonly activeSharedWebCodecsScratch;
38
- constructor(backend: GPUBackend);
59
+ private readonly frameControllers;
60
+ constructor(backend: GPUBackend, onSVGAHybridValidationFailure?: (entity: NonNullable<GiftSlot['videoEntity']>) => void, onRuntimeDiagnostic?: (event: RenderManagerRuntimeDiagnosticEvent) => void);
61
+ getRuntimeDiagnosticsSnapshot(): RenderManagerRuntimeDiagnostics;
62
+ /** Runtime diagnostics are observational and must never change frame transaction control flow. */
63
+ private emitRuntimeDiagnostic;
39
64
  addSlot(slot: GiftSlot, handle: GiftHandle): void;
40
65
  getHandle(id: string): GiftHandle | undefined;
41
66
  releaseSlotResources(slot: GiftSlot): void;
@@ -43,6 +68,10 @@ export declare class RenderManager {
43
68
  getSlot(id: string): GiftSlot | undefined;
44
69
  get activeCount(): number;
45
70
  getSlotIds(): string[];
71
+ /** Number of active, table-compatible SVGA instances sharing one parsed entity. */
72
+ countCompatibleSVGAInstances(entity: VideoEntity): number;
73
+ registerFrameController(controller: PlaybackFrameController): () => void;
74
+ createParticleBatch(descriptor: ParticleBatchDescriptor): ParticleBatchHandle;
46
75
  /**
47
76
  * Reserve a sub-rectangle in the shared WebCodecs atlas (when `webCodecsVideoAtlas` is configured).
48
77
  * Returns null if disabled, full, or size mismatch while the atlas is still in use.
@@ -88,6 +117,13 @@ export declare class RenderManager {
88
117
  * group has gone inactive, so one paused copy never stalls playback for the rest.
89
118
  */
90
119
  syncVideoPlaybackForSlot(slot: GiftSlot): void;
120
+ private syncAudioSuspension;
121
+ /**
122
+ * Applies the single absolute media clock owned by PlaybackScope. SVGA frame state, public
123
+ * frame callbacks and embedded audio are deliberately updated together here so the scope
124
+ * cannot bypass media side effects while seeking the visual frame.
125
+ */
126
+ applyPlaybackScopeMediaTime(id: string, timeMs: number, emitInitialFrame?: boolean, discontinuous?: boolean): void;
91
127
  prewarmSVGAClipMeshes(entity: NonNullable<GiftSlot['videoEntity']>, options?: {
92
128
  frameBudgetMs?: number;
93
129
  workerTimeSliceMs?: number;
@@ -102,9 +138,21 @@ export declare class RenderManager {
102
138
  checkActive?: () => void;
103
139
  signal?: AbortSignal;
104
140
  }): Promise<number>;
141
+ prewarmSVGAShapeMeshes(entity: NonNullable<GiftSlot['videoEntity']>): number;
142
+ retainSVGAHybridMeshes(entity: NonNullable<GiftSlot['videoEntity']>): void;
143
+ releaseSVGAHybridMeshes(entity: NonNullable<GiftSlot['videoEntity']>): void;
105
144
  hydrateSVGAClipMeshes(meshes: SVGAClipMeshMap | null | undefined): void;
106
145
  snapshotSVGAClipMeshes(entity: NonNullable<GiftSlot['videoEntity']>): SVGAClipMeshMap;
107
146
  private renderLoop;
147
+ private drawPreparedFrameWithReplay;
148
+ private abortPreparedFrame;
149
+ private recordReplayFailure;
150
+ private shouldScheduleAtomicRetry;
151
+ private resetAtomicRetryCycle;
152
+ private runtimeErrorMessage;
153
+ private scheduleNextFrame;
154
+ private drawPreparedFrame;
155
+ private assertBackendOperation;
108
156
  /**
109
157
  * Fixed-step frame advancement matching Unity SvgaLitePlayer.Update()
110
158
  */
@@ -134,6 +182,7 @@ export declare class RenderManager {
134
182
  private getSVGASlotTextureKey;
135
183
  private drawLayer;
136
184
  private needsContinuousFrame;
185
+ private hasActiveFrameController;
137
186
  private insertSortedSlot;
138
187
  private static compareSlots;
139
188
  private drawSlotRun;