/** * Movi Element Module * * Provides the custom HTML element wrapper for Movi Player. * This is the complete bundle including UI controls and gestures. * * Usage: * ```typescript * import { MoviElement } from 'movi/element'; * // or just use in HTML * ``` * * HTML Usage: * ```html * * ``` */ export type { Track, TrackType, VideoTrack, AudioTrack, SubtitleTrack, SubtitleRenderer, SubtitleCue, SourceConfig, CacheConfig, RendererType, DecoderType, PlayerConfig, MediaInfo, VideoDecoderConfig, AudioDecoderConfig, Packet, DecodedVideoFrame, DecodedAudioFrame, PlayerState, PlayerEventMap, PlaybackAssessment, PlaybackAssessmentOptions, PlaybackQuery, DecodeAudioOptions, DecodedAudioChunk, } from './types'; export { upgradeVideoElements, playerFor, type UpgradeOptions, type UpgradedVideo, } from './upgrade'; export { Logger, LogLevel } from './utils/Logger'; export { Time, TIME_BASE } from './utils/Time'; export { EventEmitter } from './events/EventEmitter'; export { WasmBindings, ThumbnailBindings, type DataSource } from './wasm/bindings'; export { loadWasmModule, loadWasmModuleNew, getWasmModule, isWasmModuleLoaded } from './wasm/FFmpegLoader'; export type { MoviWasmModule, StreamInfo, PacketInfo } from './wasm/types'; export type { SourceAdapter } from './source/SourceAdapter'; export { HttpSource, createHttpSource } from './source/HttpSource'; export { FileSource, createFileSource } from './source/FileSource'; export { ThumbnailHttpSource, createThumbnailHttpSource } from './source/ThumbnailHttpSource'; export { EncryptedHttpSource } from './source/EncryptedHttpSource'; export type { EncryptedSourceConfig } from './source/EncryptedHttpSource'; export { registerSourceAdapter, unregisterSourceAdapter, getRegisteredSchemes, } from './source/adapterRegistry'; export type { SourceAdapterFactory, SourceAdapterFactoryConfig, } from './source/adapterRegistry'; export { generateFingerprint } from './utils/Fingerprint'; export { LRUCache } from './cache/LRUCache'; export { Demuxer } from './demux/Demuxer'; export { MoviVideoDecoder } from './decode/VideoDecoder'; export { MoviAudioDecoder } from './decode/AudioDecoder'; export { SubtitleDecoder } from './decode/SubtitleDecoder'; export { CanvasRenderer } from './render/CanvasRenderer'; export { AudioRenderer } from './render/AudioRenderer'; export { TrackManager } from './core/TrackManager'; export { Clock } from './core/Clock'; export { PlayerStateManager } from './core/PlayerState'; export { PlaybackController } from './core/PlaybackController'; export { MoviPlayer } from './core/MoviPlayer'; export { MoviElement } from './render/MoviElement'; export type { MoviControlSpec, MoviControlItem, MoviDividerSpec } from './render/MoviElement'; export type { MoviPlaylistItem } from './render/MoviElement'; import type { MoviElement as MoviElementType } from './render/MoviElement'; export { VERSION } from './version'; export { BUILD } from './build-flags'; export { QoECollector, beaconSink, QOE_SCHEMA_VERSION, } from './utils/QoE'; export type { QoEEvent, QoESink, QoESession } from './utils/QoE'; /** * The documented `` attribute surface. Kept as a flat string/ * boolean map so it can back both the HTMLElementTagNameMap typing and the * framework wrappers. Any attribute may also be set as a property on the * element instance (see MoviElement). */ export interface MoviPlayerAttributes { src?: string; poster?: string; posterfit?: string; postertime?: string; controls?: boolean | ""; autoplay?: boolean | ""; /** * Repeat. A bare attribute repeats the ITEM, which is what it has always * done; `loop="all"` repeats the QUEUE instead — the next item plays, and * the last leads back to the first. * * this file, over and over * the playlist, round and round * …with five seconds between items * the same — a gap can only mean the queue * * Aliases for the queue: `playlist`, `queue`, `wrap`. `all` implies that the * queue advances at all. The number is the gap between items, which saves * reaching for a second attribute to say it; `autoadvance` still wins when * it names one of its own. */ loop?: boolean | "" | "all" | "one" | string; muted?: boolean | ""; /** Play inline (don't auto-fullscreen on iOS). On any touch device, touch * gestures (swipe-seek / volume) are suppressed while inline so they don't * fight the page's scroll; fullscreen gestures are unaffected. Replaces * `gesturefs`. */ playsinline?: boolean | ""; preload?: "none" | "metadata" | "auto"; volume?: number | string; playbackrate?: number | string; theme?: "dark" | "light"; /** One or two CSS colours, space-separated: primary, then optional * secondary (`"#8B5CF6 #22D3EE"`). */ themecolor?: string; title?: string; headers?: string; crossorigin?: "anonymous" | "use-credentials"; vr?: string; vrpad?: boolean | ""; audioonly?: boolean | ""; audiooutput?: string; stablevolume?: boolean | ""; ambientmode?: boolean | ""; resume?: boolean | ""; /** What the resume position is filed under. Default: the title. */ resumekey?: string; drm?: string; licenseurl?: string; /** Extra HTTP headers for the DRM license request only (JSON object string). */ licenseheaders?: string; encrypted?: boolean | ""; lcevc?: boolean | ""; lcevcurl?: string; /** Token endpoint URL for encrypted playback. */ tokenurl?: string; /** Video endpoint URL for encrypted playback. */ videourl?: string; /** Video identifier sent to the token server. */ videoid?: string; /** Element width in pixels (CSS sizing is preferred). */ width?: number | string; /** Element height in pixels (CSS sizing is preferred). */ height?: number | string; /** How the video fills the canvas. */ objectfit?: "contain" | "cover" | "fill" | "zoom" | "control"; /** Rotate the video, in degrees (snaps to a quarter-turn). */ rotate?: 0 | 90 | 180 | 270; /** Rendering backend. */ renderer?: "canvas"; /** Show the title-bar overlay at the top of the player. */ showtitle?: boolean | ""; /** Where the title bar may show, plus an optional back arrow. Tokens: * `both` (default) / `fullscreen` / `windowed`, and `back` — scoped with * `back-mobile`, `back-fullscreen` or `back-mobile-fullscreen`. */ titlemode?: string; /** Offer "Add subtitle file…" in the subtitle menu (SRT/VTT/TTML, read * locally — the file never leaves the page). */ subtitlepicker?: boolean | ""; /** Chapters from outside the media file, as a JSON array of * `{ title, start, end?, image? }` (seconds). `image` is a URL the timeline * tile shows instead of decoding a frame at `start`. Use the `chapters` * property to pass the array directly. */ chapters?: string; /** * A queue, as a JSON array of `{ src?, id?, title?, poster?, startAt? }` — or * of bare source strings — or a URL to fetch that array from. Setting one * loads its first item, unless `src` already names one of them. Use the * `playlist` property to pass the array directly. * * Items may leave `src` off, for a queue the HOST loads: the element still * owns the buttons, the keys and the lock-screen skip pair, and announces * every move as a cancelable `itemchange`. That is the shape to use when a * source is more than a URL — a `` quality ladder, per-language * audio, `` subtitles — or when each item is its own route. */ playlist?: string; /** Which item to open on. Default 0. */ playlistindex?: number | string; /** * Let the end of one item start the next. Off by default. A number is the * gap in seconds (`autoadvance="5"`), `loop` joins the ends of the queue * (`autoadvance="loop"`, or `"5 loop"` for both) — though `loop="all"` on * the element says the same thing more plainly, and is where to reach for * it. A BARE `loop` on the element is a different thing and wins: it repeats * the item, so nothing ever ends and the queue never moves. */ autoadvance?: boolean | "" | number | string; /** * Play the queue in a random order. Off by default. * * Its own attribute rather than a `loop` token, because it is its own * question: a queue can be shuffled and played through once, and it can be * looped in the order it was given. They compose — `shuffle loop="all"` is * the pair most people mean — but neither implies the other. * * The ORDER is shuffled, not the queue: `playlist` and `playlistIndex` still * describe the list the host handed over, so a page's own rows keep matching, * and turning it off puts the order back without reloading anything. The item * playing keeps its place, so switching shuffle on never restarts it. The * draw stands until the queue is replaced, shuffle is switched off and on, * or `reshuffle()` is called. */ shuffle?: boolean | ""; /** Enable ±10s fast-seek. Bare = every affordance; a token list narrows it to * `buttons` (the bottom-bar pair), `keys` (arrow keys) and/or `gestures` * (double-tap and drag-to-seek) — e.g. `fastseek="keys gestures"`. Aliases: * `touch`, `nontouch`, `keyonly`, `controls`, `none`. */ fastseek?: boolean | "" | string; /** Enable the double-tap-to-seek gesture. */ doubletap?: boolean | ""; /** Disable all keyboard shortcuts. */ nohotkeys?: boolean | ""; /** Start playback at this time, in seconds. */ startat?: number | string; /** Target prefetch window, in megabytes. */ buffersize?: number | string; /** * How long an interruption must last, in seconds, before the viewer is shown * a loading spinner. Defaults to `"1 2"` — a stall after a second, an * opening after two; `0` shows it at once. A second number gives the opening * its own wait. Applies to every reason the spinner goes up — the opening * load, seeking, buffering, a rendition switch, judder — so a brief stall * passes in silence. */ spinnerdelay?: number | string; /** * How long to wait, in milliseconds, before putting the OPENING poster up. * Default 0 — paint it at once. For a host that prefetches: a load that * finishes inside the wait shows no poster at all, so the picture is simply * there rather than preceded by a cover that flashes. */ posterdelay?: number | string; /** * Show a notice when what is loaded is not expected to play smoothly on this * device at the current speed — "This video may not play smoothly", with the * reason. Checked on load and on every speed change. Fires a cancelable * `smoothwarning` event first. */ smoothwarning?: boolean | ""; /** * Keep `smoothwarning` on but never raise the link-speed notice ("This media * needs about N Mbps"). For hosts serving local files over HTTP (a desktop * shell or LAN server on 127.0.0.1), where the player would probe loopback * and blame a connection that doesn't exist. Decode notices stay. */ nolinkwarning?: boolean | ""; /** Override the video frame rate (0 = use the source's own). */ fps?: number | string; /** Force software decoding (FFmpeg WASM) instead of WebCodecs. `auto` (default) picks per source. */ sw?: boolean | "auto"; /** Enable HDR tone-mapping (Chromium + canvas renderer + HDR source). */ hdr?: boolean | ""; /** * Generate on-demand thumbnails for seek-bar previews. `thumb="precise"` * decodes forward from the keyframe to the frame under the pointer, rather * than showing the keyframe before it — exact, at the cost of a run of * frames per preview. */ thumb?: boolean | "precise" | ""; /** * Enter Picture-in-Picture automatically when the tab is hidden, as the * attribute does on `