@lightbird/core 0.3.1 → 0.4.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.
package/dist/index.cjs CHANGED
@@ -611,6 +611,78 @@ _MKVPlayer._canPlayNatively = canPlayNatively;
611
611
  _MKVPlayer._workerFactory = null;
612
612
  var MKVPlayer = _MKVPlayer;
613
613
 
614
+ // src/players/hls-player.ts
615
+ var HLS_MIME_HINTS = ["application/x-mpegurl", "application/vnd.apple.mpegurl"];
616
+ function isHlsUrl(url) {
617
+ if (typeof url !== "string" || url.length === 0) return false;
618
+ const lower = url.toLowerCase();
619
+ if (HLS_MIME_HINTS.some((hint) => lower.includes(hint))) return true;
620
+ return lower.split(/[?#]/)[0].endsWith(".m3u8");
621
+ }
622
+ var HLSPlayer = class {
623
+ constructor(url) {
624
+ this.hls = null;
625
+ this.url = url;
626
+ this.playerFile = { url, qualityLevels: [] };
627
+ }
628
+ async initialize(videoElement) {
629
+ const { default: HlsCtor } = await import('hls.js');
630
+ if (!HlsCtor.isSupported()) {
631
+ videoElement.src = this.url;
632
+ return this.playerFile;
633
+ }
634
+ const hls = new HlsCtor();
635
+ this.hls = hls;
636
+ hls.loadSource(this.url);
637
+ hls.attachMedia(videoElement);
638
+ return this.playerFile;
639
+ }
640
+ getAudioTracks() {
641
+ if (!this.hls) return [];
642
+ return this.hls.audioTracks.map((track) => ({
643
+ id: String(track.id),
644
+ name: track.name,
645
+ lang: track.lang || "unknown"
646
+ }));
647
+ }
648
+ getSubtitles() {
649
+ return [];
650
+ }
651
+ switchAudioTrack(trackId) {
652
+ if (this.hls) {
653
+ const id = Number(trackId);
654
+ if (!Number.isNaN(id)) this.hls.audioTrack = id;
655
+ }
656
+ return Promise.resolve();
657
+ }
658
+ switchSubtitle() {
659
+ return Promise.resolve();
660
+ }
661
+ /** Quality renditions — not on `VideoPlayer`; read directly by the quality hook. */
662
+ getQualityLevels() {
663
+ if (!this.hls) return [];
664
+ return this.hls.levels.map((level, index) => ({
665
+ index,
666
+ height: level.height,
667
+ bitrate: level.bitrate,
668
+ name: level.name || (level.height > 0 ? `${level.height}p` : `Level ${index + 1}`)
669
+ }));
670
+ }
671
+ /** Pins a quality level; `-1` restores automatic (ABR) selection. */
672
+ setQualityLevel(levelIndex) {
673
+ if (this.hls) this.hls.currentLevel = levelIndex;
674
+ }
675
+ destroy() {
676
+ if (this.hls) {
677
+ this.hls.destroy();
678
+ this.hls = null;
679
+ }
680
+ }
681
+ static isCompatible(url) {
682
+ return isHlsUrl(url);
683
+ }
684
+ };
685
+
614
686
  // src/video-processor.ts
615
687
  var SimplePlayerAdapter = class {
616
688
  constructor(file, externalSubtitles = []) {
@@ -667,13 +739,21 @@ var MKVPlayerAdapter = class {
667
739
  return this.player.tracksReady;
668
740
  }
669
741
  };
670
- function createVideoPlayer(file, externalSubtitles = [], onProgress) {
671
- if (MKVPlayer.isCompatible(file)) {
672
- return new MKVPlayerAdapter(file, onProgress);
673
- } else if (SimplePlayer.isCompatible(file)) {
674
- return new SimplePlayerAdapter(file, externalSubtitles);
742
+ function createVideoPlayer(source, externalSubtitles = [], onProgress) {
743
+ if (typeof source === "string") {
744
+ if (isHlsUrl(source)) {
745
+ return new HLSPlayer(source);
746
+ }
747
+ throw new Error(
748
+ `createVideoPlayer: unsupported URL "${source}" \u2014 only HLS (.m3u8) stream URLs are supported; pass a File for other formats.`
749
+ );
750
+ }
751
+ if (MKVPlayer.isCompatible(source)) {
752
+ return new MKVPlayerAdapter(source, onProgress);
753
+ } else if (SimplePlayer.isCompatible(source)) {
754
+ return new SimplePlayerAdapter(source, externalSubtitles);
675
755
  } else {
676
- return new SimplePlayerAdapter(file, externalSubtitles);
756
+ return new SimplePlayerAdapter(source, externalSubtitles);
677
757
  }
678
758
  }
679
759
 
@@ -1466,6 +1546,7 @@ exports.DEFAULT_SHORTCUTS = DEFAULT_SHORTCUTS;
1466
1546
  exports.DEFAULT_TRACKERS = DEFAULT_TRACKERS;
1467
1547
  exports.DISCLAIMER_KEY = DISCLAIMER_KEY;
1468
1548
  exports.FLAG_MAGNET_LINK = FLAG_MAGNET_LINK;
1549
+ exports.HLSPlayer = HLSPlayer;
1469
1550
  exports.MKVPlayer = MKVPlayer;
1470
1551
  exports.ProgressEstimator = ProgressEstimator;
1471
1552
  exports.SimplePlayer = SimplePlayer;
@@ -1487,6 +1568,7 @@ exports.getVideoFiles = getVideoFiles;
1487
1568
  exports.getWebTorrentClient = getWebTorrentClient;
1488
1569
  exports.hasAcceptedDisclaimer = hasAcceptedDisclaimer;
1489
1570
  exports.initFeatureFlags = initFeatureFlags;
1571
+ exports.isHlsUrl = isHlsUrl;
1490
1572
  exports.isInteractiveElement = isInteractiveElement;
1491
1573
  exports.isMagnetUri = isMagnetUri;
1492
1574
  exports.isVideoFile = isVideoFile;
package/dist/index.d.cts CHANGED
@@ -83,6 +83,18 @@ interface SubtitleTrackMeta {
83
83
  format: string | null;
84
84
  language: string | null;
85
85
  }
86
+ /** A single HLS quality rendition (e.g. 1080p, 720p). */
87
+ interface QualityLevel {
88
+ index: number;
89
+ height: number;
90
+ bitrate: number;
91
+ name: string;
92
+ }
93
+ /** Result of initialising an HLS stream via `HLSPlayer`. */
94
+ interface HLSPlayerFile {
95
+ url: string;
96
+ qualityLevels: QualityLevel[];
97
+ }
86
98
 
87
99
  interface SimplePlayerFile {
88
100
  name: string;
@@ -168,7 +180,7 @@ declare class MKVPlayer {
168
180
  static isCompatible(file: File): boolean;
169
181
  }
170
182
 
171
- type ProcessedFile = SimplePlayerFile | MKVPlayerFile;
183
+ type ProcessedFile = SimplePlayerFile | MKVPlayerFile | HLSPlayerFile;
172
184
  interface VideoPlayer {
173
185
  initialize(videoElement: HTMLVideoElement): Promise<ProcessedFile>;
174
186
  getAudioTracks(): AudioTrack[];
@@ -185,7 +197,28 @@ interface VideoPlayer {
185
197
  */
186
198
  tracksReady?: Promise<void>;
187
199
  }
188
- declare function createVideoPlayer(file: File, externalSubtitles?: File[], onProgress?: (progress: number) => void): VideoPlayer;
200
+ declare function createVideoPlayer(source: File | string, externalSubtitles?: File[], onProgress?: (progress: number) => void): VideoPlayer;
201
+
202
+ /** True for HLS playlist URLs — a `.m3u8` path or an HLS MIME hint. */
203
+ declare function isHlsUrl(url: string): boolean;
204
+ /** Plays HLS (`.m3u8`) streams via hls.js, falling back to native HLS (Safari). */
205
+ declare class HLSPlayer implements VideoPlayer {
206
+ private readonly url;
207
+ private readonly playerFile;
208
+ private hls;
209
+ constructor(url: string);
210
+ initialize(videoElement: HTMLVideoElement): Promise<HLSPlayerFile>;
211
+ getAudioTracks(): AudioTrack[];
212
+ getSubtitles(): Subtitle[];
213
+ switchAudioTrack(trackId: string): Promise<void>;
214
+ switchSubtitle(): Promise<void>;
215
+ /** Quality renditions — not on `VideoPlayer`; read directly by the quality hook. */
216
+ getQualityLevels(): QualityLevel[];
217
+ /** Pins a quality level; `-1` restores automatic (ABR) selection. */
218
+ setQualityLevel(levelIndex: number): void;
219
+ destroy(): void;
220
+ static isCompatible(url: string): boolean;
221
+ }
189
222
 
190
223
  declare class UniversalSubtitleManager {
191
224
  private records;
@@ -393,4 +426,4 @@ declare class ProgressEstimator {
393
426
  declare function getFFmpeg(): Promise<FFmpeg>;
394
427
  declare function resetFFmpeg(): void;
395
428
 
396
- export { ASSRenderer, type AudioTrack, type AudioTrackMeta, CancellationError, type Chapter, DEFAULT_SHORTCUTS, DEFAULT_TRACKERS, DISCLAIMER_KEY, FLAG_MAGNET_LINK, type LightBirdConfig, MKVPlayer, type MKVPlayerFile, type MediaErrorType, type ParsedMediaError, type PlaylistItem, type ProcessedFile, ProgressEstimator, type ShortcutAction, type ShortcutBinding, SimplePlayer, type SimplePlayerFile, type Subtitle, SubtitleConverter, type SubtitleCue, type SubtitleTrackMeta, type TorrentStatus, UniversalSubtitleManager, VIDEO_EXTENSIONS, type VideoFilters, type VideoMetadata, type VideoPlayer, acceptDisclaimer, applyOffsetToVtt, captureVideoThumbnail, configureLightBird, createOffsetVttUrl, createVideoPlayer, destroyWebTorrentClient, exportPlaylist, extractNativeMetadata, formatShortcutKey, getFFmpeg, getVideoFiles, getWebTorrentClient, hasAcceptedDisclaimer, initFeatureFlags, isInteractiveElement, isMagnetUri, isVideoFile, loadShortcuts, matchesShortcut, parseChaptersFromFFmpegLog, parseChaptersFromVtt, parseM3U8, parseMediaError, resetFFmpeg, saveShortcuts, validateFile };
429
+ export { ASSRenderer, type AudioTrack, type AudioTrackMeta, CancellationError, type Chapter, DEFAULT_SHORTCUTS, DEFAULT_TRACKERS, DISCLAIMER_KEY, FLAG_MAGNET_LINK, HLSPlayer, type HLSPlayerFile, type LightBirdConfig, MKVPlayer, type MKVPlayerFile, type MediaErrorType, type ParsedMediaError, type PlaylistItem, type ProcessedFile, ProgressEstimator, type QualityLevel, type ShortcutAction, type ShortcutBinding, SimplePlayer, type SimplePlayerFile, type Subtitle, SubtitleConverter, type SubtitleCue, type SubtitleTrackMeta, type TorrentStatus, UniversalSubtitleManager, VIDEO_EXTENSIONS, type VideoFilters, type VideoMetadata, type VideoPlayer, acceptDisclaimer, applyOffsetToVtt, captureVideoThumbnail, configureLightBird, createOffsetVttUrl, createVideoPlayer, destroyWebTorrentClient, exportPlaylist, extractNativeMetadata, formatShortcutKey, getFFmpeg, getVideoFiles, getWebTorrentClient, hasAcceptedDisclaimer, initFeatureFlags, isHlsUrl, isInteractiveElement, isMagnetUri, isVideoFile, loadShortcuts, matchesShortcut, parseChaptersFromFFmpegLog, parseChaptersFromVtt, parseM3U8, parseMediaError, resetFFmpeg, saveShortcuts, validateFile };
package/dist/index.d.ts CHANGED
@@ -83,6 +83,18 @@ interface SubtitleTrackMeta {
83
83
  format: string | null;
84
84
  language: string | null;
85
85
  }
86
+ /** A single HLS quality rendition (e.g. 1080p, 720p). */
87
+ interface QualityLevel {
88
+ index: number;
89
+ height: number;
90
+ bitrate: number;
91
+ name: string;
92
+ }
93
+ /** Result of initialising an HLS stream via `HLSPlayer`. */
94
+ interface HLSPlayerFile {
95
+ url: string;
96
+ qualityLevels: QualityLevel[];
97
+ }
86
98
 
87
99
  interface SimplePlayerFile {
88
100
  name: string;
@@ -168,7 +180,7 @@ declare class MKVPlayer {
168
180
  static isCompatible(file: File): boolean;
169
181
  }
170
182
 
171
- type ProcessedFile = SimplePlayerFile | MKVPlayerFile;
183
+ type ProcessedFile = SimplePlayerFile | MKVPlayerFile | HLSPlayerFile;
172
184
  interface VideoPlayer {
173
185
  initialize(videoElement: HTMLVideoElement): Promise<ProcessedFile>;
174
186
  getAudioTracks(): AudioTrack[];
@@ -185,7 +197,28 @@ interface VideoPlayer {
185
197
  */
186
198
  tracksReady?: Promise<void>;
187
199
  }
188
- declare function createVideoPlayer(file: File, externalSubtitles?: File[], onProgress?: (progress: number) => void): VideoPlayer;
200
+ declare function createVideoPlayer(source: File | string, externalSubtitles?: File[], onProgress?: (progress: number) => void): VideoPlayer;
201
+
202
+ /** True for HLS playlist URLs — a `.m3u8` path or an HLS MIME hint. */
203
+ declare function isHlsUrl(url: string): boolean;
204
+ /** Plays HLS (`.m3u8`) streams via hls.js, falling back to native HLS (Safari). */
205
+ declare class HLSPlayer implements VideoPlayer {
206
+ private readonly url;
207
+ private readonly playerFile;
208
+ private hls;
209
+ constructor(url: string);
210
+ initialize(videoElement: HTMLVideoElement): Promise<HLSPlayerFile>;
211
+ getAudioTracks(): AudioTrack[];
212
+ getSubtitles(): Subtitle[];
213
+ switchAudioTrack(trackId: string): Promise<void>;
214
+ switchSubtitle(): Promise<void>;
215
+ /** Quality renditions — not on `VideoPlayer`; read directly by the quality hook. */
216
+ getQualityLevels(): QualityLevel[];
217
+ /** Pins a quality level; `-1` restores automatic (ABR) selection. */
218
+ setQualityLevel(levelIndex: number): void;
219
+ destroy(): void;
220
+ static isCompatible(url: string): boolean;
221
+ }
189
222
 
190
223
  declare class UniversalSubtitleManager {
191
224
  private records;
@@ -393,4 +426,4 @@ declare class ProgressEstimator {
393
426
  declare function getFFmpeg(): Promise<FFmpeg>;
394
427
  declare function resetFFmpeg(): void;
395
428
 
396
- export { ASSRenderer, type AudioTrack, type AudioTrackMeta, CancellationError, type Chapter, DEFAULT_SHORTCUTS, DEFAULT_TRACKERS, DISCLAIMER_KEY, FLAG_MAGNET_LINK, type LightBirdConfig, MKVPlayer, type MKVPlayerFile, type MediaErrorType, type ParsedMediaError, type PlaylistItem, type ProcessedFile, ProgressEstimator, type ShortcutAction, type ShortcutBinding, SimplePlayer, type SimplePlayerFile, type Subtitle, SubtitleConverter, type SubtitleCue, type SubtitleTrackMeta, type TorrentStatus, UniversalSubtitleManager, VIDEO_EXTENSIONS, type VideoFilters, type VideoMetadata, type VideoPlayer, acceptDisclaimer, applyOffsetToVtt, captureVideoThumbnail, configureLightBird, createOffsetVttUrl, createVideoPlayer, destroyWebTorrentClient, exportPlaylist, extractNativeMetadata, formatShortcutKey, getFFmpeg, getVideoFiles, getWebTorrentClient, hasAcceptedDisclaimer, initFeatureFlags, isInteractiveElement, isMagnetUri, isVideoFile, loadShortcuts, matchesShortcut, parseChaptersFromFFmpegLog, parseChaptersFromVtt, parseM3U8, parseMediaError, resetFFmpeg, saveShortcuts, validateFile };
429
+ export { ASSRenderer, type AudioTrack, type AudioTrackMeta, CancellationError, type Chapter, DEFAULT_SHORTCUTS, DEFAULT_TRACKERS, DISCLAIMER_KEY, FLAG_MAGNET_LINK, HLSPlayer, type HLSPlayerFile, type LightBirdConfig, MKVPlayer, type MKVPlayerFile, type MediaErrorType, type ParsedMediaError, type PlaylistItem, type ProcessedFile, ProgressEstimator, type QualityLevel, type ShortcutAction, type ShortcutBinding, SimplePlayer, type SimplePlayerFile, type Subtitle, SubtitleConverter, type SubtitleCue, type SubtitleTrackMeta, type TorrentStatus, UniversalSubtitleManager, VIDEO_EXTENSIONS, type VideoFilters, type VideoMetadata, type VideoPlayer, acceptDisclaimer, applyOffsetToVtt, captureVideoThumbnail, configureLightBird, createOffsetVttUrl, createVideoPlayer, destroyWebTorrentClient, exportPlaylist, extractNativeMetadata, formatShortcutKey, getFFmpeg, getVideoFiles, getWebTorrentClient, hasAcceptedDisclaimer, initFeatureFlags, isHlsUrl, isInteractiveElement, isMagnetUri, isVideoFile, loadShortcuts, matchesShortcut, parseChaptersFromFFmpegLog, parseChaptersFromVtt, parseM3U8, parseMediaError, resetFFmpeg, saveShortcuts, validateFile };
package/dist/index.js CHANGED
@@ -608,6 +608,78 @@ _MKVPlayer._canPlayNatively = canPlayNatively;
608
608
  _MKVPlayer._workerFactory = null;
609
609
  var MKVPlayer = _MKVPlayer;
610
610
 
611
+ // src/players/hls-player.ts
612
+ var HLS_MIME_HINTS = ["application/x-mpegurl", "application/vnd.apple.mpegurl"];
613
+ function isHlsUrl(url) {
614
+ if (typeof url !== "string" || url.length === 0) return false;
615
+ const lower = url.toLowerCase();
616
+ if (HLS_MIME_HINTS.some((hint) => lower.includes(hint))) return true;
617
+ return lower.split(/[?#]/)[0].endsWith(".m3u8");
618
+ }
619
+ var HLSPlayer = class {
620
+ constructor(url) {
621
+ this.hls = null;
622
+ this.url = url;
623
+ this.playerFile = { url, qualityLevels: [] };
624
+ }
625
+ async initialize(videoElement) {
626
+ const { default: HlsCtor } = await import('hls.js');
627
+ if (!HlsCtor.isSupported()) {
628
+ videoElement.src = this.url;
629
+ return this.playerFile;
630
+ }
631
+ const hls = new HlsCtor();
632
+ this.hls = hls;
633
+ hls.loadSource(this.url);
634
+ hls.attachMedia(videoElement);
635
+ return this.playerFile;
636
+ }
637
+ getAudioTracks() {
638
+ if (!this.hls) return [];
639
+ return this.hls.audioTracks.map((track) => ({
640
+ id: String(track.id),
641
+ name: track.name,
642
+ lang: track.lang || "unknown"
643
+ }));
644
+ }
645
+ getSubtitles() {
646
+ return [];
647
+ }
648
+ switchAudioTrack(trackId) {
649
+ if (this.hls) {
650
+ const id = Number(trackId);
651
+ if (!Number.isNaN(id)) this.hls.audioTrack = id;
652
+ }
653
+ return Promise.resolve();
654
+ }
655
+ switchSubtitle() {
656
+ return Promise.resolve();
657
+ }
658
+ /** Quality renditions — not on `VideoPlayer`; read directly by the quality hook. */
659
+ getQualityLevels() {
660
+ if (!this.hls) return [];
661
+ return this.hls.levels.map((level, index) => ({
662
+ index,
663
+ height: level.height,
664
+ bitrate: level.bitrate,
665
+ name: level.name || (level.height > 0 ? `${level.height}p` : `Level ${index + 1}`)
666
+ }));
667
+ }
668
+ /** Pins a quality level; `-1` restores automatic (ABR) selection. */
669
+ setQualityLevel(levelIndex) {
670
+ if (this.hls) this.hls.currentLevel = levelIndex;
671
+ }
672
+ destroy() {
673
+ if (this.hls) {
674
+ this.hls.destroy();
675
+ this.hls = null;
676
+ }
677
+ }
678
+ static isCompatible(url) {
679
+ return isHlsUrl(url);
680
+ }
681
+ };
682
+
611
683
  // src/video-processor.ts
612
684
  var SimplePlayerAdapter = class {
613
685
  constructor(file, externalSubtitles = []) {
@@ -664,13 +736,21 @@ var MKVPlayerAdapter = class {
664
736
  return this.player.tracksReady;
665
737
  }
666
738
  };
667
- function createVideoPlayer(file, externalSubtitles = [], onProgress) {
668
- if (MKVPlayer.isCompatible(file)) {
669
- return new MKVPlayerAdapter(file, onProgress);
670
- } else if (SimplePlayer.isCompatible(file)) {
671
- return new SimplePlayerAdapter(file, externalSubtitles);
739
+ function createVideoPlayer(source, externalSubtitles = [], onProgress) {
740
+ if (typeof source === "string") {
741
+ if (isHlsUrl(source)) {
742
+ return new HLSPlayer(source);
743
+ }
744
+ throw new Error(
745
+ `createVideoPlayer: unsupported URL "${source}" \u2014 only HLS (.m3u8) stream URLs are supported; pass a File for other formats.`
746
+ );
747
+ }
748
+ if (MKVPlayer.isCompatible(source)) {
749
+ return new MKVPlayerAdapter(source, onProgress);
750
+ } else if (SimplePlayer.isCompatible(source)) {
751
+ return new SimplePlayerAdapter(source, externalSubtitles);
672
752
  } else {
673
- return new SimplePlayerAdapter(file, externalSubtitles);
753
+ return new SimplePlayerAdapter(source, externalSubtitles);
674
754
  }
675
755
  }
676
756
 
@@ -1457,4 +1537,4 @@ function resetFFmpeg() {
1457
1537
  loading = null;
1458
1538
  }
1459
1539
 
1460
- export { ASSRenderer, CancellationError, DEFAULT_SHORTCUTS, DEFAULT_TRACKERS, DISCLAIMER_KEY, FLAG_MAGNET_LINK, MKVPlayer, ProgressEstimator, SimplePlayer, SubtitleConverter, UniversalSubtitleManager, VIDEO_EXTENSIONS, acceptDisclaimer, applyOffsetToVtt, captureVideoThumbnail, configureLightBird, createOffsetVttUrl, createVideoPlayer, destroyWebTorrentClient, exportPlaylist, extractNativeMetadata, formatShortcutKey, getFFmpeg, getVideoFiles, getWebTorrentClient, hasAcceptedDisclaimer, initFeatureFlags, isInteractiveElement, isMagnetUri, isVideoFile, loadShortcuts, matchesShortcut, parseChaptersFromFFmpegLog, parseChaptersFromVtt, parseM3U8, parseMediaError, resetFFmpeg, saveShortcuts, validateFile };
1540
+ export { ASSRenderer, CancellationError, DEFAULT_SHORTCUTS, DEFAULT_TRACKERS, DISCLAIMER_KEY, FLAG_MAGNET_LINK, HLSPlayer, MKVPlayer, ProgressEstimator, SimplePlayer, SubtitleConverter, UniversalSubtitleManager, VIDEO_EXTENSIONS, acceptDisclaimer, applyOffsetToVtt, captureVideoThumbnail, configureLightBird, createOffsetVttUrl, createVideoPlayer, destroyWebTorrentClient, exportPlaylist, extractNativeMetadata, formatShortcutKey, getFFmpeg, getVideoFiles, getWebTorrentClient, hasAcceptedDisclaimer, initFeatureFlags, isHlsUrl, isInteractiveElement, isMagnetUri, isVideoFile, loadShortcuts, matchesShortcut, parseChaptersFromFFmpegLog, parseChaptersFromVtt, parseM3U8, parseMediaError, resetFFmpeg, saveShortcuts, validateFile };
@@ -95,6 +95,18 @@ interface SubtitleTrackMeta {
95
95
  format: string | null;
96
96
  language: string | null;
97
97
  }
98
+ /** A single HLS quality rendition (e.g. 1080p, 720p). */
99
+ interface QualityLevel {
100
+ index: number;
101
+ height: number;
102
+ bitrate: number;
103
+ name: string;
104
+ }
105
+ /** Result of initialising an HLS stream via `HLSPlayer`. */
106
+ interface HLSPlayerFile {
107
+ url: string;
108
+ qualityLevels: QualityLevel[];
109
+ }
98
110
 
99
111
  declare function useVideoFilters(videoRef: RefObject<HTMLVideoElement | null>): {
100
112
  filters: VideoFilters;
@@ -236,7 +248,7 @@ interface MKVPlayerFile {
236
248
  activeSubtitleTrack: string;
237
249
  }
238
250
 
239
- type ProcessedFile = SimplePlayerFile | MKVPlayerFile;
251
+ type ProcessedFile = SimplePlayerFile | MKVPlayerFile | HLSPlayerFile;
240
252
  interface VideoPlayer {
241
253
  initialize(videoElement: HTMLVideoElement): Promise<ProcessedFile>;
242
254
  getAudioTracks(): AudioTrack[];
@@ -95,6 +95,18 @@ interface SubtitleTrackMeta {
95
95
  format: string | null;
96
96
  language: string | null;
97
97
  }
98
+ /** A single HLS quality rendition (e.g. 1080p, 720p). */
99
+ interface QualityLevel {
100
+ index: number;
101
+ height: number;
102
+ bitrate: number;
103
+ name: string;
104
+ }
105
+ /** Result of initialising an HLS stream via `HLSPlayer`. */
106
+ interface HLSPlayerFile {
107
+ url: string;
108
+ qualityLevels: QualityLevel[];
109
+ }
98
110
 
99
111
  declare function useVideoFilters(videoRef: RefObject<HTMLVideoElement | null>): {
100
112
  filters: VideoFilters;
@@ -236,7 +248,7 @@ interface MKVPlayerFile {
236
248
  activeSubtitleTrack: string;
237
249
  }
238
250
 
239
- type ProcessedFile = SimplePlayerFile | MKVPlayerFile;
251
+ type ProcessedFile = SimplePlayerFile | MKVPlayerFile | HLSPlayerFile;
240
252
  interface VideoPlayer {
241
253
  initialize(videoElement: HTMLVideoElement): Promise<ProcessedFile>;
242
254
  getAudioTracks(): AudioTrack[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightbird/core",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Client-side video player engine. Plays MKV, MP4, WebM with full subtitle, audio track, and chapter support. No server required.",
5
5
  "license": "MIT",
6
6
  "author": "Punyam Singh",
@@ -57,6 +57,7 @@
57
57
  "@openfeature/unleash-web-provider": "^0.1.1",
58
58
  "@openfeature/web-sdk": "^1.6.0",
59
59
  "ass-compiler": "^0.1.16",
60
+ "hls.js": "^1.6.16",
60
61
  "webtorrent": "^2.8.5"
61
62
  },
62
63
  "optionalDependencies": {