@rixl/media-core 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +74 -84
  2. package/dist/chunks/B-QvSqjj.js +1 -0
  3. package/dist/chunks/B2DDE32u.js +1 -0
  4. package/dist/chunks/BZFoe94X.js +1 -0
  5. package/dist/chunks/DMkwQjgA.js +1 -0
  6. package/dist/index.d.ts +2005 -82
  7. package/dist/index.js +6 -73
  8. package/package.json +13 -6
  9. package/dist/api/analytics.d.ts +0 -16
  10. package/dist/api/analytics.js +0 -227
  11. package/dist/api/feed.js +0 -52
  12. package/dist/api/heatmap.d.ts +0 -6
  13. package/dist/api/heatmap.js +0 -28
  14. package/dist/api/hot-segments.d.ts +0 -7
  15. package/dist/api/hot-segments.js +0 -20
  16. package/dist/api/image.js +0 -11
  17. package/dist/api/rixl-client.d.ts +0 -3
  18. package/dist/api/rixl-client.js +0 -14
  19. package/dist/api/upload.d.ts +0 -76
  20. package/dist/api/upload.js +0 -150
  21. package/dist/api/video.js +0 -11
  22. package/dist/lib/analytics-builders.d.ts +0 -59
  23. package/dist/lib/analytics-builders.js +0 -88
  24. package/dist/lib/analytics-initialize.d.ts +0 -1
  25. package/dist/lib/analytics-initialize.js +0 -59
  26. package/dist/lib/analytics-utils.d.ts +0 -43
  27. package/dist/lib/analytics-utils.js +0 -85
  28. package/dist/lib/analytics-wire.js +0 -153
  29. package/dist/lib/buffer-progress.d.ts +0 -20
  30. package/dist/lib/buffer-progress.js +0 -37
  31. package/dist/lib/caption-styles.d.ts +0 -20
  32. package/dist/lib/caption-styles.js +0 -56
  33. package/dist/lib/caption-utils.d.ts +0 -80
  34. package/dist/lib/caption-utils.js +0 -111
  35. package/dist/lib/chapter-utils.d.ts +0 -102
  36. package/dist/lib/chapter-utils.js +0 -147
  37. package/dist/lib/click-disambiguation.d.ts +0 -44
  38. package/dist/lib/click-disambiguation.js +0 -80
  39. package/dist/lib/click-outside.d.ts +0 -68
  40. package/dist/lib/click-outside.js +0 -64
  41. package/dist/lib/colors.d.ts +0 -6
  42. package/dist/lib/colors.js +0 -16
  43. package/dist/lib/content-analytics.d.ts +0 -27
  44. package/dist/lib/content-analytics.js +0 -38
  45. package/dist/lib/environment-effects.d.ts +0 -89
  46. package/dist/lib/environment-effects.js +0 -139
  47. package/dist/lib/feed-autoscroll.d.ts +0 -10
  48. package/dist/lib/feed-autoscroll.js +0 -13
  49. package/dist/lib/feed-container-height.d.ts +0 -7
  50. package/dist/lib/feed-container-height.js +0 -11
  51. package/dist/lib/feed-description-overflow.d.ts +0 -1
  52. package/dist/lib/feed-description-overflow.js +0 -9
  53. package/dist/lib/feed-dwell.d.ts +0 -2
  54. package/dist/lib/feed-dwell.js +0 -8
  55. package/dist/lib/feed-loop.d.ts +0 -10
  56. package/dist/lib/feed-loop.js +0 -21
  57. package/dist/lib/feed-scroll.d.ts +0 -11
  58. package/dist/lib/feed-scroll.js +0 -19
  59. package/dist/lib/feed-transforms.d.ts +0 -5
  60. package/dist/lib/feed-transforms.js +0 -30
  61. package/dist/lib/filter-undefined.js +0 -11
  62. package/dist/lib/fullscreen-utils.d.ts +0 -1
  63. package/dist/lib/fullscreen-utils.js +0 -7
  64. package/dist/lib/hls-buffer-flush.js +0 -46
  65. package/dist/lib/hls-error-recovery.d.ts +0 -35
  66. package/dist/lib/hls-error-recovery.js +0 -75
  67. package/dist/lib/hls-event-handlers.js +0 -61
  68. package/dist/lib/hls-loader.js +0 -23
  69. package/dist/lib/hls-setup.d.ts +0 -72
  70. package/dist/lib/hls-setup.js +0 -144
  71. package/dist/lib/hls-utils.d.ts +0 -31
  72. package/dist/lib/hls-utils.js +0 -34
  73. package/dist/lib/image-render.d.ts +0 -29
  74. package/dist/lib/image-render.js +0 -63
  75. package/dist/lib/keyboard-config.d.ts +0 -66
  76. package/dist/lib/keyboard-config.js +0 -127
  77. package/dist/lib/keyboard-utils.d.ts +0 -4
  78. package/dist/lib/keyboard-utils.js +0 -11
  79. package/dist/lib/lifecycle-effects.d.ts +0 -67
  80. package/dist/lib/lifecycle-effects.js +0 -78
  81. package/dist/lib/loading-debounce.d.ts +0 -26
  82. package/dist/lib/loading-debounce.js +0 -38
  83. package/dist/lib/numbers.d.ts +0 -6
  84. package/dist/lib/numbers.js +0 -36
  85. package/dist/lib/pip-utils.d.ts +0 -16
  86. package/dist/lib/pip-utils.js +0 -32
  87. package/dist/lib/playback-handlers.d.ts +0 -33
  88. package/dist/lib/playback-handlers.js +0 -51
  89. package/dist/lib/playback-slider.d.ts +0 -23
  90. package/dist/lib/playback-slider.js +0 -24
  91. package/dist/lib/player-labels.d.ts +0 -23
  92. package/dist/lib/player-labels.js +0 -132
  93. package/dist/lib/player-menu-labels.d.ts +0 -80
  94. package/dist/lib/player-menu-labels.js +0 -829
  95. package/dist/lib/player-ui-actions.d.ts +0 -10
  96. package/dist/lib/player-ui-actions.js +0 -58
  97. package/dist/lib/progress-fraction.d.ts +0 -11
  98. package/dist/lib/progress-fraction.js +0 -20
  99. package/dist/lib/progress-persist.d.ts +0 -28
  100. package/dist/lib/progress-persist.js +0 -54
  101. package/dist/lib/segment-analytics.d.ts +0 -20
  102. package/dist/lib/segment-analytics.js +0 -29
  103. package/dist/lib/subtitle-logic.d.ts +0 -31
  104. package/dist/lib/subtitle-logic.js +0 -75
  105. package/dist/lib/subtitle-utils.d.ts +0 -16
  106. package/dist/lib/subtitle-utils.js +0 -37
  107. package/dist/lib/time.d.ts +0 -1
  108. package/dist/lib/time.js +0 -17
  109. package/dist/lib/track-persistence.d.ts +0 -4
  110. package/dist/lib/track-persistence.js +0 -35
  111. package/dist/lib/video-preload-config.d.ts +0 -34
  112. package/dist/lib/video-preload-config.js +0 -41
  113. package/dist/lib/video-spinner.d.ts +0 -25
  114. package/dist/lib/video-spinner.js +0 -35
  115. package/dist/lib/video-stats.d.ts +0 -28
  116. package/dist/lib/video-stats.js +0 -44
  117. package/dist/lib/volume-utils.d.ts +0 -59
  118. package/dist/lib/volume-utils.js +0 -55
  119. package/dist/progressbar.d.ts +0 -10
  120. package/dist/progressbar.js +0 -123
  121. package/dist/store/analytics-context-store.d.ts +0 -4
  122. package/dist/store/analytics-context-store.js +0 -13
  123. package/dist/store/analytics-device-store.d.ts +0 -8
  124. package/dist/store/analytics-device-store.js +0 -44
  125. package/dist/store/analytics-session-store.d.ts +0 -8
  126. package/dist/store/analytics-session-store.js +0 -40
  127. package/dist/store/analytics-store.d.ts +0 -30
  128. package/dist/store/analytics-store.js +0 -88
  129. package/dist/store/controls-store.d.ts +0 -16
  130. package/dist/store/controls-store.js +0 -53
  131. package/dist/store/feed-cache-store.d.ts +0 -24
  132. package/dist/store/feed-cache-store.js +0 -165
  133. package/dist/store/feed-interaction-store.d.ts +0 -17
  134. package/dist/store/feed-interaction-store.js +0 -32
  135. package/dist/store/feed-store.d.ts +0 -16
  136. package/dist/store/feed-store.js +0 -38
  137. package/dist/store/generic-store.js +0 -24
  138. package/dist/store/image-store.d.ts +0 -2
  139. package/dist/store/image-store.js +0 -8
  140. package/dist/store/player-container-element-store.d.ts +0 -10
  141. package/dist/store/player-container-element-store.js +0 -38
  142. package/dist/store/player-global-actions.js +0 -53
  143. package/dist/store/player-media-element-store.d.ts +0 -10
  144. package/dist/store/player-media-element-store.js +0 -38
  145. package/dist/store/player-store-actions.js +0 -197
  146. package/dist/store/player-store.d.ts +0 -94
  147. package/dist/store/player-store.js +0 -127
  148. package/dist/store/player-track-actions.js +0 -44
  149. package/dist/store/postStore.d.ts +0 -20
  150. package/dist/store/postStore.js +0 -112
  151. package/dist/store/settings/constants.d.ts +0 -15
  152. package/dist/store/settings/constants.js +0 -47
  153. package/dist/store/settings/defaults.d.ts +0 -2
  154. package/dist/store/settings/defaults.js +0 -24
  155. package/dist/store/settings/storage.d.ts +0 -3
  156. package/dist/store/settings/storage.js +0 -28
  157. package/dist/store/settings/store.d.ts +0 -32
  158. package/dist/store/settings/store.js +0 -59
  159. package/dist/store/settings/types.d.ts +0 -27
  160. package/dist/store/settings/validation.d.ts +0 -7
  161. package/dist/store/settings/validation.js +0 -55
  162. package/dist/store/settings-menu-store.d.ts +0 -19
  163. package/dist/store/settings-menu-store.js +0 -30
  164. package/dist/store/video-store.d.ts +0 -2
  165. package/dist/store/video-store.js +0 -8
  166. package/dist/types/analytics.d.ts +0 -113
  167. package/dist/types/feed.d.ts +0 -21
  168. package/dist/types/file.d.ts +0 -12
  169. package/dist/types/heatmap.d.ts +0 -5
  170. package/dist/types/hot-segments.d.ts +0 -9
  171. package/dist/types/image.d.ts +0 -9
  172. package/dist/types/uuid.d.ts +0 -1
  173. package/dist/types/video.d.ts +0 -22
