import * as THREE from 'three/webgpu'; import { AFDecoder } from './AFDecoder.cjs'; import { AFVideoGPUCache } from './AFVideoGPUCache.cjs'; import type { AFDecoderConfigAttempt, AFDecoderSource } from './AFDecoder.cjs'; import type { AFVideoGPUCacheFacts, AFVideoGPUCacheOptions, AFVideoUploadFacts } from './AFVideoGPUCache.cjs'; import type { AFManifest } from './AFContainer.cjs'; import type { MediaDecoderLease } from './MediaDecoderCoordinator.cjs'; import type { TSLFloatNode, TSLTextureNode, TSLUniformNode, TSLVec2Node, TSLVec3Node, TSLVec4Node } from '../types/tsl.cjs'; import type { ColorSpace, MagnificationTextureFilter, MinificationTextureFilter } from 'three/webgpu'; /** Input accepted by {@link AFVideo}. */ export type AFVideoSource = AFDecoderSource; /** Internal logical members reserved for one AFVideo color/embedded-alpha pair. */ export interface AFVideoMediaDecoderLeases { readonly color: MediaDecoderLease; readonly alpha?: MediaDecoderLease; } /** Retained decoder diagnostics that do not keep decoder or encoded-source objects alive. */ export interface AFVideoDecoderConfigAttempts { readonly color: readonly AFDecoderConfigAttempt[]; readonly alpha: readonly AFDecoderConfigAttempt[]; } /** @internal Immutable request-to-applied timing facts for one decoder channel. */ export interface AFVideoTimingChannelFacts { readonly decodeUploadMs: number | null; readonly lastDecodeUploadMs: number | null; readonly samples: number; readonly lastFrame: number | null; readonly lastRequestedAtMs: number | null; readonly lastArrivedAtMs: number | null; } /** @internal Local timing facts consumed by Baked Motion's adaptive scrub scheduler. */ export interface AFVideoTimingFacts { readonly color: AFVideoTimingChannelFacts; readonly alpha: AFVideoTimingChannelFacts; readonly weightRampPending: boolean; } /** @internal Aggregated codec-activity counters for one clip's playback decoders. */ export interface AFVideoPlaybackDecoderFacts { readonly resets: number; readonly forwardExtensions: number; readonly decodedFrames: number; readonly droppedLateFrames: number; } /** @internal Forward-playback presentation facts consumed by owner diagnostics. */ export interface AFVideoPlaybackFacts { /** Last frame id whose pixels were published to a presentation slot. */ readonly presentedFrame: number | null; /** Requested nearest frame minus the presented frame — the visible decode lag. */ readonly presentationLagFrames: number | null; readonly decoder: AFVideoPlaybackDecoderFacts; } /** @internal Owned decoded-frame lifecycle facts consumed by owner diagnostics. */ export interface AFVideoFrameFacts { readonly current: number; readonly highWater: number; } /** Symbol-keyed friend channel used by internal grouped AFVideo admission. */ export declare const AF_VIDEO_MEDIA_DECODER_LEASES: unique symbol; /** Symbol-keyed friend channel used by BakedMotion's decoded-view GPU cache. */ export declare const AF_VIDEO_GPU_CACHE: unique symbol; /** Symbol-keyed friend channel used to retire uploaded frames behind the renderer's GPU fence. */ export declare const AF_VIDEO_FRAME_RETIREMENT_QUEUE: unique symbol; /** Symbol-keyed friend channel used to bound decoded frames to current + incoming + retiring. */ export declare const AF_VIDEO_BOUNDED_FRAME_LIFETIME: unique symbol; /** Symbol-keyed friend channel that leaves requested grid weights absolute rather than renormalized. */ export declare const AF_VIDEO_PRESERVE_FRAME_WEIGHTS: unique symbol; /** Construction options for {@link AFVideo}. */ export interface AFVideoOptions { colorSpace?: ColorSpace; flipY?: boolean; magFilter?: MagnificationTextureFilter; minFilter?: MinificationTextureFilter; hardwareAcceleration?: HardwareAcceleration; decoderColorSpace?: VideoColorSpaceInit | null; dataChannel?: boolean; /** Copy decoded RGBA frames into DataTexture slots instead of VideoFrameTexture uploads. */ cpuUpload?: boolean; /** * Streaming playback profile. Decoders prefer throughput codec configs (see * {@link AFDecoder} `streaming`) and discontinuous seeks snap to the nearest frame instead * of crossfading unrelated frames. Adjacent updates preserve fractional interpolation. * Leave off for scrub-first consumers. */ streaming?: boolean; slots?: number; /** Wall-clock milliseconds allowed for each decoder's first requested keyframe output. */ firstDecodeTimeout?: number; /** Indexed primary stream selected when `source` implements `AFEncodedSource`. */ encodedStream?: 'color' | 'depth'; /** @internal Exact color/embedded-alpha members supplied by a grouped coordinator transaction. */ [AF_VIDEO_MEDIA_DECODER_LEASES]?: AFVideoMediaDecoderLeases; /** @internal Borrowed renderer and bounded layer count for BakedMotion's decoded-view ring. */ [AF_VIDEO_GPU_CACHE]?: AFVideoGPUCacheOptions; /** @internal Borrowed WebGPU submission queue used to retire uploaded VideoFrames safely. */ [AF_VIDEO_FRAME_RETIREMENT_QUEUE]?: unknown; /** @internal Defer texture bootstrap and decoder requests while one GPU retirement fence is pending. */ [AF_VIDEO_BOUNDED_FRAME_LIFETIME]?: boolean; /** @internal Keep requested grid weights absolute so the caller sees unadmitted corner mass. */ [AF_VIDEO_PRESERVE_FRAME_WEIGHTS]?: boolean | AFVideoPreserveFrameWeightsOptions; } /** Decoder-admission options accepted when a suspended clip is resumed. */ export interface AFVideoResumeOptions { /** @internal Exact color/embedded-alpha members supplied by a grouped coordinator transaction. */ [AF_VIDEO_MEDIA_DECODER_LEASES]?: AFVideoMediaDecoderLeases; } /** Controls whether a bounded frame-set request waits for every texture slot. */ export interface AFVideoSetFramesOptions { wait?: boolean; } /** Controls one fractional-frame request. */ export interface AFVideoSetFrameOptions { /** Drain a throughput decoder after submitting this bounded request. */ flushTail?: boolean; } /** Public interpolated RGBA/sample node returned by AFVideo. */ export type AFVideoNode = TSLVec4Node; /** A completed AFVideo request, or `null` when a newer request superseded it. */ export type AFVideoFrameResult = AFVideo | null; /** Results from a lock-stepped {@link syncFrame} request. */ export type AFVideoSyncResult = AFVideoFrameResult[]; /** Promise with its resolver retained for a lifecycle milestone. */ export interface AFVideoDeferred extends Promise { resolve(value: TValue | PromiseLike): void; reject(reason?: unknown): void; } type AFVideoTextureSlot = THREE.VideoFrameTexture | THREE.DataTexture; interface AFVideoFrameSetWaiter { frames: Set; resolve(value: AFVideoFrameResult): void; reject(reason?: unknown): void; } interface AFVideoQueuedRequest { held: number[]; loaded: number[]; needed: readonly number[]; flushTail?: boolean; } interface AFVideoPreserveFrameWeightsOptions { readonly retirementMs?: number; readonly deferActivation?: boolean; } interface AFVideoDeferredFrame { readonly frame: VideoFrame; readonly id: number; readonly session: AFVideoDecoderGeneration; readonly decoder: AFDecoder; } interface AFVideoSubmissionQueue { onSubmittedWorkDone(): Promise; } interface AFVideoDecoderSettings { hardwareAcceleration: HardwareAcceleration; colorSpace: VideoColorSpaceInit | null; firstDecodeTimeout: number; encodedStream: 'color' | 'depth'; streaming: boolean; } interface AFVideoDecoderGeneration { readonly id: number; readonly grouped: boolean; readonly retainManifestOnFailure: boolean; color: AFDecoder | null; parallelColor: AFDecoder | null; alpha: AFDecoder | null; pendingColorLease: MediaDecoderLease | null; pendingParallelColorLease: MediaDecoderLease | null; pendingAlphaLease: MediaDecoderLease | null; } interface MutableAFVideoTimingChannelFacts { decodeUploadMs: number | null; lastDecodeUploadMs: number | null; samples: number; lastFrame: number | null; lastRequestedAtMs: number | null; lastArrivedAtMs: number | null; } interface MutableAFVideoUploadChannelFacts { gpuLumaUploads: number; cpuCopyToCalls: number; cpuCopyToTotalMs: number; cpuCopyToMaxMs: number; } /** Exact short-lived decoder attempt retained only for Baked Motion's isolated capacity probe. */ interface AFVideoExactDecoderAttempt { readonly config: Readonly; readonly advisorySupported: boolean; readonly step: AFDecoderConfigAttempt['step']; readonly error?: unknown; } interface AFVideoExactDecoderAttempts { color: readonly AFVideoExactDecoderAttempt[]; alpha: readonly AFVideoExactDecoderAttempt[]; } /** * Decode an `.af` clip and expose it as an interpolated, GPU-resident TSL texture node. * * @class AFVideo * @short Scrubbable, interpolated `.af` video/data textures for WebGPU. * @category Video */ export declare class AFVideo { source: AFVideoSource; manifest: AFManifest | null; totalFrames: number; lastFrame: number | undefined; slotCount: number; hasAlpha: boolean; dataChannel: boolean; cpuUpload: boolean; flipY: boolean; decoder: AFDecoder | null; _parallelDecoder: AFDecoder | null; alphaDecoder: AFDecoder | null; blend: TSLUniformNode<'float', number>; weights: TSLUniformNode<'float', number>[]; firstFrame: AFVideoDeferred; ready: Promise; _held: number[]; _liveFrames: (VideoFrame | null)[]; _loaded: number[]; _alphaHeld: number[]; _alphaLiveFrames: (VideoFrame | null)[]; _alphaLoaded: number[]; _frameSetWaiters: AFVideoFrameSetWaiter[]; _frameSetWeights: Map; _queuedRequests: Map; _deferredPrimaryFrames: Map; _deferredAlphaFrames: Map; _dataStagingPool: Uint8Array[]; _colorPlanes: (Uint8Array | null)[]; _dataLumaPlanes: (Uint8Array | null)[]; _alphaLumaPlanes: (Uint8Array | null)[]; _appliedLo: number; _presentedFrame: number | null; _snapTargetFrame: number | null; _pendingBlend: { readonly value: number; } | null; _lastRequestedFrame: number | null; _droppedLateFrames: number; _firstColorFrameApplied: boolean; _firstAlphaFrameApplied: boolean; _slots: AFVideoTextureSlot[]; _alphaSlots: AFVideoTextureSlot[]; _texNodes: TSLTextureNode[]; _alphaTexNodes: TSLTextureNode[]; _gpuCache: AFVideoGPUCache | null; _submissionQueue: AFVideoSubmissionQueue | null; _boundedFrameLifetime: boolean; _retiredFrames: Set; _trackedFrames: WeakSet; _videoFrameCurrent: number; _videoFrameHighWater: number; _retirementFence: Promise | null; _colorNode: TSLVec4Node | null; _alphaNode: TSLFloatNode | null; _node: TSLVec4Node | null; _disposed: boolean; _suspended: boolean; _initialError: unknown | null; _decoderGeneration: number; _decoderSession: AFVideoDecoderGeneration | null; _resumePromise: Promise | null; _decoderSettings: Readonly; _retainedAttemptDecoders: WeakSet; _retainedDecoderConfigAttempts: Readonly; _requestStartedAt: Map>; _colorTiming: MutableAFVideoTimingChannelFacts; _alphaTiming: MutableAFVideoTimingChannelFacts; _colorUploadFacts: MutableAFVideoUploadChannelFacts; _alphaUploadFacts: MutableAFVideoUploadChannelFacts; _exactDecoderAttempts: AFVideoExactDecoderAttempts; _preserveFrameWeights: boolean; _preserveRetirementMs: number; _deferFrameWeightActivation: boolean; _deferredFrameWeightTarget: number[] | null; _weightRampGeneration: number; _weightRampStartedAtMs: number; _weightRampDurationMs: number; _weightRampFrom: number[]; _weightRampTarget: number[]; _weightRampTimer: ReturnType | null; _weightRampDeferred: AFVideoDeferred | null; /** * @param {string|ArrayBuffer|{manifest:object}} source - `.af` URL, an already-loaded ArrayBuffer, or a parsed AF container. * @param {object} [options={}] * @param {string} [options.colorSpace=THREE.SRGBColorSpace] - Texture colour space for decoded video slots. WebGPU video textures must use an sRGB transfer function; raw luma tracks should use `dataChannel:true` instead. * @param {boolean} [options.flipY=true] - Flip decoded frames vertically to match standard UVs. * @param {number} [options.magFilter=THREE.LinearFilter] * @param {number} [options.minFilter=THREE.LinearFilter] * @param {'prefer-hardware'|'prefer-software'|'no-preference'} [options.hardwareAcceleration='prefer-hardware'] * @param {VideoColorSpaceInit|null} [options.decoderColorSpace=null] - WebCodecs color-space override. Full-range data tracks need `{ primaries:'bt709', transfer:'bt709', matrix:'bt709', fullRange:true }`; this is separate from the texture `colorSpace` option. * @param {boolean} [options.dataChannel=false] - Copy the decoded luma plane into `RedFormat` data textures. Use this for depth/masks: WebGPU video textures require an sRGB transfer function and would otherwise color-transform data. * @param {boolean} [options.cpuUpload=false] - Copy decoded RGBA frames into `DataTexture` slots. This bounded fallback avoids video-texture uploads on software WebGPU adapters. * @param {boolean} [options.streaming=false] - Streaming playback profile: throughput-first decoder configs, busy-codec forward appends, and nearest-frame presentation for discontinuous seeks. Leave off for scrub-first consumers. * @param {number} [options.slots=2] - Number of bounded frame slots. The default pair supports fractional video; Baked Motion grids use four slots for their current bilinear corners. * @param {number} [options.firstDecodeTimeout=5000] - Wall-clock deadline for each decoder's first requested keyframe output. * @param {'color'|'depth'} [options.encodedStream='color'] - Primary stream name for an indexed encoded source. */ constructor(source: AFVideoSource, options?: AFVideoOptions); _startDecoderGeneration(source: AFVideoSource, mediaDecoderLeases: AFVideoMediaDecoderLeases | null, retainManifestOnFailure: boolean): Promise; _isDecoderGenerationCurrent(session: AFVideoDecoderGeneration): boolean; /** * Close active decoders and return their coordinator leases while retaining every displayed * texture, frame/pixel plane, manifest, and sizing field. Idempotent and synchronous. * * @return {void} */ suspend(): void; /** * Reconfigure decoders against the retained source without replacing or allocating texture * slots. A grouped owner may transfer an exact color/embedded-alpha lease set through the * symbol-keyed friend option; standalone resumes acquire individual leases normally. * * @param {object} [options={}] - Optional grouped decoder-admission payload. * @return {Promise} Resolves when the replacement decoder generation is ready. */ resume(options?: AFVideoResumeOptions): Promise; /** * @internal Attempt to add one independently admitted decoder for the primary all-intra * color stream. The caller must supply a member from the same atomic coordinator group as * the required decoders. Unsupported/inter-frame streams and capacity failures release that * optional member and leave the existing single-decoder path fully operational. */ _admitParallelPrimaryDecoder(lease: MediaDecoderLease): Promise; /** Immutable config-attempt history retained after failed initialization or disposal. */ get decoderConfigAttempts(): Readonly; /** @internal Immutable local request-to-applied timing snapshot. */ get timingFacts(): Readonly; /** @internal Immutable forward-playback presentation and codec-activity snapshot. */ get playbackFacts(): Readonly; /** @internal Immutable per-channel attribution for GPU luma uploads and CPU frame copies. */ get uploadFacts(): Readonly; /** @internal Total successful decoded-frame publications into the GPU array cache. */ get gpuCacheUploadCount(): number; /** @internal Immutable decoded-view GPU-cache snapshot. */ get cacheFacts(): Readonly; /** @internal Immutable owned decoded-frame lifecycle snapshot. */ get frameFacts(): Readonly; /** * Whether a frame can be presented without another decode. Active slots and the decoded-view * array ring are one residency class for the scheduler. */ resident(frame: number): boolean; /** @internal Fully complete decoded views retained in the GPU array ring. */ _cachedFrames(): readonly number[]; /** @internal Physical-slot frame identities that are actually bound for presentation. */ _presentationFrames(): readonly number[]; /** * @internal Enforce a weighted proxy membership boundary before a paced replacement is issued. * * The proxy follows the exact pointer sample synchronously. A paced Baked Motion seek may * intentionally defer its decoder request, so retire absent identities now and immediately * retarget physically complete shared corners. Only genuinely missing semantic weight falls * through to the proxy; physical slots, issued demand, cache contents, waiters, and active * decoder work remain reusable. */ _retirePresentationOutside(frames: readonly number[], frameWeights?: readonly number[]): void; /** @internal Whether BakedMotion can commit this clip in a cross-track atomic activation. */ _canActivateFrameSetWeights(): boolean; /** * @internal Activate a BakedMotion-prepared frame set from the shared timestamp. The owner's * paired minimum weights keep color/alpha/depth from exposing a contribution before every * semantic channel reaches it. */ _activateFrameSetWeights(startedAtMs?: number): boolean; /** * Decode predicted frames into the GPU ring without replacing presentation slots. Requests * are issued only while every affected decoder is idle, so prediction never resets foreground * work or weakens the existing storm guard. */ prefetchFrames(frames: readonly number[]): number; /** @internal Settle after the current bounded-slot arrival ramp, if any. */ _waitForWeightRamp(): Promise; /** @internal Transfer exact failed configs to the owner, dropping binary init records here. */ _takeExactDecoderAttempts(channel: 'color' | 'alpha'): readonly AFVideoExactDecoderAttempt[]; /** Interpolated RGBA (`vec4`) at the mesh UV. */ get node(): AFVideoNode | null; /** Interpolated RGB. */ get rgb(): TSLVec3Node; /** Interpolated red channel (handy as a matte). */ get r(): TSLFloatNode; /** Interpolated green channel. */ get g(): TSLFloatNode; /** Interpolated blue channel. */ get b(): TSLFloatNode; /** Interpolated alpha. */ get a(): TSLFloatNode | null; /** Compatibility alias for material.opacityNode = clip.alphaNode. */ get alphaNode(): TSLFloatNode | null; _weightedSample(nodes: readonly TSLTextureNode[], uvNode?: TSLVec2Node | null): TSLVec4Node; _sampleColorSlot(slot: number, uvNode: TSLVec2Node): TSLVec4Node; _sampleAlphaSlot(slot: number, uvNode: TSLVec2Node): TSLFloatNode; /** * Sample one primary decoded slot without assembling its embedded-alpha channel. * * @internal */ _samplePrimarySlot(slot: number, uvNode: TSLVec2Node): TSLVec4Node; /** * Sample one resolved alpha slot without compiling the primary/embedded-matte fallback. * BakedMotion wires this graph after `ready`, when `hasAlpha` is immutable and known. * * @internal */ _sampleResolvedAlphaSlot(slot: number, uvNode: TSLVec2Node): TSLFloatNode; _weightedColorSample(uvNode?: TSLVec2Node): TSLVec4Node; _weightedAlphaSample(uvNode?: TSLVec2Node): TSLFloatNode; /** * Interpolated sample at a custom UV node — e.g. a parallax-displaced coordinate. * * @param {Node} uvNode - The UV to sample at. * @return {Node} Interpolated RGBA at `uvNode`. */ sample(uvNode: TSLVec2Node): AFVideoNode; /** Weighted sample of the currently assigned bounded frame set. */ sampleWeighted(uvNode: TSLVec2Node): AFVideoNode; /** * Sample one physical interpolation slot without applying the temporal cross-fade. * Advanced consumers use this to deform each bracketing image independently before * blending; ordinary video materials should keep using {@link AFVideo#sample}. * * @param {number} slot - Physical texture slot. * @param {Node} uvNode - The UV to sample at. * @return {Node} Slot RGBA at `uvNode`. */ sampleSlot(slot: number, uvNode: TSLVec2Node): AFVideoNode; /** * Scrub to a fractional frame. Decodes a new bracketing pair only when crossing into a new * integer frame (one decode per frame crossed) and updates the GPU cross-fade every call. * * @param {number} f - Fractional frame position in `[0, lastFrame]`. * @return {Promise} Resolves when the visible bracket for this request is loaded; * superseded requests settle with `null`. */ setFrame(f: number, { flushTail }?: AFVideoSetFrameOptions): Promise; /** * Stream an arbitrary weighted set into the fixed slot budget. Duplicate frame indices are * coalesced, so edge/corner grid samples never request the same decoded picture twice. * The returned promise settles once every requested color/matte is bound or fully staged for * the owner's atomic presentation commit. * * @param {number[]} indices - Integer frame ids. * @param {number[]} weights - Per-id blend weights; non-positive taps are skipped. * @param {{wait?:boolean}} options - Disable waiting for fire-and-forget interaction updates. * @return {Promise} Frame-set readiness; a superseded waiter settles with `null`. */ setFrames(indices: readonly number[], weights?: readonly number[], { wait }?: AFVideoSetFramesOptions): Promise; _onFrame(frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): void | Promise; _onGPUPrimaryFrame(frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): void; _onColorDataFrame(frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): Promise; _onDataFrame(frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): Promise; _onAlphaFrame(frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): void | Promise; _onGPUAlphaFrame(frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): void; _onAlphaDataFrame(frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): Promise; _maybeResolveFirstFrame(): void; _onDecoderError(decoder: AFDecoder, error: unknown, session: AFVideoDecoderGeneration): void; _onParallelDecoderError(decoder: AFDecoder, _error: unknown, session: AFVideoDecoderGeneration): void; _disposeParallelDecoder(session: AFVideoDecoderGeneration, decoder: AFDecoder, retryOnPrimary: boolean): void; _rollbackDecoderInitialization(session: AFVideoDecoderGeneration, error: unknown): void; _retainDecoderConfigAttempts(colorDecoder?: AFDecoder | null, alphaDecoder?: AFDecoder | null, parallelColorDecoder?: AFDecoder | null): void; _disposeDecoderGeneration(session: AFVideoDecoderGeneration | null): void; _releaseMediaDecoderLeases(leases: AFVideoMediaDecoderLeases | null): void; _recordDecoderRequest(decoder: AFDecoder, frames: readonly number[]): void; _recordDecoderArrival(decoder: AFDecoder, frame: number): void; _cachePinnedFrames(): ReadonlySet; _deferReplacementFrame(channel: 'primary' | 'alpha', slot: number, frame: VideoFrame, id: number, session: AFVideoDecoderGeneration, decoder: AFDecoder): boolean; _hasDeferredFrameForDecoder(decoder: AFDecoder): boolean; _pruneDeferredFrames(channel: 'primary' | 'alpha', needed: readonly number[]): void; _flushDeferredFrames(): void; _closeDeferredFrames(): void; _trackVideoFrame(frame: VideoFrame): void; _closeVideoFrame(frame: VideoFrame | null | undefined): void; _retireFrame(frame: VideoFrame | null | undefined): void; _flushRetiredFrames(): void; _preparePreserveFrameSetMembership(): void; _promoteGPUCacheSlots(): void; _frameReady(id: number): boolean; _dropsLatePlaybackFrame(id: number): boolean; _recordPlaybackPresentation(id: number): void; _snapPresentation(id: number): void; _applyFrameSetWeights(): void; _setFrameWeightTarget(target: readonly number[], durationMs?: number, startedAtMs?: number): void; _advanceWeightRamp(generation: number): void; _cancelWeightRamp(): void; _retireFrameWeightSlot(slot: number, loaded: readonly number[]): void; _waitForFrameSet(frames: readonly number[]): Promise; _cancelFrameSetWaiters(): void; _flushFrameSetWaiters(): void; _loadPair(lo: number, hi: number, flushTail?: boolean): void; _loadPairFor(decoder: AFDecoder, held: number[], loaded: number[], lo: number, hi: number, channel: 'primary' | 'alpha', flushTail?: boolean): void; _loadSetFor(decoder: AFDecoder, held: number[], loaded: number[], needed: readonly number[], channel: 'primary' | 'alpha', request?: boolean, flushTail?: boolean): void; _requestPrimaryMissing(held: number[], loaded: number[], needed: readonly number[], flushTail?: boolean): void; _requestMissing(decoder: AFDecoder, held: number[], loaded: number[], needed: readonly number[], flushTail?: boolean): void; _flushQueuedRequest(decoder: AFDecoder | null): void; _blendFactor(f: number): number; /** * Release the decoder, owned frames, and textures. Idempotent. Any `firstFrame` waiter is * settled with `null`; post-dispose `setFrame()` calls are no-ops. */ dispose(): void; } /** * Drive several lock-stepped clips (e.g. an albedo + mask + normals set) to the same * fractional frame in one call. * * @param {AFVideo[]} clips - Clips to scrub together. * @param {number} f - Fractional frame position. * @return {Promise>} Latest bracket readiness for every clip. */ export declare function syncFrame(clips: readonly AFVideo[], f: number, options?: AFVideoSetFrameOptions): Promise; export {};