import type { NMVideoPlayer } from '../../index.js'; import { Plugin } from '@nomercy-entertainment/nomercy-player-core'; /** Options for {@link SubtitleOverlayPlugin}. Currently no configurable options. */ export interface SubtitleOverlayOptions { } /** * Subtitle overlay plugin — renders the player's `subtitleCue` stream onto a * positioned DOM tree above the video element. Pools `.subtitle-area` nodes so * multiple simultaneous cues render as independently-positioned boxes. * Add via `player.addPlugin(subtitleOverlayPlugin)`. */ export declare class SubtitleOverlayPlugin extends Plugin { static readonly id: string; static readonly version: string; static readonly description: string; /** * `.subtitle-overlay` — outer positioned wrapper sized to the * video display rectangle by `bindOverlayToVideo`. */ private overlay; /** * `.subtitle-safezone` — inner wrapper that hosts cue areas * inside the WebVTT 5% safe-area inset. */ private safezone; /** * Pool of `.subtitle-area > .subtitle-text` pairs — one per * active cue. The browser's native VTT renderer paints each * active cue as a separate positioned box, so we mirror that. * Pool grows on demand and shrinks back to zero when no cues * are active. */ private areas; /** * Last-applied subtitle style — re-applied to each new pool * entry so a cue spawned mid-playback inherits the latest * font / color / edge / area background. Initialised lazily * from `player.subtitleStyle()` in `use()`. */ private currentStyle; /** * Active language tag, mirrored onto every `.subtitle-text` for * language-specific CSS rules / selectors. */ private currentLanguage; use(): void; /** * Resize the cue-area pool to exactly `n` entries. Reuses existing * DOM nodes; new entries are appended with `.subtitle-area` * + `.aligned-center` defaults (overridden per-cue when the * `align` setting differs). Overflow entries are removed. */ private ensureAreaCount; private setLanguage; /** * Render every active cue into its own positioned `.subtitle-area`. * Called from the player's `subtitleCue` event — that event fires * on every cuechange (native track) or every `enter`/`exit` from * the kit's sidecar `CueTracker`, so the pool always reflects the * current `activeCues` set. */ private renderCues; /** * Resolve overlaps between active cue areas by pushing later cues * away from the earlier ones along the line axis. Walks areas in * cue order — the cue listed first gets to keep its requested * position; subsequent cues are nudged so they don't visually * collide. * * Per WebVTT step 12 (cue layout) the displaced cue is pushed in * the line direction. For top-anchored cues that's downward; for * bottom-anchored cues that's upward. We pick the direction so the * displaced cue never crosses the safezone bottom — if pushing * down would overflow, push up instead and re-anchor as `bottom:`. */ private avoidCueCollisions; /** * Sizes the overlay to the actual video display rectangle (letterbox-fit), * not the player container. Cue font size scales with the overlay rectangle * because cqi units resolve against the nearest container-query ancestor * (`.nomercyplayer`), and the overlay dimensions are driven by the * letterbox-fit calculation. * * Consumes `player.videoRect()` and the `'videoRect'` event — single * source of truth for the contained-rect math, shared with other plugins. */ private bindOverlayToVideo; /** * Apply the cached subtitle-style to a specific area+text pair. * Colors run through `parseColorToHex` which yields `#RRGGBBAA` so the * alpha byte is correct even when `textOpacity` / `windowOpacity` is 0. */ private applyStyleTo; /** * Translate a cue's `line` / `align` / `size` into CSS positioning * on a single `.subtitle-area`, per the WebVTT cue layout rules * (W3C WebVTT 1.0, "Apply WebVTT cue settings"): * * horizontal: * position default = 0% / 50% / 100% based on alignment * left = position - alignment_anchor * size * width = size% * * where alignment_anchor is 0 / 0.5 / 1 for start / center / end. * * vertical: * line auto → `bottom: 0` (anchored to safezone bottom) * line in lower half → anchored by `bottom: <100 - line>%` so * the cue sits ABOVE the line position * and never extends past the safezone * bottom (matches the native renderer's * fallback when a top-anchored cue * would overflow) * line in upper half → anchored by `top: %` * * text alignment inside the box maps to `.aligned-{start|center|end}`. * * Width is written as `size%`, never `100%` plus `left:3%` — that * combination would overflow the safezone by 3% on the right. */ private applyCuePositioningTo; } export declare const subtitleOverlayPlugin: typeof SubtitleOverlayPlugin;