import { TemplateResult as TemplateResult$1 } from "../node_modules/lit-html/development/lit-html.js"; import { FrameRenderable, FrameState } from "../preview/FrameController.js"; import { EFFramegen } from "../EF_FRAMEGEN.js"; import { EFMedia } from "./EFMedia.js"; import { RenderToVideoOptions } from "../preview/renderTimegroupToVideo.types.js"; import { Ref } from "../node_modules/lit-html/development/directives/ref.js"; import { ScrubInputCache } from "./EFMedia/videoTasks/ScrubInputCache.js"; import * as _$lit from "lit"; import { PropertyValueMap } from "lit"; import { VideoSample } from "mediabunny"; //#region src/elements/EFVideo.d.ts declare global { var EF_FRAMEGEN: EFFramegen; } interface LoadingState { isLoading: boolean; operation: "scrub-segment" | "video-segment" | "seeking" | "decoding" | null; message: string; } /** * Event detail for scrub segment loading progress. * Dispatched during prefetchScrubSegments to indicate network activity. */ declare class VideoSeekTask { #private; value: VideoSample | undefined; task: ((...args: any[]) => any) | undefined; taskComplete: Promise; begin(): void; complete(sample: VideoSample | undefined): void; abort(): void; } declare const EFVideo_base: typeof EFMedia; declare class EFVideo extends EFVideo_base implements FrameRenderable { #private; static styles: _$lit.CSSResult[]; canvasRef: Ref; unifiedVideoSeekTask: VideoSeekTask; /** * Pin the video to a specific source time, making it a freeze frame. * * When set, `currentSourceTimeMs` ignores the composition timeline and * always returns this value — the same frame is shown for the entire * duration of the element. Pair with `duration` to control how long the * freeze frame occupies in the timeline: * * `` * * Accepts any duration string: `"4.367s"`, `"4367ms"`, etc. * * @domAttribute "current-time" */ pinnedSourceTimeMs: number | undefined; /** * When `current-time` is set, return the pinned source time regardless of * where the composition playhead is. */ get currentSourceTimeMs(): number; /** * When `current-time` is set, allow the `duration` attribute to override * the video's intrinsic duration so the timeline footprint is controlled * explicitly instead of being derived from the full video length. */ get intrinsicDurationMs(): number | undefined; /** * Get the current rendition being displayed. * @public */ get currentRenditionId(): "main" | "scrub" | undefined; /** * Query readiness state for a given time. * @implements FrameRenderable * * Note: The timeMs parameter is the root timegroup's time. We check against * this.currentSourceTimeMs since that's what we cache in prepareFrame. */ getFrameState(_timeMs: number): FrameState; /** * Async preparation - seeks video and caches the sample. * @implements FrameRenderable * * Note: The timeMs parameter is the root timegroup's time. We ignore it and * use this.currentSourceTimeMs instead, which accounts for: * - Our position within the parent timegroup (ownCurrentTimeMs) * - Source trimming (sourceIn/sourceOut or trimStart/trimEnd) */ prepareFrame(_timeMs: number, signal: AbortSignal): Promise; /** * Synchronous render - paints cached video sample to canvas. * @implements FrameRenderable * * Note: The timeMs parameter is the root timegroup's time. We use * this.currentSourceTimeMs to match what prepareFrame cached. */ renderFrame(_timeMs: number): void; /** * Loading state for user feedback */ loadingState: { isLoading: boolean; operation: LoadingState["operation"]; message: string; }; constructor(); protected updated(changedProperties: PropertyValueMap | Map): void; render(): TemplateResult$1<1>; get canvasElement(): HTMLCanvasElement | undefined; /** * Start a delayed loading operation for testing */ startDelayedLoading(operationId: string, message: string, options?: { background?: boolean; }): void; /** * Clear a delayed loading operation for testing */ clearDelayedLoading(operationId: string): void; /** * Set loading state for user feedback */ private setLoadingState; /** * Paint the current video frame to canvas */ paint(seekToMs: number, parentSpan?: any): void; /** * Clear the canvas when element becomes inactive */ clearCanvas(): void; /** * Display a video frame on the canvas. * VP9-alpha VideoFrames carry alpha natively (I420A / RGBA) — ctx.drawImage * composites the alpha automatically when the canvas has alpha: true (default). */ displayFrame(frame: VideoFrame, seekToMs: number, parentSpan?: any): void; /** * Check if we're in production rendering mode (EF_FRAMEGEN active) vs preview mode */ private isInProductionRenderingMode; /** * Check if EF_FRAMEGEN has explicitly started frame rendering (not just initialization) */ private isFrameRenderingActive; /** * Get a decoded VideoFrame at a specific source media timestamp. * Returns a standard WebCodecs VideoFrame — caller MUST call .close() when done. * * Uses the same routing logic as the unified video system: * - "auto": main track for production rendering, follows normal routing otherwise * - "scrub": force low-res scrub track (for thumbnails) * - "main": force full-quality main track * * @param sourceTimeMs - Timestamp in source media coordinates (not timeline) * @param options - Quality and abort signal * @returns VideoFrame that the caller must close() * @public */ getVideoFrameAtSourceTime(sourceTimeMs: number, options?: { quality?: "auto" | "scrub" | "main"; signal?: AbortSignal; }): Promise; /** * Capture a video frame directly at a source media timestamp. * Designed for export/rendering. * Does NOT paint to the element's internal canvas. * * Uses the same routing logic as unified video system: * - "auto": main track for production rendering, follows normal routing otherwise * - "scrub": force low-res scrub track (for thumbnails) * - "main": force full-quality main track * * @param sourceTimeMs - Timestamp in source media coordinates (not timeline) * @param options - Capture options including quality and abort signal * @returns Frame data for serialization * @public */ captureFrameAtSourceTime(sourceTimeMs: number, options?: { quality?: "auto" | "scrub" | "main"; signal?: AbortSignal; }): Promise<{ dataUrl: string; width: number; height: number; }>; /** * Pre-fetch scrub segments for given timestamps. * Loads 30-second segments sequentially, emitting progress events. * This ensures scrub track is cached for fast thumbnail generation. * * @param timestamps - Array of timestamps (in ms) that will be captured * @param onProgress - Optional callback for loading progress * @param signal - Optional AbortSignal for cancellation * @returns Promise that resolves when all segments are cached * @public */ prefetchScrubSegments(timestamps: number[], onProgress?: (loaded: number, total: number, segmentTimeRange: [number, number]) => void, signal?: AbortSignal): Promise; /** * Warm the scrub BufferedSeekingInput cache for all segments covering [fromMs, toMs]. * * Unlike prefetchScrubSegments (which only warms the network layer), this method * constructs BufferedSeekingInput instances for each segment so that subsequent * scrub seeks within the range complete without a network round-trip or BSI * construction overhead. * * Returns a Promise that resolves after the range has been computed and segment * fetches have been kicked off (but before individual fetches complete). * Callers may await this or discard the promise — both are valid. */ warmScrubCacheForRange(fromMs: number, toMs: number, signal?: AbortSignal): Promise; /** * Reset per-instance caches and rendition state. Allows tests to force * the scrub fallback path on the next render without clearing the shared * mediaCache (which races with in-flight fetches from other elements). * @public – test-only */ clearInstanceCaches(): void; /** * Returns scrub cache statistics for inspection in tests. * @public – test-only */ getScrubCacheStats(): ReturnType; /** * Clean up resources when component is disconnected */ disconnectedCallback(): void; didBecomeRoot(): void; didBecomeChild(): void; /** * Get the natural dimensions of the video (coded width and height). * Returns null if the video hasn't loaded yet or canvas isn't available. * * @public */ getNaturalDimensions(): { width: number; height: number; } | null; /** * Render this video element to an MP4 using the direct video-to-video fast path. * Bypasses DOM serialization — decodes frames directly and re-encodes to MP4. * Respects trim, CSS filter, and opacity. * * @param options - Rendering options (fps, codec, bitrate, etc.) * @returns Promise resolving to video buffer (if returnBuffer), or undefined * @public */ renderToVideo(options?: RenderToVideoOptions): Promise; } declare global { interface HTMLElementTagNameMap { "ef-video": EFVideo; } } //#endregion export { EFVideo }; //# sourceMappingURL=EFVideo.d.ts.map