/**
* Custom HTML element for Movi Player
* Usage:
*
* Note: Custom element names must contain a hyphen per HTML spec.
*
* Supports native video element properties:
* - src, autoplay, controls, loop, muted, playsinline, preload, poster
* - width, height, crossorigin
* - volume, playbackRate, currentTime, duration, paused, ended
*/
import type { RendererType } from "../types";
import type { SourceAdapter } from "../source/SourceAdapter";
import { type QoESink, type QoESession } from "../utils/QoE";
export declare class MoviElement extends HTMLElement {
private canvas;
private video;
private subtitleOverlay;
private _captionLive;
private _captionObserver;
private _lastCaptionText;
private _qoe;
private _qoeHeartbeat;
private player;
private isLoading;
private _isUnsupported;
private eventHandlers;
private controlsContainer;
private unmuteOverlay;
private _userHasUnmuted;
private brokenIndicator;
private emptyStateIndicator;
private coverArtOverlay;
private coverArtCanvas;
private coverArtBitmap;
private _posterCoverBitmap;
private _posterCoverUrl;
private _posterCoverLoading;
private _coverArtBgEl;
private _coverArtBgUrl;
private _coverArtResolved;
private _lastStripDispatched;
private controlsTimeout;
private isOverControls;
private isSeeking;
private pendingSeekTarget;
private _pendingSeek;
private isDragging;
private isTouchDragging;
private touchStartX;
private touchStartY;
private touchStartTime;
private gesturePerformed;
private clickTimer;
private lastSeekTime;
private lastSeekSide;
private cumulativeSeekAmount;
private _seekChainTarget;
private _contextMenuVisible;
private _contextMenuJustClosed;
private _menuPortalHost;
private _menuPortalRoot;
private _menuHome;
private lastTouchTime;
private _holdSpeedTimer;
private _holdSpeedActive;
private _rateBeforeHold;
private _openMenuViaGear;
private _mediaSessionReady;
private _mediaSessionLastPos;
private _mediaSessionArtworkUrl;
private _nerdStatsVisible;
private _currentManualRotation;
private _timelineGenerating;
private _timelineCancelled;
private _timelineComplete;
private _timelineNextIndex;
private nerdStatsInterval;
private networkSpeedHistory;
private _stutterInterval;
private _stutterLastPresented;
private _stutterSeconds;
private _stutterCooldown;
private _stutterCooldownTimer;
private static readonly GRAPH_MAX_SAMPLES;
private _src;
private _sourceAdapter;
private _headers;
private _audioOnly;
private _audioSrc;
private _videoQualities;
private _audioTracks;
private _subtitleTracks;
private _autoplay;
private _autoplayStarting;
private _autoplayPendingVisible;
private _autoMutedForAutoplay;
private _hasEverPlayed;
private _loopRestartInFlight;
private _pendingPlay;
private _preloadGateActive;
private _resumeDialogPending;
private _posterTime;
private _generatedPosterUrl;
private _posterGenId;
private _controls;
private _loop;
private _muted;
private _playsinline;
private _preload;
private _poster;
private _volume;
private _playbackRate;
private _subtitleDelay;
private _subtitleSettings;
private _ambientMode;
private _renderer;
private _objectFit;
private _currentFit;
private _thumb;
private _linearMode;
private _hdr;
private _theme;
private _sw;
private _swForcedForCurrentSource;
private _suppressSwReload;
private _fps;
private _gesturefs;
private _noHotkeys;
private _startAt;
private _fastSeek;
private _doubleTap;
private _themeColor;
private _bufferSize;
private _title;
private _showTitle;
private _resume;
private _stableVolume;
private _audioOutputDeviceId;
private _audioOutputs;
private _audioOutputsBound;
private _vr360;
private _vrPointerDown;
private _vrMoved;
private _vrLastX;
private _vrLastY;
private _vrPinchDist;
private _aspectPinchDist;
private _vrSuppressClick;
private _vrPadDragging;
private _encrypted;
private _tokenUrl;
private _videoUrl;
private _videoId;
private _resumeSaveInterval;
private _posterSeekActive;
private _titleAutoLoaded;
private _resumeCheckedWithTitle;
private _stripTitleAttr;
private _lastDuration;
private posterElement;
private _ambientWrapper;
private ambientWrapperElement;
private _ambientRafId;
private _lastAmbientSampleTime;
private _lastRateChangeTime;
private static readonly AMBIENT_RATE_CHANGE_COOLDOWN_MS;
private _ambientSampleInterval;
private currentAmbientColors;
private _contextLostTime;
private _contextLostPlaying;
private _lastFrameSnapshot;
private _snapshotPosterActive;
private _snapshotPosterPrev;
private _showSnapshotPoster;
private _hideSnapshotPoster;
private _onVisibilityChange;
static get observedAttributes(): string[];
constructor();
private createContextMenu;
private createControls;
private setupControlHandlers;
private seekFromEvent;
private seekFromTouchEvent;
/** Begin press-and-hold fast playback (2x). No-op unless actively playing, so
* a long-press while paused doesn't silently change the saved rate. */
private startHoldSpeed;
/** End press-and-hold fast playback, restoring the pre-hold rate. */
private stopHoldSpeed;
private setupGestures;
/**
* 360° look-around for mouse + trackpad. Touch is handled inside
* setupGestures (it already owns touchstart/move). These listeners no-op
* unless 360° mode is active, and a drag past a few pixels suppresses the
* trailing click so dragging never toggles play/pause.
*/
private setupVRControls;
/**
* Enable/disable VR rendering and pick the format:
* - half: VR180 (front hemisphere) vs full 360°.
* - fisheye: equidistant fisheye vs equirectangular.
* - sbs: side-by-side stereo (render the left eye) vs mono.
* Forwards to the player's renderer and flips the host class (for cursor +
* touch-action CSS). There's no toggle button: VR turns on automatically for
* sources we know are 360/180 (spherical metadata or the `vr` attribute), the
* same way YouTube treats them.
*/
setVR360(enabled: boolean, half?: boolean, fisheye?: boolean, sbs?: boolean, stereographic?: boolean): void;
/**
* When a custom/generated poster image is showing and 360° is on, draw the
* poster onto the canvas through the equirectangular projection (so it looks
* right, not flat-distorted) and hide the flat
overlay. No-op for the
* decoded-frame poster path (seek/postertime) — that already paints in 360.
*/
private renderVRPosterIfNeeded;
/**
* Resolve the VR format for the CURRENT source from spherical metadata
* (track.projection) + the live `vr` attribute. Never carries the previous
* clip's state over — switching to a normal clip drops back to flat unless
* `vr` is still set.
*
* `vr` attribute tokens (space/comma separated), e.g. `vr="fisheye sbs"`:
* (bare) / 360 → full 360°; 180 → VR180; sbs / 3d → side-by-side stereo
* (left eye); fisheye → equidistant fisheye (implies 180).
*
* projection metadata: 0/undefined = none; 1 = equirectangular;
* 3 = equirectangular-tile; 4 = half-equirectangular (VR180). Stereo/fisheye
* aren't auto-surfaced, so those need the attribute.
*/
private resolveVRMode;
/** Apply the resolved VR format to the renderer (enable OR disable). */
private detectAndApplyVR360;
private setupKeyboardShortcuts;
private setupContextMenu;
private updateContextMenuContent;
/**
* Highlight the current fit as the active row in the aspect-ratio submenu, so
* it reflects the live fit however it was last changed — context menu, the
* bottom-controls aspect button, or the keyboard shortcut. Called each time
* the fit submenu is shown: on hover (desktop, via showSubmenu) and on tap
* (touch, via the action==="fit" branch). Kept OUT of updateContextMenuContent
* (which runs on the main menu's open) to avoid touch-open side effects.
*/
private syncFitSubmenuActive;
private setupSubmenuHover;
private toggleFullscreen;
private _pipWindow;
private restorePiPCanvas;
private togglePiP;
/** Tracks host-driven fullscreen so toggleFullscreen() and the
* movi-fullscreen-request event can reflect it correctly even when
* document.fullscreenElement is null. */
private _hostFullscreen;
/** CSS "fill the viewport" fallback used where the element Fullscreen API
* isn't available (iOS Safari only exposes it for