package/dist/index.d.ts CHANGED
@@ -1,82 +1,2005 @@
1
- import { ProgressBarControls, ProgressBarProps, initProgressBar } from "./progressbar.js";
2
- import { getFeedPost, getFeedPosts } from "./store/feed-store.js";
3
- import { getImage } from "./store/image-store.js";
4
- import { getVideo } from "./store/video-store.js";
5
- import { FeedPost, FeedPostsResponse } from "./types/feed.js";
6
- import { UUID } from "./types/uuid.js";
7
- import { formatTime } from "./lib/time.js";
8
- import { clamp, formatNumber, formatNumberSm } from "./lib/numbers.js";
9
- import { CSSProperties, DEFAULT_IMAGE_ASPECT_RATIO, IMAGE_ASPECT_RATIO_THRESHOLD, ImageContainerStyleParams, ImageRenderAction, ImageRenderState, getImageAspectRatio, getImageContainerStyle, getImageStyle, imageRenderReducer, initialImageRenderState } from "./lib/image-render.js";
10
- import { hexToRGB, hexToRGBAString } from "./lib/colors.js";
11
- import { shouldIgnoreKeyboardEvent } from "./lib/keyboard-utils.js";
12
- import { PLAYER_LANGUAGES, PlayerControlLabels, PlayerLanguage, getPlayerControlLabels, resolvePlayerLanguage } from "./lib/player-labels.js";
13
- import { PLAY_PAUSE_KEYS, SEEK_LARGE_SECONDS, SEEK_SMALL_SECONDS, SHORTCUTS_CONFIG, ShortcutAction, ShortcutDefinition, VOLUME_DELTA, VideoKeyboardHandlers, VideoSdkKey, executeShortcutAction, getSeekAmount, getSeekPercent, getVolumeDelta, resolveShortcutAction } from "./lib/keyboard-config.js";
14
- import { calculateVolumeToSet, clampVolume, getPointerClientX, getRestoredVolume, getVolumeFromPointer, isEffectivelyMuted, shouldBeMuted } from "./lib/volume-utils.js";
15
- import { CaptionTextSettings, CaptionWindowSettings, SmartCaptionPositionParams, getCaptionTextStyle, getCaptionWindowStyle, getSmartCaptionPosition } from "./lib/caption-styles.js";
16
- import { isDocumentFullscreen } from "./lib/fullscreen-utils.js";
17
- import { isVideoPictureInPicture, togglePictureInPicture } from "./lib/pip-utils.js";
18
- import { PERSIST_INTERVAL_MS, RESUME_MIN_POSITION_SECONDS, RESUME_MIN_REMAINING_SECONDS, getPersistedProgress, persistProgress, shouldPersistProgress, shouldResumeFromPosition } from "./lib/progress-persist.js";
19
- import { PRELOAD_RANGE, UNLOAD_DISTANCE, VideoLoadState, getVideoLoadState } from "./lib/video-preload-config.js";
20
- import { LOADING_SPINNER_DELAY_MS, LoadingDebounceState, UpdateLoadingStateOptions, cleanupLoadingDebounce, createLoadingDebounceState, updateLoadingState } from "./lib/loading-debounce.js";
21
- import { PlaybackHandlerCallbacks, calculateAspectRatio, handleVideoError, handleVideoPause, handleVideoPlay, handleVideoRateChange, updatePlayerLoadingState } from "./lib/playback-handlers.js";
22
- import { ClickDisambiguationState, DOUBLE_CLICK_THRESHOLD_MS, HandleClickOptions, HandleDoubleClickOptions, SINGLE_CLICK_DELAY_MS, cleanupClickDisambiguation, createClickDisambiguationState, handleClick, handleDoubleClick } from "./lib/click-disambiguation.js";
23
- import { AppliedVolumeSync, DeriveVolumeSyncOptions, PipReentryOptions, bindFullscreenChangeListener, bindPictureInPictureChangeListener, bindPipVisibilityReentry, deriveVolumeSync, observeViewport, shouldReenterPictureInPicture } from "./lib/environment-effects.js";
24
- import { FeedPlaybackAction, FeedPlaybackDecisionInput, PosterDimensions, VideoPreloadAttribute, bindEndedListener, bindPlaybackRateSync, getAspectRatioFromPoster, getFeedPlaybackAction, getPreloadAttribute } from "./lib/lifecycle-effects.js";
25
- import { ClickOutsideOptions, bindClickOutside, bindDocumentHidden, isClickOutside, isInsideExcludedElement } from "./lib/click-outside.js";
26
- import { shouldShowSpinner } from "./lib/video-spinner.js";
27
- import { HlsController, HlsInstance, SetupHlsOptions, createHlsConfig, setupHls } from "./lib/hls-setup.js";
28
- import { AudioTrack, QualityLevel, generateLevelName, getQualityLabel, isHlsStream, sortLevelsByQuality } from "./lib/hls-utils.js";
29
- import { getPersistedAudioTrack, getPersistedSubtitleTrack, persistAudioTrack, persistSubtitleTrack } from "./lib/track-persistence.js";
30
- import { analyticsStore, analyticsStoreActions } from "./store/analytics-store.js";
31
- import { SegmentAnalyticsParams, endSegment, restartSegmentIfPlaying, startSegment } from "./lib/segment-analytics.js";
32
- import { ControlsState, controlsStore } from "./store/controls-store.js";
33
- import { HlsErrorAction, HlsErrorInput, HlsErrorPayload, HlsErrorRecoveryState, MAX_MEDIA_RECOVERIES, MAX_NETWORK_RETRIES, createHlsErrorRecoveryState, decideHlsErrorAction } from "./lib/hls-error-recovery.js";
34
- import { feedCacheAtom, feedCacheStore } from "./store/feed-cache-store.js";
35
- import { PostStoreState, postStore, postStoreActions } from "./store/postStore.js";
36
- import { FEED_COMPONENTS_COUNT, FEED_TRANSITION_THRESHOLD, feedStore, initializeVideo, setHasInteracted } from "./store/feed-interaction-store.js";
37
- import { playerContainerElementStore } from "./store/player-container-element-store.js";
38
- import { playerMediaElementStore } from "./store/player-media-element-store.js";
39
- import { CaptionLangType, SettingsState, VideoTheme } from "./store/settings/types.js";
40
- import { defaultSettings } from "./store/settings/defaults.js";
41
- import { COLORS, EDGE_STYLES, FONT_FAMILIES, FONT_SIZES, FontFamilyKey, LANG_TYPES, PLAYBACK_SPEEDS } from "./store/settings/constants.js";
42
- import { validateSettings } from "./store/settings/validation.js";
43
- import { loadSettings, saveSettings } from "./store/settings/storage.js";
44
- import { settingsStore } from "./store/settings/store.js";
45
- import { MenuKey, activeMenu, menuStack, navigationDirection, popMenu, pushMenu, resetMenu } from "./store/settings-menu-store.js";
46
- import { PlaybackPointerOptions, computePlaybackFillPercentage, computePlaybackValueFromPointer } from "./lib/playback-slider.js";
47
- import { PlayerMenuLabels, getPlayerMenuLabels } from "./lib/player-menu-labels.js";
48
- import { PlayerState, PlayerStateStore, playerStateStore } from "./store/player-store.js";
49
- import { hidePlayerControls, showPlayerControls, togglePlayerFullscreen, togglePlayerPictureInPicture } from "./lib/player-ui-actions.js";
50
- import { clearSubtitles, handleCueChange, handleLoadedMetadata } from "./lib/subtitle-utils.js";
51
- import { BufferRange, computeBufferRanges, computeBufferedAhead } from "./lib/buffer-progress.js";
52
- import { computeProgressFraction } from "./lib/progress-fraction.js";
53
- import { BuildVideoAnalyticsPayloadParams, VideoAnalyticsPayload, VideoSnapshot, buildVideoAnalyticsPayload, postContentEvent } from "./lib/content-analytics.js";
54
- import { analyticsContextStore, setAnalyticsContext } from "./store/analytics-context-store.js";
55
- import { analyticsDeviceStore, getOrCreateDeviceId, setDeviceId } from "./store/analytics-device-store.js";
56
- import { analyticsSessionStore, getOrCreateSessionId } from "./store/analytics-session-store.js";
57
- import { initializeAnalyticsContext } from "./lib/analytics-initialize.js";
58
- import { BOTTOM_OFFSET_CONTROLS_HIDDEN, BOTTOM_OFFSET_CONTROLS_VISIBLE, BOTTOM_SNAP_THRESHOLD, CAPTION_WIDTH_RATIO, CalculateDragPositionOptions, DEFAULT_CAPTION_FONT_SIZE, DEFAULT_FONT_SIZE, FONT_SIZE_RATIO, FONT_SIZE_VIEWPORT_RATIO, GetPointerOffsetsOptions, MAX_FONT_SIZE, MIN_FONT_SIZE, PointerOffsets, Position, SAFE_ZONE_MARGIN, Viewport, calculateDragPosition, calculateFontSize, calculateSafeViewport, constrainPercentagePosition, getPointerOffsets, getTextShadowValue, pixelsToPercentage, shouldPinToBottom } from "./lib/caption-utils.js";
59
- import { BuildEventParams, buildContentViewEvent, calculateWatchDuration, getEffectivePage, msToSeconds, roundMs, secondsToMs, shouldIncludeSegments } from "./lib/analytics-utils.js";
60
- import { ChapterWithEnd, calculateChaptersWithEnd, calculateFlexGrow, calculateGlobalMax, calculateHeatmapSlices, calculateSegmentBufferRanges, calculateSegmentProgress, findHoveredSegmentIndex, getCurrentPosition, getNextChapterStart, getPrevChapterTarget, isChapterWithinDuration, sliceHeatmapData, validateChapters } from "./lib/chapter-utils.js";
61
- import { SubtitleTrack, calculateSmoothedEndTime, extractSubtitleTracks, findNextCue, getCleanCueText, processCues, stripHtmlTags } from "./lib/subtitle-logic.js";
62
- import { FileData, FileStatus } from "./types/file.js";
63
- import { ImageData } from "./types/image.js";
64
- import { Chapter, VideoData } from "./types/video.js";
65
- import { flushAnalytics, postAnalytics, postEngagement, postError, postInteraction } from "./api/analytics.js";
66
- import { AnalyticsContext, AnalyticsEvent, ContentType, ContentViewEvent, EngagementEvent, ErrorEvent, InteractionEvent, Page, Segment, SessionStartEvent, ViewType } from "./types/analytics.js";
67
- import { BuildEngagementParams, BuildErrorParams, BuildInteractionParams, BuildSessionStartParams } from "./lib/analytics-builders.js";
68
- import { GetVideoHeatmapOptions, getVideoHeatmap } from "./api/heatmap.js";
69
- import { VideoHeatmap } from "./types/heatmap.js";
70
- import { GetHotSegmentsOptions, getHotSegments } from "./api/hot-segments.js";
71
- import { HotSegment } from "./types/hot-segments.js";
72
- import { CollectStatsInput, VideoStats, collectVideoStats, getBufferHealth, getDroppedFrames } from "./lib/video-stats.js";
73
- import { LOOP_REBASE_BASE_MULTIPLIER, LOOP_REBASE_THRESHOLD_MULTIPLIER, buildTransforms, calcShiftCountArray, shiftArray } from "./lib/feed-transforms.js";
74
- import { ShouldFetchMoreInput, computeScrollIndex, isAtEndOfFeed, isFeedExhausted, shouldFetchMore } from "./lib/feed-scroll.js";
75
- import { LoopRebaseInput, getLoopRebaseThreshold, getRebasedLoopIndex, resolvePostIndex, shouldRebaseLoopIndex } from "./lib/feed-loop.js";
76
- import { IMAGE_DWELL_MS, shouldDwellAdvance } from "./lib/feed-dwell.js";
77
- import { AutoAdvanceInput, gateVideoEnded, shouldAutoAdvance } from "./lib/feed-autoscroll.js";
78
- import { ContainerHeightInput, getViewportFallbackHeight, resolveContainerHeight } from "./lib/feed-container-height.js";
79
- import { checkIsCut } from "./lib/feed-description-overflow.js";
80
- import { AuthConfig, ConnectConfig, connect } from "./api/rixl-client.js";
81
- import { AudioTrackUploadItem, AudioTrackUploadResult, CreateImageUploadOptions, CreatePostUploadOptions, CreateVideoUploadOptions, ImageUploadResult, PostUploadResult, SubtitleUploadItem, SubtitleUploadResult, VideoUploadResult, createAudioTrackUpload, createImageUpload, createPostUpload, createSubtitleUpload, createVideoUpload, uploadImage, uploadPost, uploadVideo } from "./api/upload.js";
82
- export { type AnalyticsContext, type AnalyticsEvent, type AppliedVolumeSync, type AudioTrack, type AudioTrackUploadItem, type AudioTrackUploadResult, type AuthConfig, type AutoAdvanceInput, BOTTOM_OFFSET_CONTROLS_HIDDEN, BOTTOM_OFFSET_CONTROLS_VISIBLE, BOTTOM_SNAP_THRESHOLD, type BufferRange, type BuildEngagementParams, type BuildErrorParams, type BuildEventParams, type BuildInteractionParams, type BuildSessionStartParams, type BuildVideoAnalyticsPayloadParams, CAPTION_WIDTH_RATIO, COLORS, type CSSProperties, type CalculateDragPositionOptions, type CaptionLangType, type CaptionTextSettings, type CaptionWindowSettings, type Chapter, type ChapterWithEnd, type ClickDisambiguationState, type ClickOutsideOptions, type CollectStatsInput, type ConnectConfig, type ContainerHeightInput, type ContentType, type ContentViewEvent, type ControlsState, type CreateImageUploadOptions, type CreatePostUploadOptions, type CreateVideoUploadOptions, DEFAULT_CAPTION_FONT_SIZE, DEFAULT_FONT_SIZE, DEFAULT_IMAGE_ASPECT_RATIO, DOUBLE_CLICK_THRESHOLD_MS, type DeriveVolumeSyncOptions, EDGE_STYLES, type EngagementEvent, type ErrorEvent, FEED_COMPONENTS_COUNT, FEED_TRANSITION_THRESHOLD, FONT_FAMILIES, FONT_SIZES, FONT_SIZE_RATIO, FONT_SIZE_VIEWPORT_RATIO, type FeedPlaybackAction, type FeedPlaybackDecisionInput, type FeedPost, type FeedPostsResponse, type FileData, type FileStatus, type FontFamilyKey, type GetHotSegmentsOptions, type GetPointerOffsetsOptions, type GetVideoHeatmapOptions, type HandleClickOptions, type HandleDoubleClickOptions, type HlsController, type HlsErrorAction, type HlsErrorInput, type HlsErrorPayload, type HlsErrorRecoveryState, type HlsInstance, type HotSegment, IMAGE_ASPECT_RATIO_THRESHOLD, IMAGE_DWELL_MS, type ImageContainerStyleParams, type ImageData, type ImageRenderAction, type ImageRenderState, type ImageUploadResult, type InteractionEvent, LANG_TYPES, LOADING_SPINNER_DELAY_MS, LOOP_REBASE_BASE_MULTIPLIER, LOOP_REBASE_THRESHOLD_MULTIPLIER, type LoadingDebounceState, type LoopRebaseInput, MAX_FONT_SIZE, MAX_MEDIA_RECOVERIES, MAX_NETWORK_RETRIES, MIN_FONT_SIZE, type MenuKey, PERSIST_INTERVAL_MS, PLAYBACK_SPEEDS, PLAYER_LANGUAGES, PLAY_PAUSE_KEYS, PRELOAD_RANGE, type Page, type PipReentryOptions, type PlaybackHandlerCallbacks, type PlaybackPointerOptions, type PlayerControlLabels, type PlayerLanguage, type PlayerMenuLabels, type PlayerState, type PlayerStateStore, type PointerOffsets, type Position, type PostStoreState, type PostUploadResult, type PosterDimensions, type ProgressBarControls, type ProgressBarProps, type QualityLevel, RESUME_MIN_POSITION_SECONDS, RESUME_MIN_REMAINING_SECONDS, SAFE_ZONE_MARGIN, SEEK_LARGE_SECONDS, SEEK_SMALL_SECONDS, SHORTCUTS_CONFIG, SINGLE_CLICK_DELAY_MS, type Segment, type SegmentAnalyticsParams, type SessionStartEvent, type SettingsState, type SetupHlsOptions, ShortcutAction, type ShortcutAction as ShortcutActionType, type ShortcutDefinition, type ShouldFetchMoreInput, type SmartCaptionPositionParams, type SubtitleTrack, type SubtitleUploadItem, type SubtitleUploadResult, UNLOAD_DISTANCE, type UUID, type UpdateLoadingStateOptions, VOLUME_DELTA, type VideoAnalyticsPayload, type VideoData, type VideoHeatmap, type VideoKeyboardHandlers, VideoLoadState, type VideoPreloadAttribute, type VideoSdkKey, type VideoSnapshot, type VideoStats, type VideoTheme, type VideoUploadResult, type ViewType, type Viewport, activeMenu, analyticsContextStore, analyticsDeviceStore, analyticsSessionStore, analyticsStore, analyticsStoreActions, bindClickOutside, bindDocumentHidden, bindEndedListener, bindFullscreenChangeListener, bindPictureInPictureChangeListener, bindPipVisibilityReentry, bindPlaybackRateSync, buildContentViewEvent, buildTransforms, buildVideoAnalyticsPayload, calcShiftCountArray, calculateAspectRatio, calculateChaptersWithEnd, calculateDragPosition, calculateFlexGrow, calculateFontSize, calculateGlobalMax, calculateHeatmapSlices, calculateSafeViewport, calculateSegmentBufferRanges, calculateSegmentProgress, calculateSmoothedEndTime, calculateVolumeToSet, calculateWatchDuration, checkIsCut, clamp, clampVolume, cleanupClickDisambiguation, cleanupLoadingDebounce, clearSubtitles, collectVideoStats, computeBufferRanges, computeBufferedAhead, computePlaybackFillPercentage, computePlaybackValueFromPointer, computeProgressFraction, computeScrollIndex, connect, constrainPercentagePosition, controlsStore, createAudioTrackUpload, createClickDisambiguationState, createHlsConfig, createHlsErrorRecoveryState, createImageUpload, createLoadingDebounceState, createPostUpload, createSubtitleUpload, createVideoUpload, decideHlsErrorAction, defaultSettings, deriveVolumeSync, endSegment, executeShortcutAction, extractSubtitleTracks, feedCacheAtom, feedCacheStore, feedStore, findHoveredSegmentIndex, findNextCue, flushAnalytics, formatNumber, formatNumberSm, formatTime, gateVideoEnded, generateLevelName, getAspectRatioFromPoster, getBufferHealth, getCaptionTextStyle, getCaptionWindowStyle, getCleanCueText, getCurrentPosition, getDroppedFrames, getEffectivePage, getFeedPlaybackAction, getFeedPost, getFeedPosts, getHotSegments, getImage, getImageAspectRatio, getImageContainerStyle, getImageStyle, getLoopRebaseThreshold, getNextChapterStart, getOrCreateDeviceId, getOrCreateSessionId, getPersistedAudioTrack, getPersistedProgress, getPersistedSubtitleTrack, getPlayerControlLabels, getPlayerMenuLabels, getPointerClientX, getPointerOffsets, getPreloadAttribute, getPrevChapterTarget, getQualityLabel, getRebasedLoopIndex, getRestoredVolume, getSeekAmount, getSeekPercent, getSmartCaptionPosition, getTextShadowValue, getVideo, getVideoHeatmap, getVideoLoadState, getViewportFallbackHeight, getVolumeDelta, getVolumeFromPointer, handleClick, handleCueChange, handleDoubleClick, handleLoadedMetadata, handleVideoError, handleVideoPause, handleVideoPlay, handleVideoRateChange, hexToRGB, hexToRGBAString, hidePlayerControls, imageRenderReducer, initProgressBar, initialImageRenderState, initializeAnalyticsContext, initializeVideo, isAtEndOfFeed, isChapterWithinDuration, isClickOutside, isDocumentFullscreen, isEffectivelyMuted, isFeedExhausted, isHlsStream, isInsideExcludedElement, isVideoPictureInPicture, loadSettings, menuStack, msToSeconds, navigationDirection, observeViewport, persistAudioTrack, persistProgress, persistSubtitleTrack, pixelsToPercentage, playerContainerElementStore, playerMediaElementStore, playerStateStore, popMenu, postAnalytics, postContentEvent, postEngagement, postError, postInteraction, postStore, postStoreActions, processCues, pushMenu, resetMenu, resolveContainerHeight, resolvePlayerLanguage, resolvePostIndex, resolveShortcutAction, restartSegmentIfPlaying, roundMs, saveSettings, secondsToMs, setAnalyticsContext, setDeviceId, setHasInteracted, settingsStore, setupHls, shiftArray, shouldAutoAdvance, shouldBeMuted, shouldDwellAdvance, shouldFetchMore, shouldIgnoreKeyboardEvent, shouldIncludeSegments, shouldPersistProgress, shouldPinToBottom, shouldRebaseLoopIndex, shouldReenterPictureInPicture, shouldResumeFromPosition, shouldShowSpinner, showPlayerControls, sliceHeatmapData, sortLevelsByQuality, startSegment, stripHtmlTags, togglePictureInPicture, togglePlayerFullscreen, togglePlayerPictureInPicture, updateLoadingState, updatePlayerLoadingState, uploadImage, uploadPost, uploadVideo, validateChapters, validateSettings };
1
+ import { AuthConfig, ConnectConfig, client } from "@rixl/sdk";
2
+ import { MapStore, ReadableAtom, WritableAtom } from "nanostores";
3
+ import Hls, { MediaPlaylist } from "hls.js";
4
+ interface ProgressBarProps {
5
+ video: HTMLVideoElement;
6
+ onDraggingChange?: (isDragging: boolean) => void;
7
+ onProgressChange?: (progress: number) => void;
8
+ }
9
+ type ProgressBarCoordinates = {
10
+ clientX: number;
11
+ } | {
12
+ touches: ArrayLike<{
13
+ clientX: number;
14
+ }>;
15
+ changedTouches?: ArrayLike<{
16
+ clientX: number;
17
+ }>;
18
+ };
19
+ type ProgressBarStartEvent = ProgressBarCoordinates & {
20
+ currentTarget: EventTarget | null;
21
+ };
22
+ interface ProgressBarControls {
23
+ handleDragStart: (event: ProgressBarStartEvent) => void;
24
+ destroy: () => void;
25
+ }
26
+ export declare const initProgressBar: ({ video, onDraggingChange, onProgressChange }: ProgressBarProps) => ProgressBarControls;
27
+ type FileStatus = "uploading" | "uploaded" | "processing" | "ready" | "error";
28
+ interface FileData {
29
+ id: string;
30
+ project_id: string;
31
+ format: string;
32
+ url: string;
33
+ name: string;
34
+ size: number;
35
+ status: FileStatus;
36
+ created_at: Date;
37
+ updated_at: Date;
38
+ }
39
+ interface ImageData {
40
+ id: string;
41
+ thumbhash: string;
42
+ width: number;
43
+ height: number;
44
+ attached_to_video: boolean;
45
+ file: FileData;
46
+ }
47
+ interface Chapter {
48
+ title: string;
49
+ start_time_sec: number;
50
+ end_time_sec: number;
51
+ duration_label: string;
52
+ }
53
+ interface VideoData {
54
+ id: string;
55
+ file: FileData;
56
+ poster: ImageData;
57
+ duration: number;
58
+ width: number;
59
+ height: number;
60
+ codec: string;
61
+ bitrate: number;
62
+ framerate: string;
63
+ hdr: boolean;
64
+ chapters?: Chapter[];
65
+ plan_type?: "free" | "pro" | "pay-as-you-go" | "custom";
66
+ }
67
+ interface FeedPost {
68
+ id: string;
69
+ feedId: string;
70
+ creatorId: string;
71
+ type: "image" | "video";
72
+ description: string;
73
+ createdAt: string;
74
+ image?: ImageData;
75
+ video?: VideoData;
76
+ projectId?: string;
77
+ planType?: string;
78
+ updatedAt?: string;
79
+ }
80
+ interface FeedPostsResponse {
81
+ posts: FeedPost[];
82
+ total: number;
83
+ offset: number;
84
+ limit: number;
85
+ }
86
+ /**
87
+ * Get a feed post by ID, using cache if available
88
+ * @param feedId ID of the feed
89
+ * @param postId ID of the post to fetch
90
+ * @returns Promise with the feed post
91
+ */
92
+ export declare const getFeedPost: (feedId: string, postId: string) => Promise<FeedPost>;
93
+ /**
94
+ * Get posts from a specific feed, with pagination
95
+ * @param feedId ID of the feed
96
+ * @param offset Pagination offset
97
+ * @param limit Maximum number of items to return
98
+ * @returns Promise with feed posts response
99
+ */
100
+ export declare const getFeedPosts: (feedId: string, offset?: number, limit?: number) => Promise<FeedPostsResponse>;
101
+ export declare const getImage: (imageId: string) => Promise<ImageData>;
102
+ export declare const getVideo: (videoId: string) => Promise<VideoData>;
103
+ type UUID = `${string}-${string}-${string}-${string}-${string}`;
104
+ export declare const formatTime: (seconds: number) => string;
105
+ /**
106
+ * Returns a copy of `obj` with all `undefined` values removed.
107
+ * A type assertion is required because `Object.fromEntries` cannot infer
108
+ * `Partial<T>` from filtered entries.
109
+ */
110
+ export declare function filterUndefined<T extends Record<string, unknown>>(obj: T): Partial<T>;
111
+ /**
112
+ * Clamp a value between min and max bounds
113
+ */
114
+ export declare function clamp(value: number, min: number, max: number): number;
115
+ export declare function formatNumber(number: number): string;
116
+ export declare function formatNumberSm(number: number): string;
117
+ type CSSProperties = Record<string, string | number | null | undefined>;
118
+ interface ImageRenderState {
119
+ isLoading: boolean;
120
+ isVisible: boolean;
121
+ aspectRatio: number;
122
+ }
123
+ type ImageRenderAction = {
124
+ type: "reset";
125
+ aspectRatio?: number;
126
+ } | {
127
+ type: "loaded";
128
+ } | {
129
+ type: "visible";
130
+ } | {
131
+ type: "set_aspect_ratio";
132
+ aspectRatio: number;
133
+ };
134
+ export declare const DEFAULT_IMAGE_ASPECT_RATIO = .5;
135
+ export declare const IMAGE_ASPECT_RATIO_THRESHOLD = .7;
136
+ export declare const initialImageRenderState: ImageRenderState;
137
+ interface ImageContainerStyleParams {
138
+ aspectRatio: number;
139
+ isVisible: boolean;
140
+ thumbhashUrl?: string;
141
+ }
142
+ export declare function imageRenderReducer(state: ImageRenderState, action: ImageRenderAction): ImageRenderState;
143
+ export declare function getImageAspectRatio(width?: number, height?: number): number | undefined;
144
+ export declare function getImageContainerStyle({ aspectRatio, isVisible, thumbhashUrl }: ImageContainerStyleParams): CSSProperties;
145
+ export declare function getImageStyle(aspectRatio: number, isLoading: boolean): CSSProperties;
146
+ export declare function hexToRGB(hex: string): {
147
+ r: number;
148
+ g: number;
149
+ b: number;
150
+ };
151
+ export declare function hexToRGBAString(hex: string, alpha?: number): string;
152
+ /**
153
+ * Check if keyboard event should be ignored (input fields, textareas, etc.)
154
+ */
155
+ export declare function shouldIgnoreKeyboardEvent(target: EventTarget | null): boolean;
156
+ export declare const PLAYER_LANGUAGES: readonly ["en", "de", "es", "fr", "it", "pl", "ru", "tr", "uk"];
157
+ type PlayerLanguage = (typeof PLAYER_LANGUAGES)[number];
158
+ /**
159
+ * Control-bar strings for the player UI. Values mirror the `controls.*` and
160
+ * `captions.toggle` keys of packages/react/src/locales/<lang>.json — one
161
+ * label per button regardless of state, keyboard hint included, same as the
162
+ * React tooltips.
163
+ */
164
+ interface PlayerControlLabels {
165
+ play: string;
166
+ pause: string;
167
+ replay: string;
168
+ mute: string;
169
+ unmute: string;
170
+ volume: string;
171
+ settings: string;
172
+ pip: string;
173
+ fullScreen: string;
174
+ captionsToggle: string;
175
+ }
176
+ /** Same semantics as the React resolveSupportedLanguage: lowercase exact match, fallback en. */
177
+ export declare function resolvePlayerLanguage(code: string | null | undefined): PlayerLanguage;
178
+ export declare function getPlayerControlLabels(code: string | null | undefined): PlayerControlLabels;
179
+ /**
180
+ * Media SDK video keyboard shortcuts configuration
181
+ */
182
+ type VideoSdkKey = "Space" | "KeyK" | "KeyJ" | "KeyL" | "KeyI" | "KeyF" | "KeyM" | "KeyN" | "KeyP" | "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "MediaPlay" | "MediaPause" | "MediaPlayPause" | "F1" | "F12" | "Digit0" | "Digit1" | "Digit2" | "Digit3" | "Digit4" | "Digit5" | "Digit6" | "Digit7" | "Digit8" | "Digit9";
183
+ export declare const ShortcutAction: {
184
+ readonly PLAY_PAUSE: "play_pause";
185
+ readonly SEEK_10: "seek_10";
186
+ readonly SEEK_5: "seek_5";
187
+ readonly FULLSCREEN: "fullscreen";
188
+ readonly MINIPLAYER: "miniplayer";
189
+ readonly MUTE: "mute";
190
+ readonly VOLUME: "volume";
191
+ };
192
+ export type ShortcutAction = (typeof ShortcutAction)[keyof typeof ShortcutAction];
193
+ interface ShortcutDefinition {
194
+ action: ShortcutAction;
195
+ keys: VideoSdkKey[];
196
+ labelKey: string;
197
+ }
198
+ /**
199
+ * Default keyboard shortcuts configuration
200
+ */
201
+ export declare const SHORTCUTS_CONFIG: ShortcutDefinition[];
202
+ /**
203
+ * Seek amounts in seconds
204
+ */
205
+ export declare const SEEK_SMALL_SECONDS = 5;
206
+ export declare const SEEK_LARGE_SECONDS = 10;
207
+ /**
208
+ * Volume change delta (0-1 range)
209
+ */
210
+ export declare const VOLUME_DELTA = .1;
211
+ interface VideoKeyboardHandlers {
212
+ onPlayPause: () => void;
213
+ onSeek: (seconds: number) => void;
214
+ onFullscreen: () => void;
215
+ onMiniplayer: () => void;
216
+ onMute: () => void;
217
+ onVolume: (delta: number) => void;
218
+ }
219
+ /**
220
+ * Get seek amount for a keyboard event
221
+ * @returns number of seconds to seek (positive = forward, negative = backward)
222
+ */
223
+ export declare function getSeekAmount(keyCode: string, action: ShortcutAction): number;
224
+ /**
225
+ * Get volume delta for a keyboard event
226
+ * @returns volume change amount (positive = increase, negative = decrease)
227
+ */
228
+ export declare function getVolumeDelta(keyCode: string): number;
229
+ /**
230
+ * Execute keyboard shortcut action
231
+ */
232
+ export declare function executeShortcutAction(action: ShortcutAction, keyCode: string, handlers: VideoKeyboardHandlers): void;
233
+ /**
234
+ * Full play/pause key set including media keys — mirrors React's
235
+ * component-level PlayPauseShortcuts, which extends SHORTCUTS_CONFIG.
236
+ */
237
+ export declare const PLAY_PAUSE_KEYS: VideoSdkKey[];
238
+ /** Resolve a KeyboardEvent.code to its shortcut action, or null when unmapped. */
239
+ export declare function resolveShortcutAction(keyCode: string): ShortcutAction | null;
240
+ /**
241
+ * Digit0–Digit9 → 0–90 percent seek targets — mirrors React's
242
+ * PercentageShortcuts table.
243
+ */
244
+ export declare function getSeekPercent(keyCode: string): number | null;
245
+ /**
246
+ * Volume and mute utility functions
247
+ * Pure functions for volume calculations and mute state logic
248
+ */
249
+ /**
250
+ * Calculate the volume to set, ensuring it's never 0 when unmuting
251
+ * @param currentVolume - The current volume from settings (0-1)
252
+ * @param defaultVolume - The default volume to use if current is 0 (default: 1.0)
253
+ * @returns The volume to set (0-1)
254
+ */
255
+ export declare function calculateVolumeToSet(currentVolume: number, defaultVolume?: number): number;
256
+ /**
257
+ * Determine if video should be muted based on player state and interaction state
258
+ * @param playerMuted - Whether the current player is muted
259
+ * @param isFeed - Whether this is a feed video
260
+ * @param feedInteracted - Whether user has interacted with the feed
261
+ * @param playerInteracted - Whether user has interacted with the player
262
+ * @returns Whether the video should be muted
263
+ */
264
+ interface MuteCheckParams {
265
+ playerMuted: boolean;
266
+ playerInteracted: boolean;
267
+ }
268
+ export declare function shouldBeMuted({ playerMuted, playerInteracted }: MuteCheckParams): boolean;
269
+ /**
270
+ * Get the volume to restore when unmuting, with a minimum threshold
271
+ * @param currentVolume - The current volume (0-1)
272
+ * @param previousVolume - The previously saved volume before muting (0-1)
273
+ * @param minVolume - The minimum volume to restore to (default: 0.1)
274
+ * @returns The volume to restore (0-1)
275
+ */
276
+ export declare function getRestoredVolume(currentVolume: number, previousVolume: number, minVolume?: number): number;
277
+ /**
278
+ * Clamp volume to valid range (0-1)
279
+ * @param volume - The volume to clamp
280
+ * @returns Volume clamped to 0-1 range
281
+ */
282
+ export declare function clampVolume(volume: number): number;
283
+ /**
284
+ * Check if volume is effectively muted (0 or very close to 0)
285
+ * @param volume - The volume to check
286
+ * @param threshold - The threshold below which volume is considered muted (default: 0.01)
287
+ * @returns Whether volume is effectively muted
288
+ */
289
+ export declare function isEffectivelyMuted(volume: number, threshold?: number): boolean;
290
+ interface MousePointerLike {
291
+ clientX: number;
292
+ }
293
+ interface TouchPointerLike {
294
+ touches: ArrayLike<MousePointerLike>;
295
+ }
296
+ /** clientX of a mouse or touch event (first touch) — shared by the volume sliders. */
297
+ export declare function getPointerClientX(event: MousePointerLike | TouchPointerLike): number;
298
+ /** Map a pointer position over a slider rect to a clamped 0-1 volume. */
299
+ export declare function getVolumeFromPointer(rect: {
300
+ left: number;
301
+ width: number;
302
+ }, clientX: number): number;
303
+ type Viewport = {
304
+ width: number;
305
+ height: number;
306
+ };
307
+ interface Position {
308
+ x: number;
309
+ y: number;
310
+ }
311
+ export declare const DEFAULT_FONT_SIZE = 16;
312
+ export declare const MIN_FONT_SIZE = 12;
313
+ export declare const MAX_FONT_SIZE = 120;
314
+ export declare const FONT_SIZE_RATIO = .03;
315
+ export declare const FONT_SIZE_VIEWPORT_RATIO = .07;
316
+ export declare const DEFAULT_CAPTION_FONT_SIZE = 100;
317
+ export declare const SAFE_ZONE_MARGIN = 8;
318
+ export declare const CAPTION_WIDTH_RATIO = .6;
319
+ /**
320
+ * Smart caption positioning constants
321
+ */
322
+ export declare const BOTTOM_SNAP_THRESHOLD = 85;
323
+ export declare const BOTTOM_OFFSET_CONTROLS_VISIBLE = 80;
324
+ export declare const BOTTOM_OFFSET_CONTROLS_HIDDEN = 24;
325
+ /**
326
+ * Calculates the font size based on the viewport width and user preference.
327
+ * Uses a logarithmic scale
328
+ * 100% -> 1.0x
329
+ * 200% -> 1.5x
330
+ * 400% -> 2.0x
331
+ */
332
+ export declare const calculateFontSize: (viewport: Viewport, captionFontSize: number) => number;
333
+ /**
334
+ * Constrains a percentage-based position to be within safe bounds (0-100).
335
+ * Assumes the input position is already in percentages.
336
+ */
337
+ export declare const constrainPercentagePosition: (position: Position, elementWidthRatio?: number) => Position;
338
+ /**
339
+ * Converts pixel coordinates to percentage coordinates relative to the viewport.
340
+ */
341
+ export declare const pixelsToPercentage: (x: number, y: number, viewport: Viewport) => Position;
342
+ /**
343
+ * Calculate pointer offsets for caption dragging
344
+ */
345
+ interface PointerOffsets {
346
+ clickXRelative: number;
347
+ clickYRelative: number;
348
+ currentVisualX: number;
349
+ currentVisualY: number;
350
+ }
351
+ interface GetPointerOffsetsOptions {
352
+ containerRect: DOMRect;
353
+ elementRect: DOMRect;
354
+ clientX: number;
355
+ clientY: number;
356
+ }
357
+ export declare function getPointerOffsets(options: GetPointerOffsetsOptions): PointerOffsets;
358
+ /**
359
+ * Calculate new drag position from delta
360
+ */
361
+ interface CalculateDragPositionOptions {
362
+ startPositionPixels: Position;
363
+ startX: number;
364
+ startY: number;
365
+ currentXRelative: number;
366
+ currentYRelative: number;
367
+ viewport: Viewport;
368
+ }
369
+ export declare function calculateDragPosition(options: CalculateDragPositionOptions): Position;
370
+ /**
371
+ * Calculate safe zone viewport dimensions
372
+ */
373
+ export declare function calculateSafeViewport(viewport: Viewport): Viewport;
374
+ /**
375
+ * Determine if caption should be pinned to bottom
376
+ */
377
+ export declare function shouldPinToBottom(positionY: number, isDragging: boolean): boolean;
378
+ /**
379
+ * CSS text-shadow value for a caption character edge style.
380
+ * Shadow size scales with font size so edges stay proportional.
381
+ */
382
+ export declare function getTextShadowValue(edgeStyle: string, fontSize: number): string;
383
+ type VideoTheme = "default" | "minimal" | "feed" | "hover" | "hideUI";
384
+ type CaptionLangType = "off" | "eng" | "auto";
385
+ interface SettingsState {
386
+ volume: number;
387
+ playbackSpeed: number;
388
+ customPlayback: number;
389
+ allowCaptions: boolean;
390
+ captionPosition: {
391
+ x: number;
392
+ y: number;
393
+ };
394
+ captionLang: CaptionLangType;
395
+ captionFontFamily: string;
396
+ captionFontSize: number;
397
+ captionFontColor: string;
398
+ captionFontOpacity: number;
399
+ captionBGColor: string;
400
+ captionBGOpacity: number;
401
+ captionWindowColor: string;
402
+ captionWindowOpacity: number;
403
+ captionCharacterEdgeStyle: string;
404
+ selectedLanguageCode?: string;
405
+ globalMutedPreference: boolean;
406
+ preferredQuality?: number;
407
+ preferredAudioLanguage?: string;
408
+ preferredSubtitleLanguage?: string;
409
+ }
410
+ interface SmartCaptionPositionParams {
411
+ position: Position;
412
+ isDragging: boolean;
413
+ controlsVisible: boolean;
414
+ }
415
+ /**
416
+ * Caption window placement: percent-based within the safe zone, snapping to
417
+ * the bottom (above the controls bar when visible) once dragged past the
418
+ * snap threshold. Single source for the React hook and the Lit overlay.
419
+ */
420
+ export declare function getSmartCaptionPosition({ position, isDragging, controlsVisible }: SmartCaptionPositionParams): CSSProperties;
421
+ type CaptionWindowSettings = Pick<SettingsState, "captionWindowColor" | "captionWindowOpacity">;
422
+ /** Caption window box: width from the safe viewport, settings-driven background, drag cursor. */
423
+ export declare function getCaptionWindowStyle(settings: CaptionWindowSettings, safeViewportWidth: number, isDragging: boolean): CSSProperties;
424
+ type CaptionTextSettings = Pick<SettingsState, "captionFontFamily" | "captionFontColor" | "captionFontOpacity" | "captionBGColor" | "captionBGOpacity" | "captionCharacterEdgeStyle">;
425
+ /** Caption text styling from the user's caption settings (font, colors, edge-style shadow). */
426
+ export declare function getCaptionTextStyle(settings: CaptionTextSettings, fontSize: number): CSSProperties;
427
+ export declare function isDocumentFullscreen(): boolean;
428
+ /**
429
+ * Utility functions for Picture-in-Picture logic
430
+ */
431
+ /**
432
+ * Check if a video element is currently in Picture-in-Picture mode.
433
+ *
434
+ * Browsers disagree for a video inside shadow DOM: by the spec,
435
+ * `document.pictureInPictureElement` is retargeted to the shadow host and the
436
+ * owning ShadowRoot reports the video, but Chromium reports the video on the
437
+ * document and nothing on the ShadowRoot. Either match counts.
438
+ */
439
+ export declare function isVideoPictureInPicture(video: HTMLVideoElement | null): boolean;
440
+ /**
441
+ * Helper to toggle PIP mode safely
442
+ */
443
+ export declare function togglePictureInPicture(video: HTMLVideoElement | null): Promise<void>;
444
+ /**
445
+ * Minimum position in seconds to resume from (skip if too close to start)
446
+ */
447
+ export declare const RESUME_MIN_POSITION_SECONDS = 5;
448
+ /**
449
+ * Minimum remaining duration in seconds to resume (skip if too close to end)
450
+ */
451
+ export declare const RESUME_MIN_REMAINING_SECONDS = 5;
452
+ /**
453
+ * Interval in milliseconds between progress persistence operations
454
+ */
455
+ export declare const PERSIST_INTERVAL_MS = 2e3;
456
+ export declare const getPersistedProgress: (videoId: string) => number;
457
+ export declare const persistProgress: (videoId: string, positionMs: number) => void;
458
+ /**
459
+ * Determine if a saved progress position should be used to resume playback
460
+ * @param savedPositionSeconds - The saved position in seconds
461
+ * @param durationSeconds - The total video duration in seconds
462
+ * @returns true if position is valid for resuming (not too close to start or end)
463
+ */
464
+ export declare function shouldResumeFromPosition(savedPositionSeconds: number, durationSeconds: number): boolean;
465
+ /**
466
+ * Determine if enough time has elapsed to persist progress again
467
+ * @param lastPersistTime - Timestamp of last persist operation (from performance.now())
468
+ * @param currentTime - Current timestamp (from performance.now())
469
+ * @returns true if interval has elapsed
470
+ */
471
+ export declare function shouldPersistProgress(lastPersistTime: number, currentTime: number): boolean;
472
+ /**
473
+ * PRELOAD_RANGE determines how many videos around the current one should be loaded
474
+ *
475
+ * Example with BEFORE: 1, AFTER: 2, current index is 5:
476
+ *
477
+ * Legend:
478
+ * PRELOADING (buffering in background)
479
+ * PLAYING (currently visible)
480
+ * IDLE (exists but not loaded)
481
+ * UNLOADED (too far, save memory)
482
+ */
483
+ export declare const PRELOAD_RANGE: {
484
+ BEFORE: number;
485
+ AFTER: number;
486
+ };
487
+ /**
488
+ * UNLOAD_DISTANCE determines when to unload videos to free memory
489
+ * If a video is more than this distance from current, unload it
490
+ */
491
+ export declare const UNLOAD_DISTANCE = 5;
492
+ /**
493
+ * Video loading states
494
+ */
495
+ export declare const VideoLoadState: {
496
+ readonly UNLOADED: "unloaded";
497
+ readonly IDLE: "idle";
498
+ readonly PRELOADING: "preloading";
499
+ readonly PLAYING: "playing";
500
+ };
501
+ export type VideoLoadState = (typeof VideoLoadState)[keyof typeof VideoLoadState];
502
+ /**
503
+ * Calculate what state a video should be in based on its distance from current
504
+ */
505
+ export declare function getVideoLoadState(videoIndex: number, currentIndex: number, isCurrent: boolean): VideoLoadState;
506
+ /**
507
+ * Delay in milliseconds before showing the loading spinner
508
+ * This prevents flash-of-spinner for brief buffering moments
509
+ */
510
+ export declare const LOADING_SPINNER_DELAY_MS = 300;
511
+ interface LoadingDebounceState {
512
+ timerId: ReturnType<typeof setTimeout> | null;
513
+ }
514
+ interface UpdateLoadingStateOptions {
515
+ state: LoadingDebounceState;
516
+ shouldShow: boolean;
517
+ onShow: () => void;
518
+ onHide: () => void;
519
+ }
520
+ /**
521
+ * Create initial loading debounce state
522
+ */
523
+ export declare function createLoadingDebounceState(): LoadingDebounceState;
524
+ /**
525
+ * Update loading state with debounce
526
+ */
527
+ export declare function updateLoadingState(options: UpdateLoadingStateOptions): void;
528
+ /**
529
+ * Clean up loading debounce state (clear any pending timers)
530
+ */
531
+ export declare function cleanupLoadingDebounce(state: LoadingDebounceState): void;
532
+ /**
533
+ * Calculate aspect ratio from video element dimensions
534
+ * @returns aspect ratio (width/height) or undefined if dimensions not available
535
+ */
536
+ export declare function calculateAspectRatio(videoElement: HTMLVideoElement | null, videoData: VideoData | undefined): number | undefined;
537
+ interface PlaybackHandlerCallbacks {
538
+ onSegmentStart: () => void;
539
+ onSegmentEnd: () => void;
540
+ onRestartSegment: (isPaused?: boolean) => void;
541
+ onShowSpinner: (show: boolean) => void;
542
+ }
543
+ /**
544
+ * Handle video play event
545
+ */
546
+ export declare function handleVideoPlay(playerId: UUID, callbacks: Pick<PlaybackHandlerCallbacks, "onSegmentStart">): void;
547
+ /**
548
+ * Handle video pause event
549
+ */
550
+ export declare function handleVideoPause(playerId: UUID, callbacks: Pick<PlaybackHandlerCallbacks, "onSegmentEnd">): void;
551
+ /**
552
+ * Handle video rate change event
553
+ */
554
+ export declare function handleVideoRateChange(playerId: UUID, videoElement: HTMLVideoElement | null, callbacks: Pick<PlaybackHandlerCallbacks, "onRestartSegment">): void;
555
+ /**
556
+ * Handle video error event
557
+ */
558
+ export declare function handleVideoError(playerId: UUID, callbacks: Pick<PlaybackHandlerCallbacks, "onShowSpinner">): void;
559
+ /**
560
+ * Update player loading state in store
561
+ */
562
+ export declare function updatePlayerLoadingState(playerId: UUID, isLoading: boolean): void;
563
+ /**
564
+ * Delay in milliseconds for single-click detection
565
+ * Used to distinguish between single click (toggle play) and double click (fullscreen)
566
+ */
567
+ export declare const SINGLE_CLICK_DELAY_MS = 250;
568
+ /**
569
+ * Maximum time between clicks to be considered a double-click
570
+ */
571
+ export declare const DOUBLE_CLICK_THRESHOLD_MS = 400;
572
+ interface ClickDisambiguationState {
573
+ singleClickTimerId: ReturnType<typeof setTimeout> | null;
574
+ lastClickTime: number;
575
+ }
576
+ /**
577
+ * Create initial click disambiguation state
578
+ */
579
+ export declare function createClickDisambiguationState(): ClickDisambiguationState;
580
+ interface HandleClickOptions {
581
+ state: ClickDisambiguationState;
582
+ hideUI: boolean;
583
+ allowFullscreen: boolean;
584
+ isExcludedTarget: boolean;
585
+ onTogglePlay: () => void;
586
+ }
587
+ /**
588
+ * Handle a click event with disambiguation logic
589
+ * Returns true if the click was handled, false if ignored
590
+ */
591
+ export declare function handleClick(options: HandleClickOptions): boolean;
592
+ interface HandleDoubleClickOptions {
593
+ state: ClickDisambiguationState;
594
+ allowFullscreen: boolean;
595
+ isExcludedTarget: boolean;
596
+ onToggleFullscreen: () => void;
597
+ }
598
+ /**
599
+ * Handle a double-click event
600
+ * Returns true if the double-click was handled, false if ignored
601
+ */
602
+ export declare function handleDoubleClick(options: HandleDoubleClickOptions): boolean;
603
+ /**
604
+ * Clean up click disambiguation state (clear any pending timers)
605
+ */
606
+ export declare function cleanupClickDisambiguation(state: ClickDisambiguationState): void;
607
+ /**
608
+ * Pure helpers for video-element environment effects.
609
+ *
610
+ * "Environment effects" = things the player has to keep in sync with the
611
+ * surrounding document/window: fullscreen state, picture-in-picture state,
612
+ * tab visibility, viewport size, and the volume/mute state derived from
613
+ * player + user-interaction inputs.
614
+ *
615
+ * Everything in this module is framework-agnostic. React/Lit/Vue wrappers
616
+ * supply the DOM listeners and the store-update callbacks; this module
617
+ * supplies the predicates, the state derivations, and the listener factories.
618
+ */
619
+ /**
620
+ * Bind the `document` `fullscreenchange` event to a callback that receives the
621
+ * current fullscreen state.
622
+ *
623
+ * Returns a teardown function that removes the listener.
624
+ */
625
+ export declare function bindFullscreenChangeListener(onChange: (isFullscreen: boolean) => void): () => void;
626
+ /**
627
+ * Bind `enterpictureinpicture` and `leavepictureinpicture` events on a
628
+ * video element to a callback that receives the current PiP state.
629
+ *
630
+ * Returns a teardown function.
631
+ */
632
+ export declare function bindPictureInPictureChangeListener(videoElement: HTMLVideoElement | null, onChange: (isPip: boolean) => void): () => void;
633
+ interface PipReentryOptions {
634
+ videoElement: HTMLVideoElement | null;
635
+ isCurrentlyInPip: boolean;
636
+ }
637
+ /**
638
+ * Decide whether to re-request PiP when the document becomes hidden.
639
+ *
640
+ * Returns `true` when the caller should re-enter PiP on the supplied
641
+ * video element. The actual `requestPictureInPicture()` call is left to the
642
+ * caller (since it returns a promise and the caller chooses how to handle
643
+ * errors).
644
+ */
645
+ export declare function shouldReenterPictureInPicture({ videoElement, isCurrentlyInPip }: PipReentryOptions): boolean;
646
+ /**
647
+ * Bind a `visibilitychange` handler that re-enters PiP whenever the document
648
+ * becomes hidden and the player believes itself to be in PiP but the browser
649
+ * has dropped out.
650
+ *
651
+ * Returns a teardown function.
652
+ */
653
+ export declare function bindPipVisibilityReentry(getOptions: () => PipReentryOptions, onError?: (error: unknown) => void): () => void;
654
+ interface AppliedVolumeSync {
655
+ /** The `muted` value that should be assigned to the video element. */
656
+ muted: boolean;
657
+ /** The `volume` value that should be assigned, or `null` if not changing. */
658
+ volume: number | null;
659
+ /** When non-null, the store's current `volume` should be updated to this value. */
660
+ storeVolumeUpdate: number | null;
661
+ }
662
+ interface DeriveVolumeSyncOptions {
663
+ /** Hard mute applied by the consumer (e.g. theme override). */
664
+ forcedMuted: boolean;
665
+ /** The player's persisted `muted` state. */
666
+ playerMuted: boolean;
667
+ /** Whether the user has interacted with the player yet. */
668
+ playerInteracted: boolean;
669
+ /** The player's persisted `volume`. */
670
+ playerVolume: number;
671
+ /** The player's persisted `previousVolume` (used to restore on unmute). */
672
+ playerPreviousVolume: number;
673
+ }
674
+ /**
675
+ * Pure derivation of the values that should be written to the video element
676
+ * (and back to the store) given the current player state.
677
+ *
678
+ * Mirrors the behaviour previously implemented inside `useVolumeEffect`:
679
+ *
680
+ * 1. When the caller forces mute, nothing else is touched.
681
+ * 2. Otherwise, `shouldBeMuted` decides the effective mute state.
682
+ * 3. When unmuted, `getRestoredVolume` resolves the volume to assign, and the
683
+ * store is updated only when the current persisted volume is `0`.
684
+ */
685
+ export declare function deriveVolumeSync({ forcedMuted, playerMuted, playerInteracted, playerVolume, playerPreviousVolume }: DeriveVolumeSyncOptions): AppliedVolumeSync | null;
686
+ /**
687
+ * Observe a container element's viewport size, invoking the callback with the
688
+ * current `{width, height}` whenever it changes (via `ResizeObserver`) or
689
+ * the window resizes.
690
+ *
691
+ * Returns a teardown function.
692
+ */
693
+ export declare function observeViewport(container: HTMLElement | null, onChange: (viewport: Viewport) => void): () => void;
694
+ /**
695
+ * Pure helpers and DOM-listener factories for player lifecycle effects:
696
+ * playback rate sync, ended handling, preload state machine, reset-on-data
697
+ * derivations, and feed playback gating.
698
+ *
699
+ * Framework-agnostic. React/Lit/Vue wrappers supply the store-update callbacks;
700
+ * this module supplies the predicates, derivations, and listener factories.
701
+ */
702
+ /** Valid values for `<video preload>`. */
703
+ type VideoPreloadAttribute = "auto" | "metadata" | "none";
704
+ /**
705
+ * Map a feed virtualization `VideoLoadState` to the appropriate
706
+ * `<video preload>` attribute value.
707
+ *
708
+ * - UNLOADED → "none" (slot is far from viewport; don't fetch anything)
709
+ * - IDLE → "metadata" (slot is reachable but not active; fetch headers only)
710
+ * - PRELOADING / PLAYING → "auto" (slot is active or about to be; fetch segments)
711
+ */
712
+ export declare function getPreloadAttribute(loadState: VideoLoadState): VideoPreloadAttribute;
713
+ /**
714
+ * Bind a `loadeddata` listener that re-applies the playback rate after the
715
+ * browser resets it (most browsers reset `playbackRate` to `1.0` on each
716
+ * `<source>` change).
717
+ *
718
+ * Also writes the rate immediately so that callers don't have to do so
719
+ * separately. Returns a teardown function.
720
+ */
721
+ export declare function bindPlaybackRateSync(videoElement: HTMLVideoElement | null, playbackRate: number): () => void;
722
+ /**
723
+ * Bind an `ended` listener that invokes `onEnded()` exactly once per native
724
+ * `ended` event. Returns a teardown function.
725
+ */
726
+ export declare function bindEndedListener(videoElement: HTMLVideoElement | null, onEnded: () => void): () => void;
727
+ interface PosterDimensions {
728
+ width?: number;
729
+ height?: number;
730
+ }
731
+ /**
732
+ * Compute the aspect ratio (width / height) from poster dimensions, returning
733
+ * `null` when either dimension is missing or zero.
734
+ *
735
+ * Mirrors the conditional in `useResetOnDataChangeEffect`:
736
+ *
737
+ * if (videoData?.poster?.width && videoData?.poster?.height) {
738
+ * setAspectRatio(videoData.poster.width / videoData.poster.height);
739
+ * }
740
+ */
741
+ export declare function getAspectRatioFromPoster(poster: PosterDimensions | undefined): number | null;
742
+ interface FeedPlaybackDecisionInput {
743
+ isFeed: boolean;
744
+ isCurrent: boolean;
745
+ loadState: VideoLoadState;
746
+ showSpinner: boolean;
747
+ videoReadyState: number;
748
+ }
749
+ type FeedPlaybackAction = "play" | "pause" | "none";
750
+ /**
751
+ * Decide what a feed-virtualized player should do given the current slot state.
752
+ *
753
+ * - In a non-feed context, returns "none" (caller handles its own playback).
754
+ * - If the slot is not current, returns "pause" so the off-screen player stops.
755
+ * - If the slot is current, in PLAYING load state, not spinning, and the video
756
+ * has enough data (readyState >= 2), returns "play".
757
+ * - Otherwise returns "none" (still loading / preloading; wait).
758
+ */
759
+ export declare function getFeedPlaybackAction({ isFeed, isCurrent, loadState, showSpinner, videoReadyState }: FeedPlaybackDecisionInput): FeedPlaybackAction;
760
+ /**
761
+ * Generic "click outside" detection with an optional exclusion attribute.
762
+ *
763
+ * Use case: a settings menu that should close when the user clicks outside it,
764
+ * but NOT when the user clicks the button that opens it (otherwise the button
765
+ * both opens and immediately closes the menu in the same pointer cycle).
766
+ *
767
+ * Pure, DOM-only, framework-agnostic. React/Lit/Vue wrappers call
768
+ * `bindClickOutside` from their lifecycle hooks.
769
+ */
770
+ interface ClickOutsideOptions {
771
+ /**
772
+ * Function that returns the "inside" element. Called on every pointer event,
773
+ * so the caller can pass a ref-like getter that may be null until the
774
+ * referenced element is mounted.
775
+ */
776
+ getContainer: () => HTMLElement | null;
777
+ /**
778
+ * Optional attribute name (e.g. `"data-settings-button"`). Any pointer event
779
+ * whose target is inside an element carrying this attribute is treated as
780
+ * "inside" and does NOT trigger `onOutsideClick`.
781
+ *
782
+ * This is what lets the button that toggles the menu coexist with a
783
+ * close-on-outside-click listener: the button's own clicks are ignored here,
784
+ * letting the button's own onClick decide whether to toggle.
785
+ */
786
+ excludeAttribute?: string;
787
+ /**
788
+ * Invoked when a pointer event lands outside both the container and (if
789
+ * configured) any element carrying `excludeAttribute`.
790
+ */
791
+ onOutsideClick: (event: MouseEvent) => void;
792
+ }
793
+ /**
794
+ * Returns `true` when the given event target is inside an element carrying
795
+ * the supplied attribute. When `attribute` is undefined, always returns false.
796
+ */
797
+ export declare function isInsideExcludedElement(target: EventTarget | null, attribute: string | undefined): boolean;
798
+ /**
799
+ * Returns `true` when the event lands outside both the container and any
800
+ * excluded element.
801
+ *
802
+ * Checks the composed path as well as the plain target: document-level
803
+ * listeners see shadow-DOM events retargeted to the host, and
804
+ * `document.querySelector` cannot see into shadow roots — the composed path
805
+ * is the only reliable record of where the click really landed.
806
+ */
807
+ export declare function isClickOutside(event: MouseEvent, container: HTMLElement | null, excludeAttribute: string | undefined): boolean;
808
+ /**
809
+ * Bind a `mousedown` listener on the document that invokes `onOutsideClick`
810
+ * whenever the event lands outside the container and outside any element
811
+ * carrying `excludeAttribute`.
812
+ *
813
+ * Returns a teardown function that removes the listener.
814
+ *
815
+ * The container is looked up via `getContainer()` on every event so the caller
816
+ * can wire it to a ref that may be null at bind time.
817
+ */
818
+ export declare function bindClickOutside({ getContainer, excludeAttribute, onOutsideClick }: ClickOutsideOptions): () => void;
819
+ /**
820
+ * Bind a `visibilitychange` listener that fires `onHidden` when the document
821
+ * is hidden. Returns a teardown function.
822
+ *
823
+ * Settings menus use this to close themselves when the user tabs away.
824
+ * Lives next to `bindClickOutside` because the two are almost always wired
825
+ * together for "dismissible overlay" behaviour.
826
+ */
827
+ export declare function bindDocumentHidden(onHidden: () => void): () => void;
828
+ /**
829
+ * Live "is the player buffering right now?" predicate.
830
+ *
831
+ * Different from `video-preload-config.ts` despite the similar name:
832
+ * - `video-preload-config.ts` decides the `<video preload>` attribute for
833
+ * a slot in the feed virtualization (one-time decision per slot).
834
+ * - `shouldShowSpinner` is called continuously during playback to decide
835
+ * whether the buffering spinner should currently be visible.
836
+ *
837
+ * Inputs come from a live `<HTMLVideoElement>`. The function is otherwise
838
+ * pure and framework-agnostic.
839
+ */
840
+ /**
841
+ * Decide whether the buffering spinner should be visible for the given
842
+ * video element.
843
+ *
844
+ * Logic, in order:
845
+ * 1. No video → never show.
846
+ * 2. Playing past the start → if the current time falls inside any buffered
847
+ * range, the player has the bytes it needs; never show.
848
+ * 3. Otherwise fall back to `readyState`/`seeking`: show when the browser
849
+ * reports `HAVE_CURRENT_DATA` (2) or is actively seeking with
850
+ * `readyState < 3` (HAVE_FUTURE_DATA).
851
+ */
852
+ export declare function shouldShowSpinner(video: HTMLVideoElement | null): boolean;
853
+ interface QualityLevel {
854
+ height: number;
855
+ width: number;
856
+ bitrate: number;
857
+ name: string;
858
+ index: number;
859
+ }
860
+ interface AudioTrack {
861
+ index: number;
862
+ label: string;
863
+ language: string;
864
+ kind: string;
865
+ /** The raw Hls.js MediaPlaylist object for this audio track. */
866
+ track: MediaPlaylist;
867
+ }
868
+ export declare const sortLevelsByQuality: (levels: QualityLevel[]) => QualityLevel[];
869
+ export declare const isHlsStream: (url: string) => boolean;
870
+ export declare const generateLevelName: (level: {
871
+ height: number;
872
+ width: number;
873
+ bitrate: number;
874
+ }) => string;
875
+ interface QualityLabelParams {
876
+ resolution: number;
877
+ levels: QualityLevel[];
878
+ currentLevel: number;
879
+ autoText: string;
880
+ }
881
+ export declare const getQualityLabel: ({ resolution, levels, currentLevel, autoText }: QualityLabelParams) => string;
882
+ export declare const MAX_NETWORK_RETRIES = 3;
883
+ export declare const MAX_MEDIA_RECOVERIES = 1;
884
+ interface HlsErrorPayload {
885
+ /** The hls.js error type, e.g. `"networkError"`, `"mediaError"`. */
886
+ error: string;
887
+ /** Specific hls.js error details (e.g. `"manifestLoadError"`) or undefined. */
888
+ code?: string;
889
+ }
890
+ interface HlsErrorRecoveryState {
891
+ networkRetries: number;
892
+ mediaRecoveries: number;
893
+ }
894
+ export declare function createHlsErrorRecoveryState(): HlsErrorRecoveryState;
895
+ type HlsErrorAction = {
896
+ kind: "retry-network";
897
+ attempt: number;
898
+ } | {
899
+ kind: "recover-media";
900
+ attempt: number;
901
+ } | {
902
+ kind: "give-up";
903
+ payload: HlsErrorPayload;
904
+ };
905
+ interface HlsErrorInput {
906
+ type: string;
907
+ details?: string;
908
+ fatal: boolean;
909
+ }
910
+ /**
911
+ * Decide what to do given an HLS error and the current recovery counters.
912
+ *
913
+ * Mutates `state` to advance the appropriate counter when retry/recover is
914
+ * selected. Non-fatal errors return `null` (the caller should ignore them).
915
+ */
916
+ export declare function decideHlsErrorAction(error: HlsErrorInput, state: HlsErrorRecoveryState): HlsErrorAction | null;
917
+ /**
918
+ * Framework-agnostic HLS setup.
919
+ *
920
+ * Owns:
921
+ * - HLS.js configuration tuned for the SDK's playback profile.
922
+ * - Media-attached / manifest-parsed / level-switched / audio-track-switched
923
+ * event handlers.
924
+ * - Buffer-flush-on-far-seek heuristic (see `createSeekingHandler`).
925
+ * - Error recovery policy (see Error recovery section below).
926
+ * - Safari native HLS fallback.
927
+ *
928
+ * hls.js itself is loaded on first use (see `loadHls`), so `setupHls` is
929
+ * async and pages that never attach an HLS stream never download it.
930
+ *
931
+ * Resolves to a `HlsController` whose lifetime the caller manages via `destroy()`.
932
+ * Caller responsibilities:
933
+ * - Provide the `<video>` element and a `playerId`.
934
+ * - Subscribe to quality/level/audio changes via the controller's getters or
935
+ * by reading `playerStateStore`.
936
+ * - Surface errors to UI via the `onError` callback.
937
+ */
938
+ type HlsInstance = Hls;
939
+ interface HlsController {
940
+ hls: Hls | null;
941
+ levels: QualityLevel[];
942
+ currentLevel: number;
943
+ isAuto: boolean;
944
+ destroy: () => void;
945
+ setQuality: (index: number) => void;
946
+ }
947
+ interface SetupHlsOptions {
948
+ videoElement: HTMLVideoElement;
949
+ videoUrl: string;
950
+ playerId: UUID;
951
+ isPreloading?: boolean;
952
+ /**
953
+ * Invoked when an HLS error is given up on (after retries are exhausted, or
954
+ * for non-recoverable error types). Callers typically dispatch a custom event
955
+ * and/or show an error overlay.
956
+ */
957
+ onError?: (payload: HlsErrorPayload) => void;
958
+ /**
959
+ * Invoked whenever HLS reports updated quality levels (after manifest parse
960
+ * or level update). Useful for framework wrappers that mirror controller
961
+ * state into reactive store/state (e.g. React `useState`).
962
+ */
963
+ onLevelsChange?: (levels: QualityLevel[]) => void;
964
+ /**
965
+ * Invoked whenever HLS switches to a different quality level.
966
+ */
967
+ onLevelSwitch?: (level: number) => void;
968
+ }
969
+ export declare function createHlsConfig(isPreloading?: boolean): Partial<Hls["config"]>;
970
+ /**
971
+ * Set up HLS streaming on a video element, resolving to a controller for
972
+ * quality/audio switching and teardown.
973
+ *
974
+ * - For non-HLS URLs: sets `videoElement.src` directly and resolves to `null`
975
+ * without loading hls.js.
976
+ * - For HLS URLs on Safari (no `Hls.isSupported()` but native canPlayType):
977
+ * sets `videoElement.src` and returns `null` (UI features that depend on
978
+ * the HLS controller — quality switching, audio tracks — won't be available
979
+ * in native mode).
980
+ * - Otherwise: instantiates HLS.js, attaches the media, wires events
981
+ * (including error recovery), and returns the controller.
982
+ */
983
+ export declare function setupHls(opts: SetupHlsOptions): Promise<HlsController | null>;
984
+ export declare const getPersistedSubtitleTrack: () => number;
985
+ export declare const persistSubtitleTrack: (trackIndex: number) => void;
986
+ export declare const getPersistedAudioTrack: () => number;
987
+ export declare const persistAudioTrack: (trackIndex: number) => void;
988
+ type ContentType = "video" | "image";
989
+ type ViewType = "start" | "watch" | "end";
990
+ type Page = "feed" | "standalone" | "profile";
991
+ interface Segment {
992
+ start_ms: number;
993
+ end_ms: number;
994
+ speed: number;
995
+ }
996
+ interface ContentViewEvent {
997
+ _type: "content_views";
998
+ timestamp?: number;
999
+ content_id: string;
1000
+ content_type: ContentType;
1001
+ view_type: ViewType;
1002
+ watch_duration_ms: number;
1003
+ page: Page;
1004
+ feed_id?: string;
1005
+ post_id?: string;
1006
+ video_position_ms?: number;
1007
+ video_total_duration_ms?: number;
1008
+ segments?: Segment[];
1009
+ device_id?: string;
1010
+ country?: string;
1011
+ }
1012
+ interface EngagementEvent {
1013
+ _type: "engagement";
1014
+ timestamp?: number;
1015
+ engagement_type: string;
1016
+ resource_type?: string;
1017
+ resource_id?: string;
1018
+ page?: string;
1019
+ comment_text?: string;
1020
+ share_platform?: string;
1021
+ country?: string;
1022
+ device_type?: string;
1023
+ session_id?: string;
1024
+ }
1025
+ interface InteractionEvent {
1026
+ _type: "interaction";
1027
+ timestamp?: number;
1028
+ interaction_type: string;
1029
+ element_type?: string;
1030
+ element_id?: string;
1031
+ session_id?: string;
1032
+ page?: string;
1033
+ page_url?: string;
1034
+ scroll_depth?: number;
1035
+ search_query?: string;
1036
+ click_x?: number;
1037
+ click_y?: number;
1038
+ device_type?: string;
1039
+ browser?: string;
1040
+ resource_id?: string;
1041
+ resource_type?: string;
1042
+ feed_id?: string;
1043
+ post_id?: string;
1044
+ content_id?: string;
1045
+ }
1046
+ interface ErrorEvent {
1047
+ _type: "error";
1048
+ timestamp?: number;
1049
+ error_type: string;
1050
+ error_code?: string;
1051
+ error_message?: string;
1052
+ stack_trace?: string;
1053
+ resource_type?: string;
1054
+ resource_id?: string;
1055
+ endpoint?: string;
1056
+ session_id?: string;
1057
+ device_type?: string;
1058
+ browser?: string;
1059
+ os?: string;
1060
+ }
1061
+ interface SessionStartEvent {
1062
+ _type: "session_start";
1063
+ timestamp?: number;
1064
+ utm_source?: string;
1065
+ utm_campaign?: string;
1066
+ browser?: string;
1067
+ language?: string;
1068
+ screen_resolution?: string;
1069
+ platform?: string;
1070
+ tg_platform?: string;
1071
+ tg_version?: string;
1072
+ timezone?: string;
1073
+ timezone_offset?: number;
1074
+ color_depth?: number;
1075
+ touch_support?: boolean;
1076
+ country?: string;
1077
+ user_id?: string;
1078
+ }
1079
+ interface AnalyticsContext {
1080
+ user_id?: string;
1081
+ country?: string;
1082
+ city?: string;
1083
+ region?: string;
1084
+ device?: string;
1085
+ os?: string;
1086
+ os_version?: string;
1087
+ language?: string;
1088
+ browser?: string;
1089
+ screen_resolution?: string;
1090
+ platform?: string;
1091
+ tg_platform?: string;
1092
+ tg_version?: string;
1093
+ timezone?: string;
1094
+ timezone_offset?: number;
1095
+ color_depth?: number;
1096
+ touch_support?: boolean;
1097
+ utm_source?: string;
1098
+ utm_campaign?: string;
1099
+ }
1100
+ type AnalyticsEvent = ContentViewEvent | EngagementEvent | InteractionEvent | ErrorEvent | SessionStartEvent;
1101
+ interface CurrentSegment {
1102
+ start_ms: number;
1103
+ speed: number;
1104
+ }
1105
+ interface AnalyticsState {
1106
+ segments: Map<string, Segment[]>;
1107
+ currentSegment: Map<string, CurrentSegment | null>;
1108
+ }
1109
+ export declare const analyticsStore: WritableAtom<AnalyticsState>;
1110
+ export declare const analyticsStoreActions: {
1111
+ /**
1112
+ * Start tracking a new segment
1113
+ */
1114
+ startSegment(playerId: string, positionMs: number, speed: number): void;
1115
+ /**
1116
+ * End the current segment being tracked
1117
+ */
1118
+ endSegment(playerId: string, positionMs: number): void;
1119
+ /**
1120
+ * Get segments including the current in-progress segment
1121
+ */
1122
+ getSegmentsWithCurrent(playerId: string, currentPositionMs: number): Segment[];
1123
+ /**
1124
+ * Clear all segments for a player
1125
+ */
1126
+ clearSegments(playerId: string): void;
1127
+ };
1128
+ interface SegmentAnalyticsParams {
1129
+ playerId: UUID;
1130
+ currentTimeMs: number;
1131
+ playbackRate: number;
1132
+ isPaused: boolean;
1133
+ }
1134
+ /**
1135
+ * Start tracking a new analytics segment
1136
+ */
1137
+ export declare function startSegment(params: SegmentAnalyticsParams): void;
1138
+ /**
1139
+ * End the current analytics segment
1140
+ */
1141
+ export declare function endSegment(params: Pick<SegmentAnalyticsParams, "playerId" | "currentTimeMs">): void;
1142
+ /**
1143
+ * Restart segment if video is currently playing
1144
+ * This is useful when playback rate changes or other segment-breaking events occur
1145
+ */
1146
+ export declare function restartSegmentIfPlaying(params: SegmentAnalyticsParams): void;
1147
+ interface ControlsState {
1148
+ visible: boolean;
1149
+ hideTimeout: ReturnType<typeof setTimeout> | null;
1150
+ }
1151
+ interface ControlsStore {
1152
+ state: Map<UUID, MapStore<ControlsState>>;
1153
+ get: (id: UUID) => MapStore<ControlsState>;
1154
+ deleteControls: (id: UUID) => void;
1155
+ setVisible: (id: UUID, visible: boolean) => void;
1156
+ showControls: (id: UUID, autoHideMs?: number) => void;
1157
+ hideControls: (id: UUID) => void;
1158
+ }
1159
+ export declare const controlsStore: ControlsStore;
1160
+ interface FeedCacheState {
1161
+ cachedPosts: FeedPost[];
1162
+ isLoadingFromCache: boolean;
1163
+ }
1164
+ export declare const feedCacheAtom: WritableAtom<FeedCacheState>;
1165
+ interface FeedCacheStore {
1166
+ currentFeedId: string | undefined;
1167
+ loadCache: (feedId?: string) => FeedPost[];
1168
+ /**
1169
+ * Append posts to the cache. Pass the feed the posts came from and the batch
1170
+ * is refused if the cache has since moved to another feed.
1171
+ */
1172
+ saveNewPosts: (newPosts: FeedPost[], feedId?: string) => void;
1173
+ removePost: (postId: string) => void;
1174
+ clearCache: () => void;
1175
+ getCacheStats: () => {
1176
+ size: number;
1177
+ timestamp: number | null;
1178
+ };
1179
+ }
1180
+ export declare const feedCacheStore: FeedCacheStore;
1181
+ interface PostStoreState {
1182
+ initialized: boolean;
1183
+ feedId: string;
1184
+ posts: FeedPost[];
1185
+ isLoadedInitial: boolean;
1186
+ isFetchingVideos: boolean;
1187
+ currentIndex: number;
1188
+ total: number;
1189
+ }
1190
+ export declare const postStore: WritableAtom<PostStoreState>;
1191
+ interface PostStoreActions {
1192
+ init: (feedId: string) => void;
1193
+ loadInitialPosts: () => Promise<void>;
1194
+ fetchNewVideos: () => Promise<void>;
1195
+ setCurrentIndex: (index: number) => void;
1196
+ }
1197
+ export declare const postStoreActions: PostStoreActions;
1198
+ export declare const FEED_COMPONENTS_COUNT = 5;
1199
+ export declare const FEED_TRANSITION_THRESHOLD: number;
1200
+ interface FeedInteractionStore {
1201
+ hasInteracted: WritableAtom<boolean>;
1202
+ whenInteracted: WritableAtom<Date>;
1203
+ hasInitialized: WritableAtom<boolean>;
1204
+ videosInitialized: WritableAtom<number>;
1205
+ components: WritableAtom<number[]>;
1206
+ originalPositions: WritableAtom<number[]>;
1207
+ transforms: WritableAtom<number[]>;
1208
+ setTransforms: (transforms: number[]) => void;
1209
+ }
1210
+ export declare const feedStore: FeedInteractionStore;
1211
+ export declare const setHasInteracted: () => boolean;
1212
+ export declare const initializeVideo: () => void;
1213
+ interface PlayerContainerElementStore {
1214
+ register: (playerId: UUID, element: HTMLDivElement) => void;
1215
+ unregister: (playerId: UUID) => void;
1216
+ get: (playerId: UUID) => HTMLDivElement | null;
1217
+ subscribe: (playerId: UUID, listener: () => void) => () => void;
1218
+ clear: () => void;
1219
+ }
1220
+ export declare const playerContainerElementStore: PlayerContainerElementStore;
1221
+ interface PlayerMediaElementStore {
1222
+ register: (playerId: UUID, element: HTMLVideoElement) => void;
1223
+ unregister: (playerId: UUID) => void;
1224
+ get: (playerId: UUID) => HTMLVideoElement | null;
1225
+ subscribe: (playerId: UUID, listener: () => void) => () => void;
1226
+ clear: () => void;
1227
+ }
1228
+ export declare const playerMediaElementStore: PlayerMediaElementStore;
1229
+ export declare const defaultSettings: SettingsState;
1230
+ export declare const FONT_FAMILIES: {
1231
+ readonly monospace_serif: "\"Courier New\", Courier, \"Nimbus Mono L\", \"Cutive Mono\", monospace";
1232
+ readonly proportional_serif: "\"Times New Roman\", Times, Georgia, Cambria, \"PT Serif Caption\", serif";
1233
+ readonly monospace_sans: "\"Deja Vu Sans Mono\", \"Lucida Console\", Monaco, Consolas, \"PT Mono\", monospace";
1234
+ readonly proportional_sans: "Roboto, Arial, Helvetica, Verdana, \"PT Sans Caption\", sans-serif";
1235
+ readonly casual: "\"Comic Sans MS\", Impact, Handlee, fantasy";
1236
+ readonly cursive: "\"Monotype Corsiva\", \"URW Chancery L\", \"Apple Chancery\", \"Dancing Script\", cursive";
1237
+ readonly small_caps: "Arial, Helvetica, Verdana, \"Marcellus SC\", sans-serif";
1238
+ };
1239
+ type FontFamilyKey = keyof typeof FONT_FAMILIES;
1240
+ export declare const FONT_SIZES: number[];
1241
+ export declare const COLORS: Record<string, string>;
1242
+ export declare const EDGE_STYLES: string[];
1243
+ export declare const PLAYBACK_SPEEDS: number[];
1244
+ export declare const LANG_TYPES: string[];
1245
+ /**
1246
+ * Validate and parse settings, returning defaults for invalid values
1247
+ * @param parsed - Raw settings object (e.g., from localStorage)
1248
+ * @returns Validated settings with defaults applied for invalid values
1249
+ */
1250
+ export declare const validateSettings: (parsed: unknown) => SettingsState;
1251
+ export declare const loadSettings: () => SettingsState;
1252
+ export declare const saveSettings: (settings: SettingsState) => void;
1253
+ interface SettingsStore {
1254
+ state: MapStore<SettingsState>;
1255
+ getSettings: () => SettingsState;
1256
+ setVolume: (volume: number) => number;
1257
+ setPlaybackSpeed: (playbackSpeed: number) => number;
1258
+ setCustomPlayback: (customPlayback: number) => number;
1259
+ setAllowCaptions: (allowCaptions: boolean) => boolean;
1260
+ setCaptionPosition: (x: number, y: number) => {
1261
+ x: number;
1262
+ y: number;
1263
+ };
1264
+ setSubtitleLang: (captionLang: CaptionLangType) => CaptionLangType;
1265
+ setCaptionFontFamily: (captionFontFamily: string) => string;
1266
+ setCaptionFontSize: (captionFontSize: number) => number;
1267
+ setCaptionFontColor: (captionFontColor: string) => string;
1268
+ setCaptionBGColor: (captionBGColor: string) => string;
1269
+ setCaptionBGOpacity: (captionOpacity: number) => number;
1270
+ setCaptionWindowColor: (captionWindowColor: string) => string;
1271
+ setCaptionWindowOpacity: (captionWindowOpacity: number) => number;
1272
+ setCaptionFontOpacity: (captionFontOpacity: number) => number;
1273
+ setCaptionCharacterEdgeStyle: (captionCharacterEdgeStyle: string) => string;
1274
+ resetCaptionSettings: () => void;
1275
+ setSelectedLanguageCode: (languageCode: string) => string | undefined;
1276
+ setMuted: (muted: boolean) => boolean;
1277
+ setPreferredQuality: (quality: number | undefined) => number | undefined;
1278
+ setPreferredAudioLanguage: (language: string | undefined) => string | undefined;
1279
+ setPreferredSubtitleLanguage: (language: string | undefined) => string | undefined;
1280
+ }
1281
+ export declare const settingsStore: SettingsStore;
1282
+ /**
1283
+ * Settings-menu keys follow a hierarchical naming convention:
1284
+ * - Root menus: simple names (main, quality, audio, captions, playback)
1285
+ * - Nested menus: parent-child pattern (captions.style, captions.font, etc.)
1286
+ */
1287
+ type MenuKey = "main" | "quality" | "audio" | "captions" | "playback" | "captions.style" | "captions.font" | "captions.background" | "captions.window" | "captions.font-family" | "captions.edge-style";
1288
+ /** Stack of visited menus for navigation history */
1289
+ export declare const menuStack: WritableAtom<MenuKey[]>;
1290
+ /** Direction of the last navigation (for animation) */
1291
+ export declare const navigationDirection: WritableAtom<"forward" | "back">;
1292
+ /** Current active menu is the top of the stack */
1293
+ export declare const activeMenu: ReadableAtom<MenuKey>;
1294
+ /** Navigate to a new menu (pushes to stack) */
1295
+ export declare const pushMenu: (menuId: MenuKey) => void;
1296
+ /** Go back to previous menu (pops from stack) */
1297
+ export declare const popMenu: () => void;
1298
+ /** Reset to main menu */
1299
+ export declare const resetMenu: () => void;
1300
+ /**
1301
+ * Fill percentage for the custom playback-speed slider. Piecewise on purpose:
1302
+ * normal speed (1.0x) sits at the visual middle of the track, with min–1.0
1303
+ * mapped to the lower half and 1.0–max to the upper half. Note the pointer
1304
+ * mapping below is linear — the same asymmetry the React slider ships with.
1305
+ */
1306
+ export declare function computePlaybackFillPercentage(value: number, min: number, max: number): number;
1307
+ interface PlaybackPointerOptions {
1308
+ rect: {
1309
+ left: number;
1310
+ width: number;
1311
+ };
1312
+ clientX: number;
1313
+ min: number;
1314
+ max: number;
1315
+ step: number;
1316
+ }
1317
+ /**
1318
+ * Linear pointer-position → playback value: clamped to the track, snapped to
1319
+ * the step grid, formatted to two decimals (the value React persists via
1320
+ * settingsStore.setCustomPlayback).
1321
+ */
1322
+ export declare function computePlaybackValueFromPointer({ rect, clientX, min, max, step }: PlaybackPointerOptions): number;
1323
+ /**
1324
+ * Settings-menu strings, mirroring the corresponding keys of
1325
+ * packages/react/src/locales/<lang>.json verbatim (quality.*, audio.*,
1326
+ * playback.*, captions.* and common.*). Edge-style options are keyed by the
1327
+ * EDGE_STYLES runtime values and font families by FontFamilyKey, so menus can
1328
+ * look labels up directly from the constants they render.
1329
+ *
1330
+ * Import this module from the lazy settings chunk only — it must not be
1331
+ * pulled into the initial player bundle.
1332
+ */
1333
+ interface PlayerMenuLabels {
1334
+ quality: {
1335
+ title: string;
1336
+ auto: string;
1337
+ };
1338
+ audio: {
1339
+ title: string;
1340
+ noTracks: string;
1341
+ };
1342
+ playback: {
1343
+ speed: string;
1344
+ custom: string;
1345
+ normal: string;
1346
+ };
1347
+ captions: {
1348
+ title: string;
1349
+ off: string;
1350
+ style: string;
1351
+ font: string;
1352
+ background: string;
1353
+ window: string;
1354
+ resetAll: string;
1355
+ edgeStyle: {
1356
+ title: string;
1357
+ options: Record<string, string>;
1358
+ };
1359
+ fontFamilies: Record<FontFamilyKey, string>;
1360
+ };
1361
+ stats: {
1362
+ title: string;
1363
+ copyDebug: string;
1364
+ videoId: string;
1365
+ playerId: string;
1366
+ viewport: string;
1367
+ dropped: string;
1368
+ resolution: string;
1369
+ volume: string;
1370
+ codecs: string;
1371
+ color: string;
1372
+ connectionSpeed: string;
1373
+ bufferHealth: string;
1374
+ };
1375
+ shortcuts: {
1376
+ title: string;
1377
+ playPause: string;
1378
+ seek10s: string;
1379
+ seek5s: string;
1380
+ pip: string;
1381
+ fullscreen: string;
1382
+ mute: string;
1383
+ volume: string;
1384
+ };
1385
+ colors: Record<string, string>;
1386
+ common: {
1387
+ back: string;
1388
+ family: string;
1389
+ more: string;
1390
+ less: string;
1391
+ settings: string;
1392
+ size: string;
1393
+ opacity: string;
1394
+ color: string;
1395
+ reset: string;
1396
+ custom: string;
1397
+ options: string;
1398
+ off: string;
1399
+ };
1400
+ }
1401
+ export declare function getPlayerMenuLabels(code: string | null | undefined): PlayerMenuLabels;
1402
+ interface SubtitleTrack {
1403
+ index: number;
1404
+ label: string;
1405
+ language: string;
1406
+ kind: string;
1407
+ track: TextTrack;
1408
+ }
1409
+ /**
1410
+ * Calculates the efficient end time for a cue to prevent flickering and ensure readability.
1411
+ */
1412
+ export declare const calculateSmoothedEndTime: (cue: TextTrackCue | VTTCue, nextCue?: TextTrackCue | VTTCue) => number;
1413
+ /**
1414
+ * Helper to find the next cue in a TextTrackCueList by reference.
1415
+ */
1416
+ export declare const findNextCue: (activeCue: TextTrackCue, allCues: TextTrackCueList | null) => TextTrackCue | undefined;
1417
+ export declare function stripHtmlTags(input: string): string;
1418
+ /**
1419
+ * Extracts and cleans text from a cue object.
1420
+ * Handles VTTCue vs TextTrackCue differences.
1421
+ */
1422
+ export declare const getCleanCueText: (cue: TextTrackCue | VTTCue) => string;
1423
+ /**
1424
+ * Applies smoothing logic to a list of cues (typically activeCues).
1425
+ * Modifies the cues in-place and caches them to avoid re-processing.
1426
+ */
1427
+ export declare const processCues: (cues: TextTrackCueList | TextTrackCue[], allCues: TextTrackCueList | null) => void;
1428
+ /**
1429
+ * Parses the video element's text tracks and extracts relevant subtitle/caption tracks.
1430
+ * Also normalizes track state.
1431
+ */
1432
+ export declare const extractSubtitleTracks: (tracks: TextTrackList) => SubtitleTrack[];
1433
+ interface PlayerState {
1434
+ paused: boolean;
1435
+ loading: boolean;
1436
+ ended: boolean;
1437
+ mounted: boolean;
1438
+ hasInteracted: boolean;
1439
+ whenInteracted: Date;
1440
+ isFullscreen: boolean;
1441
+ isPictureInPicture: boolean;
1442
+ muted: boolean;
1443
+ playbackRate: number;
1444
+ volume: number;
1445
+ previousVolume: number;
1446
+ viewport: {
1447
+ width: number;
1448
+ height: number;
1449
+ };
1450
+ resolution: number;
1451
+ subtitleTrack: number;
1452
+ availableSubtitleTracks: SubtitleTrack[];
1453
+ currentSubtitleText: string;
1454
+ audioTrack: number;
1455
+ availableAudioTracks: AudioTrack[];
1456
+ hlsInstance: Hls | null;
1457
+ }
1458
+ interface PlayerProgressSnapshot {
1459
+ currentTime: number;
1460
+ duration: number;
1461
+ progress: number;
1462
+ buffered: number;
1463
+ }
1464
+ interface PlayerStateStore {
1465
+ state: Map<UUID, MapStore<PlayerState>>;
1466
+ get: (id: UUID) => MapStore<PlayerState>;
1467
+ deletePlayer: (id: UUID) => void;
1468
+ getEffectiveMediaMuted: (player: Pick<PlayerState, "muted" | "volume" | "hasInteracted">) => boolean;
1469
+ muteMedia: (id: UUID) => void;
1470
+ unmuteMedia: (id: UUID) => void;
1471
+ toggleMediaMute: (id: UUID) => void;
1472
+ setMediaVolume: (id: UUID, volume: number) => void;
1473
+ playMedia: (id: UUID) => Promise<void>;
1474
+ pauseMedia: (id: UUID) => void;
1475
+ toggleMediaPlayback: (id: UUID) => Promise<void>;
1476
+ pauseOtherMedia: (except: UUID) => void;
1477
+ setMediaPlaybackRate: (id: UUID, playbackRate: number) => void;
1478
+ readProgressSnapshot: (id: UUID) => PlayerProgressSnapshot;
1479
+ subscribeToProgress: (id: UUID, onStoreChange: () => void) => () => void;
1480
+ seekProgressTo: (id: UUID, seconds: number) => void;
1481
+ seekProgressBy: (id: UUID, deltaSeconds: number) => void;
1482
+ getTrackOptions: (tracks: {
1483
+ label: string;
1484
+ language: string;
1485
+ kind: string;
1486
+ }[]) => {
1487
+ index: number;
1488
+ label: string;
1489
+ language: string;
1490
+ kind: string;
1491
+ }[];
1492
+ selectAudioTrack: (id: UUID, trackIndex: number) => void;
1493
+ selectSubtitleTrack: (id: UUID, trackIndex: number) => void;
1494
+ setAudioTrack: (id: UUID, audioTrack: number) => void;
1495
+ setAvailableAudioTracks: (id: UUID, tracks: AudioTrack[]) => void;
1496
+ setGlobalMuted: (muted: boolean) => void;
1497
+ setGlobalVolume: (volume: number) => void;
1498
+ setGlobalPlaybackRate: (rate: number) => void;
1499
+ setGlobalPreferredQuality: (quality: number | undefined) => void;
1500
+ setGlobalPreferredAudioLanguage: (language: string | undefined) => void;
1501
+ setGlobalPreferredSubtitleLanguage: (language: string | undefined) => void;
1502
+ pauseAllPlayers: () => void;
1503
+ setMounted: (id: UUID) => void;
1504
+ setHasInteracted: (id: UUID) => void;
1505
+ setPaused: (id: UUID, paused: boolean) => void;
1506
+ setLoading: (id: UUID, loading: boolean) => void;
1507
+ setEnded: (id: UUID, ended: boolean) => void;
1508
+ setFullscreen: (id: UUID, isFullscreen: boolean) => void;
1509
+ setPictureInPicture: (id: UUID, isPictureInPicture: boolean) => void;
1510
+ setMuted: (id: UUID, muted: boolean) => void;
1511
+ setPlaybackRate: (id: UUID, playbackRate: number) => void;
1512
+ setPreviousVolume: (id: UUID, previousVolume: number) => void;
1513
+ setVolume: (id: UUID, volume: number) => void;
1514
+ setViewport: (id: UUID, width: number, height: number) => void;
1515
+ setResolution: (id: UUID, resolution: number) => void;
1516
+ setSubtitleTrack: (id: UUID, subtitleTrack: number) => void;
1517
+ setAvailableSubtitleTracks: (id: UUID, tracks: SubtitleTrack[]) => void;
1518
+ setCurrentSubtitleText: (id: UUID, text: string) => void;
1519
+ setHlsInstance: (id: UUID, hlsInstance: Hls | null) => void;
1520
+ }
1521
+ export declare const playerStateStore: PlayerStateStore;
1522
+ interface PlayerUiActionTargets {
1523
+ container?: HTMLDivElement | null;
1524
+ video?: HTMLVideoElement | null;
1525
+ }
1526
+ export declare function showPlayerControls(playerId: UUID): void;
1527
+ export declare function hidePlayerControls(playerId: UUID): void;
1528
+ export declare function togglePlayerFullscreen(playerId: UUID, overrides?: PlayerUiActionTargets): Promise<void>;
1529
+ export declare function togglePlayerPictureInPicture(playerId: UUID, overrides?: PlayerUiActionTargets): Promise<void>;
1530
+ /**
1531
+ * Structural shape of a video element ref. Compatible with React.RefObject
1532
+ * but does not depend on React, keeping this module framework-agnostic.
1533
+ */
1534
+ interface VideoElementRef {
1535
+ current: HTMLVideoElement | null;
1536
+ }
1537
+ export declare const handleLoadedMetadata: (videoElement: HTMLVideoElement, playerId: UUID) => void;
1538
+ export declare const clearSubtitles: (playerId: UUID) => void;
1539
+ /**
1540
+ * Handles the 'cuechange' event to update subtitles.
1541
+ * Uses event-driven logic + lookahead smoothing to prevent flickering.
1542
+ */
1543
+ export declare const handleCueChange: (playerId: UUID, videoRef: VideoElementRef) => void;
1544
+ /**
1545
+ * Pure buffer-progress computations extracted from useBufferProgress.
1546
+ * Operate on plain TimeRanges + numbers, not HTMLVideoElement, so they
1547
+ * are framework-agnostic and trivially testable.
1548
+ */
1549
+ interface BufferRange {
1550
+ start: number;
1551
+ end: number;
1552
+ }
1553
+ /**
1554
+ * Convert a TimeRanges into normalized 0-100 percentage ranges.
1555
+ * Returns [] when duration is zero/invalid or timeRanges is missing.
1556
+ */
1557
+ export declare const computeBufferRanges: (timeRanges: TimeRanges | null | undefined, duration: number) => BufferRange[];
1558
+ /**
1559
+ * How much buffer (as a 0-100 percentage) is loaded ahead of the
1560
+ * current playback position. Considers only ranges that cover the
1561
+ * current position; takes the maximum contiguous lookahead.
1562
+ */
1563
+ export declare const computeBufferedAhead: (ranges: BufferRange[], currentTime: number, duration: number) => number;
1564
+ /**
1565
+ * Pure progress-fraction helper extracted from useProgressBar.
1566
+ *
1567
+ * Returns a value in [0, 1] representing how far through `duration`
1568
+ * `currentTime` is. Defensive against the common edge cases where
1569
+ * duration is zero, NaN, or Infinity (e.g. before metadata loads),
1570
+ * and against non-finite currentTime values. The previous inline
1571
+ * `video.currentTime / video.duration` formula produced NaN in
1572
+ * those cases, which leaked into React state.
1573
+ */
1574
+ export declare function computeProgressFraction(currentTime: number, duration: number): number;
1575
+ interface BuildEventParams {
1576
+ contentId: string;
1577
+ contentType: ContentType;
1578
+ viewType: ViewType;
1579
+ watchDurationMs: number;
1580
+ page: Page;
1581
+ feedId?: string;
1582
+ postId?: string;
1583
+ videoPositionMs?: number;
1584
+ videoTotalDurationMs?: number;
1585
+ segments?: Segment[];
1586
+ }
1587
+ /**
1588
+ * Build a content view event for analytics
1589
+ * Pure function that constructs the event payload
1590
+ */
1591
+ export declare function buildContentViewEvent(params: BuildEventParams): ContentViewEvent;
1592
+ /**
1593
+ * Calculate watch duration from start time to now
1594
+ */
1595
+ export declare function calculateWatchDuration(startTimeMs: number | null): number;
1596
+ /**
1597
+ * Determine the effective page based on feedId presence
1598
+ */
1599
+ export declare function getEffectivePage(page: Page, feedId?: string): Page;
1600
+ /**
1601
+ * Check if segments should be included in the event
1602
+ * Only include for "watch" and "end" view types
1603
+ */
1604
+ export declare function shouldIncludeSegments(viewType: ViewType): boolean;
1605
+ /**
1606
+ * Round milliseconds for video position/duration
1607
+ */
1608
+ export declare function roundMs(ms: number): number;
1609
+ /**
1610
+ * Convert seconds to milliseconds
1611
+ */
1612
+ export declare function secondsToMs(seconds: number): number;
1613
+ /**
1614
+ * Convert milliseconds to seconds (for timestamp)
1615
+ */
1616
+ export declare function msToSeconds(ms: number): number;
1617
+ interface VideoAnalyticsPayload {
1618
+ videoPositionMs?: number;
1619
+ videoTotalDurationMs?: number;
1620
+ segments?: Segment[];
1621
+ }
1622
+ interface VideoSnapshot {
1623
+ currentTime: number;
1624
+ duration: number;
1625
+ }
1626
+ interface BuildVideoAnalyticsPayloadParams {
1627
+ contentType: ContentType;
1628
+ viewType: ViewType;
1629
+ video?: VideoSnapshot | null;
1630
+ playerId?: string;
1631
+ }
1632
+ /**
1633
+ * Build and POST a single content-view event.
1634
+ */
1635
+ export declare function postContentEvent(params: BuildEventParams): void;
1636
+ /**
1637
+ * Compute the video position / duration / segments to attach to a
1638
+ * content-view event. Returns an empty payload for non-video content
1639
+ * or when the video snapshot is unavailable.
1640
+ */
1641
+ export declare function buildVideoAnalyticsPayload({ contentType, viewType, video, playerId }: BuildVideoAnalyticsPayloadParams): VideoAnalyticsPayload;
1642
+ export declare const analyticsContextStore: WritableAtom<AnalyticsContext>;
1643
+ export declare function setAnalyticsContext(context: Partial<AnalyticsContext>): void;
1644
+ interface DeviceState {
1645
+ deviceId: string | undefined;
1646
+ }
1647
+ export declare const analyticsDeviceStore: WritableAtom<DeviceState>;
1648
+ export declare function getOrCreateDeviceId(): string;
1649
+ export declare function setDeviceId(deviceId: string): void;
1650
+ interface SessionState {
1651
+ sessionId: string | undefined;
1652
+ started: boolean;
1653
+ }
1654
+ export declare const analyticsSessionStore: WritableAtom<SessionState>;
1655
+ export declare function getOrCreateSessionId(): string;
1656
+ export declare function initializeAnalyticsContext(): void;
1657
+ /**
1658
+ * Chapter with calculated end time and duration
1659
+ */
1660
+ interface ChapterWithEnd extends Chapter {
1661
+ endTime: number;
1662
+ durationSec: number;
1663
+ }
1664
+ /**
1665
+ * Check if a single chapter is within the video duration
1666
+ * @param chapter - The chapter to validate
1667
+ * @param videoDuration - The total video duration in seconds
1668
+ * @param tolerance - Tolerance in seconds for rounding errors (default: 1)
1669
+ * @returns Whether the chapter is within valid bounds
1670
+ */
1671
+ export declare function isChapterWithinDuration(chapter: Chapter, videoDuration: number, tolerance?: number): boolean;
1672
+ /**
1673
+ * Validate chapters for use with chaptered progress bar
1674
+ * Returns false if:
1675
+ * - chapters is undefined or empty
1676
+ * - less than 2 chapters (need multiple for chaptered bar)
1677
+ * - any chapter exceeds video duration
1678
+ *
1679
+ * @param chapters - Array of chapters to validate
1680
+ * @param videoDuration - The total video duration in seconds
1681
+ * @param tolerance - Tolerance in seconds for rounding errors (default: 1)
1682
+ * @returns Whether chapters are valid for chaptered progress bar
1683
+ */
1684
+ export declare function validateChapters(chapters: Chapter[] | undefined, videoDuration: number, tolerance?: number): boolean;
1685
+ /**
1686
+ * Calculate chapter end times based on next chapter start or video duration
1687
+ */
1688
+ export declare function calculateChaptersWithEnd(chapters: Chapter[], duration: number): ChapterWithEnd[];
1689
+ /**
1690
+ * Slice heatmap data for a specific chapter based on its time range
1691
+ */
1692
+ interface HeatmapSliceParams {
1693
+ heatmapData: number[];
1694
+ chapterStartTime: number;
1695
+ chapterEndTime: number;
1696
+ videoDuration: number;
1697
+ }
1698
+ export declare function sliceHeatmapData({ heatmapData, chapterStartTime, chapterEndTime, videoDuration }: HeatmapSliceParams): number[];
1699
+ /**
1700
+ * Calculate all heatmap slices for chapters
1701
+ */
1702
+ export declare function calculateHeatmapSlices(heatmapData: number[] | null, chapters: ChapterWithEnd[], duration: number): number[][];
1703
+ /**
1704
+ * Calculate global max value from heatmap data for consistent normalization
1705
+ */
1706
+ export declare function calculateGlobalMax(heatmapData: number[] | null): number;
1707
+ /**
1708
+ * Calculate progress percentage within a chapter segment
1709
+ * @returns 0-100 percentage
1710
+ */
1711
+ export declare function calculateSegmentProgress(currentPosition: number, chapterStart: number, chapterEnd: number): number;
1712
+ /**
1713
+ * Calculate buffer ranges within a chapter segment
1714
+ * Converts global buffer ranges to segment-local 0-100 scale
1715
+ */
1716
+ type SegmentBufferParams = {
1717
+ globalBufferRanges: BufferRange[];
1718
+ chapterStart: number;
1719
+ chapterEnd: number;
1720
+ videoDuration: number;
1721
+ };
1722
+ export declare function calculateSegmentBufferRanges({ globalBufferRanges, chapterStart, chapterEnd, videoDuration }: SegmentBufferParams): BufferRange[];
1723
+ /**
1724
+ * Calculate flex grow ratio for a chapter based on its duration
1725
+ */
1726
+ export declare function calculateFlexGrow(chapterDuration: number, videoDuration: number): number;
1727
+ /**
1728
+ * Determine current playback position
1729
+ * Uses progress during drag for real-time feedback, currentTime otherwise
1730
+ */
1731
+ interface CurrentPositionParams {
1732
+ isDragging: boolean;
1733
+ progress: number;
1734
+ duration: number;
1735
+ currentTime: number;
1736
+ }
1737
+ export declare function getCurrentPosition({ isDragging, progress, duration, currentTime }: CurrentPositionParams): number;
1738
+ /**
1739
+ * Find which segment is hovered based on mouse X position
1740
+ * @param segments - Array of segment DOM elements
1741
+ * @param mouseX - Mouse X coordinate (clientX)
1742
+ * @returns Index of hovered segment, or null if none
1743
+ */
1744
+ export declare function findHoveredSegmentIndex(segments: Array<HTMLDivElement | null>, mouseX: number): number | null;
1745
+ /**
1746
+ * Start time of the first chapter after the current position, or null when
1747
+ * already in the last chapter. Mirrors React useChapterNavigation.
1748
+ */
1749
+ export declare function getNextChapterStart(chapters: Chapter[] | undefined, currentTime: number): number | null;
1750
+ /**
1751
+ * Target for "previous chapter": restart the current chapter when more than
1752
+ * 3s in (or when it is the first), otherwise jump to the previous chapter.
1753
+ * Mirrors React useChapterNavigation.
1754
+ */
1755
+ export declare function getPrevChapterTarget(chapters: Chapter[] | undefined, currentTime: number): number | null;
1756
+ interface BuildEngagementParams {
1757
+ engagementType: string;
1758
+ resourceType?: string;
1759
+ resourceId?: string;
1760
+ page?: string;
1761
+ commentText?: string;
1762
+ sharePlatform?: string;
1763
+ country?: string;
1764
+ deviceType?: string;
1765
+ sessionId?: string;
1766
+ }
1767
+ interface BuildInteractionParams {
1768
+ interactionType: string;
1769
+ elementType?: string;
1770
+ elementId?: string;
1771
+ sessionId?: string;
1772
+ page?: string;
1773
+ pageUrl?: string;
1774
+ scrollDepth?: number;
1775
+ searchQuery?: string;
1776
+ clickX?: number;
1777
+ clickY?: number;
1778
+ deviceType?: string;
1779
+ browser?: string;
1780
+ resourceId?: string;
1781
+ resourceType?: string;
1782
+ feedId?: string;
1783
+ postId?: string;
1784
+ contentId?: string;
1785
+ }
1786
+ interface BuildErrorParams {
1787
+ errorType: string;
1788
+ errorCode?: string;
1789
+ errorMessage?: string;
1790
+ stackTrace?: string;
1791
+ resourceType?: string;
1792
+ resourceId?: string;
1793
+ endpoint?: string;
1794
+ sessionId?: string;
1795
+ deviceType?: string;
1796
+ browser?: string;
1797
+ os?: string;
1798
+ }
1799
+ interface BuildSessionStartParams {
1800
+ browser?: string;
1801
+ language?: string;
1802
+ screenResolution?: string;
1803
+ platform?: string;
1804
+ tgPlatform?: string;
1805
+ tgVersion?: string;
1806
+ timezone?: string;
1807
+ timezoneOffset?: number;
1808
+ colorDepth?: number;
1809
+ touchSupport?: boolean;
1810
+ country?: string;
1811
+ userId?: string;
1812
+ utmSource?: string;
1813
+ utmCampaign?: string;
1814
+ }
1815
+ export declare function postAnalytics(events: AnalyticsEvent[]): Promise<void>;
1816
+ export declare function postEngagement(params: BuildEngagementParams): void;
1817
+ export declare function postInteraction(params: BuildInteractionParams): void;
1818
+ export declare function postError(params: BuildErrorParams): void;
1819
+ /**
1820
+ * Resolves once the events outstanding at call time have been sent, rather than
1821
+ * once a flush has merely been started. Two paths used to return early: a call
1822
+ * during an active flush reported a drain that had not happened, and a call
1823
+ * while the only outstanding batch was already in flight (so the queue looked
1824
+ * empty) returned before that request finished. Delegating to flushQueue makes
1825
+ * it wait for whichever drain covers the outstanding work — starting one now,
1826
+ * bypassing the timer, when nothing is running yet.
1827
+ */
1828
+ export declare function flushAnalytics(): Promise<void>;
1829
+ interface VideoHeatmap {
1830
+ video_id: string;
1831
+ total_duration_ms: number;
1832
+ data: number[];
1833
+ }
1834
+ interface GetVideoHeatmapOptions {
1835
+ videoId: string;
1836
+ buckets?: number;
1837
+ }
1838
+ export declare function getVideoHeatmap({ videoId, buckets }: GetVideoHeatmapOptions): Promise<VideoHeatmap | null>;
1839
+ /**
1840
+ * Hot segment data for a video
1841
+ * Represents a segment with higher-than-average viewership
1842
+ */
1843
+ interface HotSegment {
1844
+ start_second: number;
1845
+ end_second: number;
1846
+ multiplier: number;
1847
+ }
1848
+ interface GetHotSegmentsOptions {
1849
+ videoId: string;
1850
+ startDate?: string;
1851
+ endDate?: string;
1852
+ }
1853
+ export declare function getHotSegments({ videoId, startDate, endDate }: GetHotSegmentsOptions): Promise<HotSegment[]>;
1854
+ interface VideoStats {
1855
+ droppedFrames: number;
1856
+ volume: number;
1857
+ networkSpeed: number;
1858
+ bufferHealth: number;
1859
+ currentRes: {
1860
+ width: number;
1861
+ height: number;
1862
+ } | null;
1863
+ optimalRes: {
1864
+ width: number;
1865
+ height: number;
1866
+ } | null;
1867
+ }
1868
+ interface CollectStatsInput {
1869
+ video: HTMLVideoElement | null;
1870
+ hlsBandwidthEstimate: number | null;
1871
+ hlsLevels: ReadonlyArray<{
1872
+ width: number;
1873
+ height: number;
1874
+ }>;
1875
+ hlsCurrentLevel: number;
1876
+ hlsAutoLevelEnabled: boolean;
1877
+ hlsAutoLevelCapping: number;
1878
+ }
1879
+ export declare function getDroppedFrames(video: HTMLVideoElement): number;
1880
+ export declare function getBufferHealth(video: HTMLVideoElement): number;
1881
+ export declare function collectVideoStats(input: CollectStatsInput): VideoStats;
1882
+ export declare const LOOP_REBASE_BASE_MULTIPLIER = 2;
1883
+ export declare const LOOP_REBASE_THRESHOLD_MULTIPLIER = 50;
1884
+ export declare function shiftArray(arr: number[], shiftBy: number): number[];
1885
+ export declare function calcShiftCountArray(index: number, arraySize: number): number[];
1886
+ export declare function buildTransforms(currentIndex: number, originalPositions: number[]): number[];
1887
+ export declare function computeScrollIndex(scrollTop: number, containerHeight: number, gap?: number): number;
1888
+ export declare function isAtEndOfFeed(currentIndex: number, postsLength: number): boolean;
1889
+ export declare function isFeedExhausted(postsLength: number, total: number): boolean;
1890
+ interface ShouldFetchMoreInput {
1891
+ currentIndex: number;
1892
+ postsLength: number;
1893
+ total: number;
1894
+ isFetching: boolean;
1895
+ isLoaded: boolean;
1896
+ }
1897
+ export declare function shouldFetchMore({ currentIndex, postsLength, total, isFetching, isLoaded }: ShouldFetchMoreInput): boolean;
1898
+ export declare function resolvePostIndex(transform: number, postsLength: number, loop: boolean): number;
1899
+ export declare function getLoopRebaseThreshold(postsLength: number): number;
1900
+ interface LoopRebaseInput {
1901
+ currentIndex: number;
1902
+ postsLength: number;
1903
+ loop: boolean;
1904
+ total: number;
1905
+ }
1906
+ export declare function shouldRebaseLoopIndex({ currentIndex, postsLength, loop, total }: LoopRebaseInput): boolean;
1907
+ export declare function getRebasedLoopIndex(currentIndex: number, postsLength: number): number;
1908
+ export declare const IMAGE_DWELL_MS = 5e3;
1909
+ export declare function shouldDwellAdvance(autoscroll: boolean, isCurrent: boolean, isImage: boolean): boolean;
1910
+ export declare function gateVideoEnded(isCurrent: boolean, autoscroll: boolean): boolean;
1911
+ interface AutoAdvanceInput {
1912
+ isCurrent: boolean;
1913
+ autoscroll: boolean;
1914
+ loop: boolean;
1915
+ currentIndex: number;
1916
+ postsLength: number;
1917
+ total: number;
1918
+ }
1919
+ export declare function shouldAutoAdvance({ isCurrent, autoscroll, loop, currentIndex, postsLength, total }: AutoAdvanceInput): boolean;
1920
+ export declare function getViewportFallbackHeight(safeAreaTabBar: number): number;
1921
+ interface ContainerHeightInput {
1922
+ measuredHeight: number;
1923
+ scrollContainerHeight: number;
1924
+ safeAreaTabBar: number;
1925
+ }
1926
+ export declare function resolveContainerHeight({ measuredHeight, scrollContainerHeight, safeAreaTabBar }: ContainerHeightInput): number;
1927
+ export declare function checkIsCut(el: HTMLElement | null): boolean;
1928
+ export declare function connect(config: ConnectConfig): Promise<string | undefined>;
1929
+ interface CreateImageUploadOptions {
1930
+ projectId: string;
1931
+ orgId?: string;
1932
+ name: string;
1933
+ }
1934
+ interface ImageUploadResult {
1935
+ imageId: string;
1936
+ uploadUrl: string;
1937
+ }
1938
+ export declare function createImageUpload(options: CreateImageUploadOptions): Promise<ImageUploadResult>;
1939
+ export declare function uploadImage(file: Blob | Uint8Array, options: CreateImageUploadOptions): Promise<ImageUploadResult>;
1940
+ interface CreateVideoUploadOptions {
1941
+ projectId: string;
1942
+ orgId?: string;
1943
+ name: string;
1944
+ videoQuality?: string;
1945
+ }
1946
+ interface VideoUploadResult {
1947
+ videoId: string;
1948
+ posterId: string;
1949
+ videoUploadUrl: string;
1950
+ posterUploadUrl: string;
1951
+ }
1952
+ export declare function createVideoUpload(options: CreateVideoUploadOptions): Promise<VideoUploadResult>;
1953
+ export declare function uploadVideo(videoFile: Blob | Uint8Array, posterFile: Blob | Uint8Array, options: CreateVideoUploadOptions): Promise<VideoUploadResult>;
1954
+ interface AudioTrackUploadItem {
1955
+ languageCode: string;
1956
+ label?: string;
1957
+ fileName: string;
1958
+ format: string;
1959
+ size?: number;
1960
+ }
1961
+ interface AudioTrackUploadTarget {
1962
+ id: string;
1963
+ languageCode?: string;
1964
+ uploadUrl?: string;
1965
+ }
1966
+ interface AudioTrackUploadResult {
1967
+ targets: AudioTrackUploadTarget[];
1968
+ }
1969
+ export declare function createAudioTrackUpload(projectId: string, videoId: string, items: AudioTrackUploadItem[]): Promise<AudioTrackUploadResult>;
1970
+ interface SubtitleUploadItem {
1971
+ languageCode: string;
1972
+ label?: string;
1973
+ fileName: string;
1974
+ format: string;
1975
+ size?: number;
1976
+ }
1977
+ interface SubtitleUploadTarget {
1978
+ id: string;
1979
+ languageCode?: string;
1980
+ uploadUrl?: string;
1981
+ }
1982
+ interface SubtitleUploadResult {
1983
+ targets: SubtitleUploadTarget[];
1984
+ }
1985
+ export declare function createSubtitleUpload(projectId: string, videoId: string, items: SubtitleUploadItem[]): Promise<SubtitleUploadResult>;
1986
+ interface CreatePostUploadOptions {
1987
+ projectId: string;
1988
+ feedId: string;
1989
+ orgId?: string;
1990
+ creatorId: string;
1991
+ description?: string;
1992
+ contentType: string;
1993
+ fileName: string;
1994
+ videoQuality?: string;
1995
+ }
1996
+ interface PostUploadResult {
1997
+ postId: string;
1998
+ contentId: string;
1999
+ posterId: string;
2000
+ contentUploadUrl: string;
2001
+ posterUploadUrl: string;
2002
+ }
2003
+ export declare function uploadPost(contentFile: Blob | Uint8Array, posterFile: Blob | Uint8Array, options: CreatePostUploadOptions): Promise<PostUploadResult>;
2004
+ export declare function createPostUpload(options: CreatePostUploadOptions): Promise<PostUploadResult>;
2005
+ export type { AnalyticsContext, AnalyticsEvent, AppliedVolumeSync, AudioTrack, AudioTrackUploadItem, AudioTrackUploadResult, AuthConfig, AutoAdvanceInput, BufferRange, BuildEngagementParams, BuildErrorParams, BuildEventParams, BuildInteractionParams, BuildSessionStartParams, BuildVideoAnalyticsPayloadParams, CSSProperties, CalculateDragPositionOptions, CaptionLangType, CaptionTextSettings, CaptionWindowSettings, Chapter, ChapterWithEnd, ClickDisambiguationState, ClickOutsideOptions, CollectStatsInput, ConnectConfig, ContainerHeightInput, ContentType, ContentViewEvent, ControlsState, CreateImageUploadOptions, CreatePostUploadOptions, CreateVideoUploadOptions, DeriveVolumeSyncOptions, EngagementEvent, ErrorEvent, FeedPlaybackAction, FeedPlaybackDecisionInput, FeedPost, FeedPostsResponse, FileData, FileStatus, FontFamilyKey, GetHotSegmentsOptions, GetPointerOffsetsOptions, GetVideoHeatmapOptions, HandleClickOptions, HandleDoubleClickOptions, HlsController, HlsErrorAction, HlsErrorInput, HlsErrorPayload, HlsErrorRecoveryState, HlsInstance, HotSegment, ImageContainerStyleParams, ImageData, ImageRenderAction, ImageRenderState, ImageUploadResult, InteractionEvent, LoadingDebounceState, LoopRebaseInput, MenuKey, Page, PipReentryOptions, PlaybackHandlerCallbacks, PlaybackPointerOptions, PlayerControlLabels, PlayerLanguage, PlayerMenuLabels, PlayerState, PlayerStateStore, PointerOffsets, Position, PostStoreState, PostUploadResult, PosterDimensions, ProgressBarControls, ProgressBarProps, ProgressBarStartEvent, QualityLevel, Segment, SegmentAnalyticsParams, SessionStartEvent, SettingsState, SetupHlsOptions, ShortcutAction as ShortcutActionType, ShortcutDefinition, ShouldFetchMoreInput, SmartCaptionPositionParams, SubtitleTrack, SubtitleUploadItem, SubtitleUploadResult, UUID, UpdateLoadingStateOptions, VideoAnalyticsPayload, VideoData, VideoHeatmap, VideoKeyboardHandlers, VideoPreloadAttribute, VideoSdkKey, VideoSnapshot, VideoStats, VideoTheme, VideoUploadResult, ViewType, Viewport };