libbitsub 1.10.2 → 1.11.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 (89) hide show
  1. package/README.md +184 -34
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/integrations/hlsjs.d.ts +45 -0
  7. package/dist/integrations/hlsjs.d.ts.map +1 -0
  8. package/dist/integrations/hlsjs.js +121 -0
  9. package/dist/integrations/hlsjs.js.map +1 -0
  10. package/dist/integrations/index.d.ts +11 -0
  11. package/dist/integrations/index.d.ts.map +1 -0
  12. package/dist/integrations/index.js +11 -0
  13. package/dist/integrations/index.js.map +1 -0
  14. package/dist/integrations/react.d.ts +55 -0
  15. package/dist/integrations/react.d.ts.map +1 -0
  16. package/dist/integrations/react.js +127 -0
  17. package/dist/integrations/react.js.map +1 -0
  18. package/dist/integrations/shaka.d.ts +38 -0
  19. package/dist/integrations/shaka.d.ts.map +1 -0
  20. package/dist/integrations/shaka.js +71 -0
  21. package/dist/integrations/shaka.js.map +1 -0
  22. package/dist/integrations/shared.d.ts +41 -0
  23. package/dist/integrations/shared.d.ts.map +1 -0
  24. package/dist/integrations/shared.js +123 -0
  25. package/dist/integrations/shared.js.map +1 -0
  26. package/dist/integrations/videojs.d.ts +85 -0
  27. package/dist/integrations/videojs.d.ts.map +1 -0
  28. package/dist/integrations/videojs.js +111 -0
  29. package/dist/integrations/videojs.js.map +1 -0
  30. package/dist/ts/diagnostics.d.ts.map +1 -1
  31. package/dist/ts/diagnostics.js.map +1 -1
  32. package/dist/ts/frame-export.d.ts.map +1 -1
  33. package/dist/ts/frame-export.js +4 -4
  34. package/dist/ts/frame-export.js.map +1 -1
  35. package/dist/ts/parsers.d.ts +7 -6
  36. package/dist/ts/parsers.d.ts.map +1 -1
  37. package/dist/ts/parsers.js +76 -13
  38. package/dist/ts/parsers.js.map +1 -1
  39. package/dist/ts/range-loader.d.ts +31 -0
  40. package/dist/ts/range-loader.d.ts.map +1 -0
  41. package/dist/ts/range-loader.js +220 -0
  42. package/dist/ts/range-loader.js.map +1 -0
  43. package/dist/ts/renderers.d.ts +14 -0
  44. package/dist/ts/renderers.d.ts.map +1 -1
  45. package/dist/ts/renderers.js +445 -162
  46. package/dist/ts/renderers.js.map +1 -1
  47. package/dist/ts/types.d.ts +51 -1
  48. package/dist/ts/types.d.ts.map +1 -1
  49. package/dist/ts/utils.d.ts.map +1 -1
  50. package/dist/ts/utils.js.map +1 -1
  51. package/dist/ts/wasm.d.ts +2 -0
  52. package/dist/ts/wasm.d.ts.map +1 -1
  53. package/dist/ts/wasm.js +12 -0
  54. package/dist/ts/wasm.js.map +1 -1
  55. package/dist/ts/webgl2-renderer.d.ts +9 -0
  56. package/dist/ts/webgl2-renderer.d.ts.map +1 -1
  57. package/dist/ts/webgl2-renderer.js +34 -0
  58. package/dist/ts/webgl2-renderer.js.map +1 -1
  59. package/dist/ts/webgpu-renderer.d.ts +9 -0
  60. package/dist/ts/webgpu-renderer.d.ts.map +1 -1
  61. package/dist/ts/webgpu-renderer.js +70 -2
  62. package/dist/ts/webgpu-renderer.js.map +1 -1
  63. package/dist/ts/worker.d.ts +11 -0
  64. package/dist/ts/worker.d.ts.map +1 -1
  65. package/dist/ts/worker.js +229 -161
  66. package/dist/ts/worker.js.map +1 -1
  67. package/dist/wrapper.d.ts +3 -1
  68. package/dist/wrapper.d.ts.map +1 -1
  69. package/dist/wrapper.js +2 -0
  70. package/dist/wrapper.js.map +1 -1
  71. package/examples/README.md +38 -0
  72. package/examples/hlsjs/README.md +53 -0
  73. package/examples/react/README.md +60 -0
  74. package/examples/shaka/README.md +61 -0
  75. package/examples/videojs/README.md +55 -0
  76. package/package.json +64 -7
  77. package/pkg/README.md +184 -34
  78. package/pkg/libbitsub.d.ts +14 -0
  79. package/pkg/libbitsub.js +50 -0
  80. package/pkg/libbitsub_bg.wasm +0 -0
  81. package/pkg/libbitsub_bg.wasm.d.ts +7 -0
  82. package/pkg/package.json +1 -1
  83. package/src/integrations/hlsjs.ts +154 -0
  84. package/src/integrations/index.ts +36 -0
  85. package/src/integrations/react.tsx +170 -0
  86. package/src/integrations/shaka.ts +92 -0
  87. package/src/integrations/shared.ts +170 -0
  88. package/src/integrations/videojs.ts +200 -0
  89. package/src/wrapper.ts +12 -0
package/README.md CHANGED
@@ -11,6 +11,7 @@ Started as a fork of Arcus92's [libpgs-js](https://github.com/Arcus92/libpgs-js)
11
11
  - Matroska `.mks` extraction for embedded `S_VOBSUB` tracks
12
12
  - WebGPU, WebGL2, and Canvas2D rendering with automatic fallback
13
13
  - Worker-backed parsing/rendering for large subtitle files
14
+ - HTTP Range / streaming loads for large `.sup`, `.sub`, `.idx`, and `.mks` assets (progressive indexing where feasible)
14
15
  - Rich layout controls: scale, aspect mode, horizontal/vertical offsets, alignment, bottom padding, safe area, opacity
15
16
  - Cue metadata and parser introspection APIs
16
17
  - Rendered-frame export helpers for ImageData, ImageBitmap, Blob, and custom canvas targets
@@ -18,6 +19,7 @@ Started as a fork of Arcus92's [libpgs-js](https://github.com/Arcus92/libpgs-js)
18
19
  - Automatic format detection and unified loading helpers
19
20
  - First-class diagnostics with structured error codes, warning hooks, and render/cache snapshots
20
21
  - TypeScript support with exported event and metadata types
22
+ - Optional player integrations for Video.js, Shaka Player, hls.js, and React (core stays dependency-free)
21
23
 
22
24
  ## Showcase
23
25
 
@@ -67,11 +69,11 @@ deno add jsr:@altq/libbitsub
67
69
 
68
70
  In most bundler-based projects, no manual worker setup is required. `libbitsub` now resolves the WASM asset relative to the package module URL, so bundlers such as Vite, webpack, and Rollup can emit the asset automatically.
69
71
 
70
- If your app serves package files in a way that does not expose that emitted WASM asset to the browser, you can still provide the legacy public fallback by copying the WASM file to `/libbitsub/libbitsub_bg.wasm`:
72
+ If your app serves package files in a way that does not expose that emitted WASM asset to the browser, you can still provide the legacy public fallback by copying the WASM file and its JS glue to `/libbitsub/`:
71
73
 
72
74
  ```bash
73
75
  mkdir -p public/libbitsub
74
- cp node_modules/libbitsub/pkg/libbitsub_bg.wasm public/libbitsub/
76
+ cp node_modules/libbitsub/pkg/libbitsub_bg.wasm node_modules/libbitsub/pkg/libbitsub.js public/libbitsub/
75
77
  ```
76
78
 
77
79
  The worker is still created inline. `workerUrl` remains in the option type only for compatibility and does not change runtime behavior.
@@ -110,6 +112,129 @@ const parser = new PgsParser()
110
112
 
111
113
  Calling `initWasm()` multiple times is safe (it deduplicates).
112
114
 
115
+ ### Worker prewarm (TV / players)
116
+
117
+ On devices where the first subtitle track switch should not pay worker + WASM startup cost (for example TV apps), prewarm the shared parsing worker during app startup:
118
+
119
+ ```ts
120
+ import { warmup, ready, PgsRenderer } from 'libbitsub'
121
+
122
+ // Fire-and-forget at app boot (safe to call multiple times).
123
+ void warmup()
124
+
125
+ // Before the user changes tracks, ensure the worker is ready.
126
+ await ready()
127
+
128
+ const renderer = new PgsRenderer({ video: videoElement, subContent: trackBytes })
129
+ ```
130
+
131
+ `warmup()` and `ready()` share a single worker-init promise with renderer creation. The shared worker is only published after in-worker WASM initialization succeeds. When Web Workers are unavailable, both resolve immediately and renderers use the main thread.
132
+
133
+ ### Range / streaming loads (TV / slow networks)
134
+
135
+ URL-based loads (`subUrl` / `idxUrl`) use progressive fetch by default:
136
+
137
+ - Probe HTTP Range support and, for large assets, download with Range chunks when the origin allows it
138
+ - Stream the response body otherwise and report `load-progress` events
139
+ - **PGS (`.sup`)**: feed chunks into the parser as they arrive so cues can be indexed before the full file finishes
140
+ - **VobSub (`.idx` + `.sub`)**: parse the small `.idx` first for timestamps, then stream/Range-download the `.sub` body and attach packets
141
+ - **MKS**: stream/Range-download the container first (Matroska extraction still needs the assembled payload), then parse
142
+ - **In-memory** `subContent` / `idxContent` remains the simple full-buffer path
143
+
144
+ ```ts
145
+ import { PgsRenderer } from 'libbitsub'
146
+
147
+ const renderer = new PgsRenderer({
148
+ video: videoElement,
149
+ subUrl: '/subtitles/movie.sup',
150
+ // streamingLoad: true, // default
151
+ // rangeRequests: true, // default
152
+ onEvent: (event) => {
153
+ if (event.type === 'load-progress') {
154
+ console.log(event.strategy, event.loadedBytes, event.totalBytes, event.indexedCues)
155
+ }
156
+ if (event.type === 'indexed') {
157
+ console.log('cues ready', event.metadata.cueCount, event.partial ? '(partial)' : '(final)')
158
+ }
159
+ }
160
+ })
161
+ ```
162
+
163
+ Disable progressive behavior when you want a single blocking GET:
164
+
165
+ ```ts
166
+ new PgsRenderer({ video, subUrl, streamingLoad: false, rangeRequests: false })
167
+ ```
168
+
169
+ Low-level helpers are also exported: `probeRangeSupport()`, `fetchSubtitleAsset()`, and `fetchSubtitleText()`.
170
+
171
+ ## Player integrations
172
+
173
+ Optional adapters ship as **subpath exports**. They wrap the high-level renderers for common players while keeping the core package free of player/React dependencies (peer deps are optional and only needed when you import that adapter).
174
+
175
+ | Import | Adapter | Optional peer |
176
+ | ------------------------ | ---------------------------------------- | ------------------- |
177
+ | `libbitsub/videojs` | Video.js plugin (`registerBitSubPlugin`) | `video.js` >= 7 |
178
+ | `libbitsub/shaka` | `attachBitSubToShaka(player, options)` | `shaka-player` >= 4 |
179
+ | `libbitsub/hlsjs` | `attachBitSubToHls(hls, options)` | `hls.js` >= 1 |
180
+ | `libbitsub/react` | `useBitSub` / `BitSubOverlay` | `react` >= 18 |
181
+ | `libbitsub/integrations` | Shared `attachBitSub` controller | — |
182
+
183
+ Copy-paste recipes live under [`examples/`](./examples).
184
+
185
+ ### Video.js
186
+
187
+ ```ts
188
+ import videojs from 'video.js'
189
+ import { registerBitSubPlugin } from 'libbitsub/videojs'
190
+
191
+ registerBitSubPlugin(videojs)
192
+ const player = videojs('my-video')
193
+ const bitsub = player.bitsub({ subUrl: '/subs/movie.sup' })
194
+ bitsub.load({ subUrl: '/subs/other.sup' })
195
+ ```
196
+
197
+ ### Shaka Player
198
+
199
+ ```ts
200
+ import { attachBitSubToShaka } from 'libbitsub/shaka'
201
+
202
+ const bitsub = attachBitSubToShaka(player, { subUrl: '/subs/movie.sup' })
203
+ // later
204
+ bitsub.dispose()
205
+ ```
206
+
207
+ ### hls.js
208
+
209
+ ```ts
210
+ import Hls from 'hls.js'
211
+ import { attachBitSubToHls } from 'libbitsub/hlsjs'
212
+
213
+ const hls = new Hls()
214
+ hls.loadSource(url)
215
+ hls.attachMedia(video)
216
+ const bitsub = attachBitSubToHls(hls, { subUrl: '/subs/movie.sup' })
217
+ ```
218
+
219
+ ### React
220
+
221
+ ```tsx
222
+ import { useRef } from 'react'
223
+ import { useBitSub } from 'libbitsub/react'
224
+
225
+ function Player({ src, subUrl }: { src: string; subUrl: string }) {
226
+ const videoRef = useRef<HTMLVideoElement>(null)
227
+ useBitSub(videoRef, { subUrl })
228
+ return (
229
+ <div style={{ position: 'relative' }}>
230
+ <video ref={videoRef} src={src} controls playsInline />
231
+ </div>
232
+ )
233
+ }
234
+ ```
235
+
236
+ Bitmap PGS/VobSub/MKS tracks are external canvas overlays, not native HTML/TextTrack entries. Prefer deep imports so unused adapters stay out of your bundle.
237
+
113
238
  ## High-level video renderers
114
239
 
115
240
  The high-level API manages subtitle loading, canvas overlay creation, playback sync, resize handling, worker usage, and renderer fallback.
@@ -207,16 +332,16 @@ renderer.resetDisplaySettings()
207
332
 
208
333
  `SubtitleDisplaySettings`:
209
334
 
210
- | Field | Type | Range / values | Meaning |
211
- | --- | --- | --- | --- |
212
- | `scale` | number | `0.1` to `3.0` | Overall subtitle scale |
213
- | `aspectMode` | `'stretch' \| 'contain' \| 'cover'` | fixed set | How subtitle screen coordinates map into the visible video box |
214
- | `verticalOffset` | number | `-50` to `50` | Vertical movement as percent of video height |
215
- | `horizontalOffset` | number | `-50` to `50` | Horizontal movement as percent of video width |
216
- | `horizontalAlign` | `'left' \| 'center' \| 'right'` | fixed set | Anchor used when scaling subtitle groups |
217
- | `bottomPadding` | number | `0` to `50` | Extra padding from the bottom edge |
218
- | `safeArea` | number | `0` to `25` | Clamp subtitles inside a video-safe area |
219
- | `opacity` | number | `0.0` to `1.0` | Global subtitle opacity |
335
+ | Field | Type | Range / values | Meaning |
336
+ | ------------------ | ----------------------------------- | -------------- | -------------------------------------------------------------- |
337
+ | `scale` | number | `0.1` to `3.0` | Overall subtitle scale |
338
+ | `aspectMode` | `'stretch' \| 'contain' \| 'cover'` | fixed set | How subtitle screen coordinates map into the visible video box |
339
+ | `verticalOffset` | number | `-50` to `50` | Vertical movement as percent of video height |
340
+ | `horizontalOffset` | number | `-50` to `50` | Horizontal movement as percent of video width |
341
+ | `horizontalAlign` | `'left' \| 'center' \| 'right'` | fixed set | Anchor used when scaling subtitle groups |
342
+ | `bottomPadding` | number | `0` to `50` | Extra padding from the bottom edge |
343
+ | `safeArea` | number | `0` to `25` | Clamp subtitles inside a video-safe area |
344
+ | `opacity` | number | `0.0` to `1.0` | Global subtitle opacity |
220
345
 
221
346
  ## Metadata and introspection
222
347
 
@@ -291,14 +416,7 @@ Like `UnifiedSubtitleParser.loadAuto()`, this is a low-level in-memory API: pass
291
416
  Low-level parser output can be flattened into a single exportable frame for previews, editors, snapshots, fixture generation, or visual diffing.
292
417
 
293
418
  ```ts
294
- import {
295
- PgsParser,
296
- initWasm,
297
- renderFrameData,
298
- toBlob,
299
- toCanvas,
300
- toImageBitmap
301
- } from 'libbitsub'
419
+ import { PgsParser, initWasm, renderFrameData, toBlob, toCanvas, toImageBitmap } from 'libbitsub'
302
420
 
303
421
  await initWasm()
304
422
 
@@ -385,7 +503,7 @@ Structured diagnostic error codes currently include:
385
503
  - `WORKER_FALLBACK`
386
504
  - `UNKNOWN`
387
505
 
388
- Warnings use a smaller code set focused on non-fatal conditions such as malformed bitmap buffers, worker fallback, and missing PGS palettes during render.
506
+ Warnings use a smaller code set focused on non-fatal conditions such as malformed bitmap buffers, worker fallback, progressive/Range fallback (`RANGE_FALLBACK`), and missing PGS palettes during render.
389
507
 
390
508
  ## MKS security and corruption checks
391
509
 
@@ -415,6 +533,8 @@ const renderer = new PgsRenderer({
415
533
  onEvent: (event) => {
416
534
  switch (event.type) {
417
535
  case 'loading':
536
+ case 'load-progress':
537
+ case 'indexed':
418
538
  case 'loaded':
419
539
  case 'error':
420
540
  case 'warning':
@@ -482,17 +602,17 @@ renderer.dispose()
482
602
 
483
603
  Emitted events:
484
604
 
485
- | Event | Payload |
486
- | --- | --- |
487
- | `loading` | subtitle format |
488
- | `loaded` | subtitle format and parser metadata |
489
- | `error` | subtitle format and `SubtitleDiagnosticErrorLike` |
490
- | `warning` | `SubtitleDiagnosticWarning` |
491
- | `renderer-change` | active backend: `webgpu`, `webgl2`, or `canvas2d` |
492
- | `worker-state` | whether worker mode is enabled, ready, fallback status, and the active session ID |
493
- | `cache-change` | cached frame count, pending renders, and configured cache limit |
494
- | `cue-change` | current cue metadata or `null` when nothing is displayed |
495
- | `stats` | periodic renderer stats snapshot |
605
+ | Event | Payload |
606
+ | ----------------- | --------------------------------------------------------------------------------- |
607
+ | `loading` | subtitle format |
608
+ | `loaded` | subtitle format and parser metadata |
609
+ | `error` | subtitle format and `SubtitleDiagnosticErrorLike` |
610
+ | `warning` | `SubtitleDiagnosticWarning` |
611
+ | `renderer-change` | active backend: `webgpu`, `webgl2`, or `canvas2d` |
612
+ | `worker-state` | whether worker mode is enabled, ready, fallback status, and the active session ID |
613
+ | `cache-change` | cached frame count, pending renders, and configured cache limit |
614
+ | `cue-change` | current cue metadata or `null` when nothing is displayed |
615
+ | `stats` | periodic renderer stats snapshot |
496
616
 
497
617
  ## Performance stats
498
618
 
@@ -581,6 +701,25 @@ console.log({
581
701
 
582
702
  WebGL2 and Canvas2D fallback remain automatic. Use `onWebGPUFallback`, `onWebGL2Fallback`, `onEvent`, or `onWarning` if you need to observe backend changes.
583
703
 
704
+ ## Compatibility & visual regression
705
+
706
+ A formal suite locks decoder edge cases and backend pixel parity:
707
+
708
+ - Malformed PGS / VobSub / MKS fixtures
709
+ - Palette edge cases and zero-length RLE runs
710
+ - Alternate display sizes (SD → 4K)
711
+ - Slow worker startup / shared init
712
+ - Pixel-level goldens across software, Canvas2D, WebGL2, and WebGPU
713
+
714
+ ```bash
715
+ bun run test # Rust core (includes compatibility fixtures)
716
+ bun run test:ts # TypeScript fixtures, goldens, worker startup
717
+ bun run test:visual # Headless Chromium backend parity
718
+ bun run test:all # All of the above
719
+ ```
720
+
721
+ Browser/device support matrix (including webOS TV): [docs/COMPATIBILITY.md](./docs/COMPATIBILITY.md).
722
+
584
723
  ## Notes
585
724
 
586
725
  - Worker mode is shared, but subtitle parser state is isolated per renderer session.
@@ -594,10 +733,13 @@ WebGL2 and Canvas2D fallback remain automatic. Use `onWebGPUFallback`, `onWebGL2
594
733
 
595
734
  - `initWasm(): Promise<void>` initializes the WASM module. Called automatically by high-level renderers and on first import in browser environments. Safe to call multiple times. Only needed explicitly for low-level parser usage.
596
735
  - `isWasmInitialized(): boolean` reports whether initialization has completed.
736
+ - `warmup(): Promise<void>` / `ready(): Promise<void>` pre-initialize the shared subtitle worker (including in-worker WASM). Safe to call multiple times; concurrent callers share one init promise. Prefer these in TV/player apps before the first track switch.
737
+ - `isWorkerAvailable(): boolean` / `isWorkerReady(): boolean` report worker support and whether the shared worker has finished initializing.
597
738
  - `isWebGPUSupported(): boolean` checks WebGPU support.
598
739
  - `detectSubtitleFormat(source: AutoSubtitleSource): 'pgs' | 'vobsub' | null` detects the bitmap subtitle format from file hints or binary data.
599
740
  - `createAutoSubtitleRenderer(options: AutoVideoSubtitleOptions): PgsRenderer | VobSubRenderer` creates a high-level renderer after format detection.
600
741
  - `openSubtitles(source, options?): Promise<OpenedSubtitles>` initializes WASM, auto-detects the low-level format, and returns a normalized parser handle.
742
+ - `probeRangeSupport(url, options?)` / `fetchSubtitleAsset(url, options?, onChunk?)` / `fetchSubtitleText(url, options?)` perform Range-aware progressive asset downloads for custom loaders.
601
743
  - `renderFrameData(frame, options?): SubtitleRenderedFrameData | null` composes a `SubtitleData` frame into exportable pixels.
602
744
  - `toCanvas(frame, target?, options?): HTMLCanvasElement | OffscreenCanvas` draws a rendered frame to a new or existing canvas/context.
603
745
  - `toImageBitmap(frame, options?): Promise<ImageBitmap>` creates an `ImageBitmap` from a subtitle frame export.
@@ -605,6 +747,7 @@ WebGL2 and Canvas2D fallback remain automatic. Use `onWebGPUFallback`, `onWebGL2
605
747
  - `SubtitleDiagnosticError` is the structured error class libbitsub uses for coded diagnostics.
606
748
  - `createSubtitleDiagnosticError(...)` and `normalizeSubtitleError(...)` are exported for integrations that want to preserve libbitsub-style error codes.
607
749
  - Legacy aliases remain exported: `PGSRenderer`, `VobsubRenderer`, `UnifiedSubtitleRenderer`.
750
+ - Optional integration entry points: `libbitsub/videojs`, `libbitsub/shaka`, `libbitsub/hlsjs`, `libbitsub/react`, `libbitsub/integrations` (see [examples/](./examples) and [references/api.md](./references/api.md)).
608
751
 
609
752
  ### High-level renderers
610
753
 
@@ -639,7 +782,9 @@ WebGL2 and Canvas2D fallback remain automatic. Use `onWebGPUFallback`, `onWebGL2
639
782
 
640
783
  #### `PgsParser`
641
784
 
642
- - `load(data: Uint8Array): number` loads PGS data and returns the cue count.
785
+ - `load(data: Uint8Array): number` loads PGS data and returns the cue count (simple in-memory path).
786
+ - `reset(): void` / `feed(data: Uint8Array): number` / `finishFeed(): number` progressive indexing APIs for streamed chunks.
787
+ - `pendingLen: number` incomplete trailing bytes retained between `feed()` calls.
643
788
  - `getTimestamps(): Float64Array` returns cue timestamps in milliseconds.
644
789
  - `count: number` returns the number of cues.
645
790
  - `findIndexAtTimestamp(timeSeconds: number): number` finds the cue index for a playback time in seconds.
@@ -652,7 +797,10 @@ WebGL2 and Canvas2D fallback remain automatic. Use `onWebGPUFallback`, `onWebGL2
652
797
 
653
798
  #### `VobSubParserLowLevel`
654
799
 
655
- - `loadFromData(idxContent: string, subData: Uint8Array): void` loads IDX and SUB data.
800
+ - `loadFromData(idxContent: string, subData: Uint8Array): void` loads IDX and SUB data (simple in-memory path).
801
+ - `loadFromIdx(idxContent: string): void` indexes timestamps from IDX before packet bytes arrive.
802
+ - `attachSubData(subData: Uint8Array): void` attaches `.sub` packets after an IDX-first load.
803
+ - `hasSubData: boolean` whether packet bytes are currently attached.
656
804
  - `loadFromSubOnly(subData: Uint8Array): void` loads SUB-only VobSub data.
657
805
  - `getTimestamps(): Float64Array`, `count`, `findIndexAtTimestamp()`, `renderAtIndex()`, `renderAtTimestamp()`, `getMetadata()`, `getCueMetadata()`, `clearCache()`, and `dispose()` behave like `PgsParser`.
658
806
  - `setDebandEnabled(enabled: boolean): void`, `setDebandThreshold(threshold: number): void`, `setDebandRange(range: number): void`, and `debandEnabled` control debanding.
@@ -687,6 +835,8 @@ interface VideoSubtitleOptions {
687
835
  before?: number
688
836
  after?: number
689
837
  }
838
+ streamingLoad?: boolean // default true — progressive URL loads
839
+ rangeRequests?: boolean // default true — use HTTP Range when supported
690
840
  onEvent?: (event: SubtitleRendererEvent) => void
691
841
  }
692
842
  ```
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export { PgsRenderer, VobSubRenderer, createAutoSubtitleRenderer, type VideoSubtitleOptions, type VideoVobSubOptions, type SubtitleRendererStats } from './wrapper';
7
7
  export { PgsParser, VobSubParserLowLevel, UnifiedSubtitleParser, openSubtitles } from './wrapper';
8
- export { initWasm, isWasmInitialized, isWebGPUSupported, detectSubtitleFormat, renderFrameData, toBlob, toCanvas, toImageBitmap, createSubtitleDiagnosticError, normalizeSubtitleError, SubtitleDiagnosticError, type AutoSubtitleSource, type AutoVideoSubtitleOptions, type OpenedSubtitles, type SubtitleAspectMode, type SubtitleCacheStats, type SubtitleCueBounds, type SubtitleCueMetadata, type SubtitleData, type SubtitleDiagnosticDetailValue, type SubtitleDiagnosticErrorCode, type SubtitleDiagnosticErrorLike, type SubtitleDiagnosticsOptions, type SubtitleDiagnosticWarning, type SubtitleDiagnosticWarningCode, type SubtitleCompositionData, type SubtitleDisplaySettings, type SubtitleFrameCanvasOptions, type SubtitleFrameCanvasTarget, type SubtitleFrameCropMode, type SubtitleFrameRenderOptions, type SubtitleRenderedFrameData, type SubtitleFormatName, type SubtitleHorizontalAlign, type SubtitleLastRenderInfo, type SubtitleParserMetadata, type SubtitleRendererBackend, type SubtitleRendererEvent, type SubtitleRendererStatsSnapshot } from './wrapper';
8
+ export { initWasm, isWasmInitialized, isWebGPUSupported, isWorkerAvailable, isWorkerReady, warmup, ready, detectSubtitleFormat, fetchSubtitleAsset, fetchSubtitleText, probeRangeSupport, renderFrameData, toBlob, toCanvas, toImageBitmap, createSubtitleDiagnosticError, normalizeSubtitleError, SubtitleDiagnosticError, type AssetFetchOptions, type AssetFetchProgress, type AssetFetchStrategy, type AutoSubtitleSource, type AutoVideoSubtitleOptions, type OpenedSubtitles, type RangeProbeResult, type SubtitleAspectMode, type SubtitleCacheStats, type SubtitleCueBounds, type SubtitleCueMetadata, type SubtitleData, type SubtitleDiagnosticDetailValue, type SubtitleDiagnosticErrorCode, type SubtitleDiagnosticErrorLike, type SubtitleDiagnosticsOptions, type SubtitleDiagnosticWarning, type SubtitleDiagnosticWarningCode, type SubtitleCompositionData, type SubtitleDisplaySettings, type SubtitleFrameCanvasOptions, type SubtitleFrameCanvasTarget, type SubtitleFrameCropMode, type SubtitleFrameRenderOptions, type SubtitleRenderedFrameData, type SubtitleFormatName, type SubtitleHorizontalAlign, type SubtitleLastRenderInfo, type SubtitleParserMetadata, type SubtitleRendererBackend, type SubtitleRendererEvent, type SubtitleRendererStatsSnapshot } from './wrapper';
9
9
  export type { RenderResult, SubtitleFrame, VobSubFrame } from './wrapper';
10
10
  export { PGSRenderer, VobsubRenderer, UnifiedSubtitleRenderer } from './wrapper';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,WAAW,EACX,cAAc,EACd,0BAA0B,EAC1B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC3B,MAAM,WAAW,CAAA;AAGlB,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAGjG,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,MAAM,EACN,QAAQ,EACR,aAAa,EACb,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EACnC,MAAM,WAAW,CAAA;AAGlB,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAGzE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,WAAW,EACX,cAAc,EACd,0BAA0B,EAC1B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC3B,MAAM,WAAW,CAAA;AAGlB,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAGjG,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,MAAM,EACN,KAAK,EACL,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,MAAM,EACN,QAAQ,EACR,aAAa,EACb,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EACnC,MAAM,WAAW,CAAA;AAGlB,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAGzE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ export { PgsRenderer, VobSubRenderer, createAutoSubtitleRenderer } from './wrapp
8
8
  // Low-level parsers for programmatic use
9
9
  export { PgsParser, VobSubParserLowLevel, UnifiedSubtitleParser, openSubtitles } from './wrapper';
10
10
  // Utility exports
11
- export { initWasm, isWasmInitialized, isWebGPUSupported, detectSubtitleFormat, renderFrameData, toBlob, toCanvas, toImageBitmap, createSubtitleDiagnosticError, normalizeSubtitleError, SubtitleDiagnosticError } from './wrapper';
11
+ export { initWasm, isWasmInitialized, isWebGPUSupported, isWorkerAvailable, isWorkerReady, warmup, ready, detectSubtitleFormat, fetchSubtitleAsset, fetchSubtitleText, probeRangeSupport, renderFrameData, toBlob, toCanvas, toImageBitmap, createSubtitleDiagnosticError, normalizeSubtitleError, SubtitleDiagnosticError } from './wrapper';
12
12
  // Legacy aliases
13
13
  export { PGSRenderer, VobsubRenderer, UnifiedSubtitleRenderer } from './wrapper';
14
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,4EAA4E;AAC5E,OAAO,EACL,WAAW,EACX,cAAc,EACd,0BAA0B,EAI3B,MAAM,WAAW,CAAA;AAElB,yCAAyC;AACzC,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAEjG,kBAAkB;AAClB,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,MAAM,EACN,QAAQ,EACR,aAAa,EACb,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EA6BxB,MAAM,WAAW,CAAA;AAKlB,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,4EAA4E;AAC5E,OAAO,EACL,WAAW,EACX,cAAc,EACd,0BAA0B,EAI3B,MAAM,WAAW,CAAA;AAElB,yCAAyC;AACzC,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAEjG,kBAAkB;AAClB,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,MAAM,EACN,KAAK,EACL,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,MAAM,EACN,QAAQ,EACR,aAAa,EACb,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EAiCxB,MAAM,WAAW,CAAA;AAKlB,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Optional hls.js adapter for libbitsub bitmap subtitles.
3
+ *
4
+ * hls.js handles HLS media and WebVTT/IMSC text tracks; use this helper for
5
+ * external PGS/VobSub/MKS bitmap overlays on the same media element.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import Hls from 'hls.js'
10
+ * import { attachBitSubToHls } from 'libbitsub/hlsjs'
11
+ *
12
+ * const hls = new Hls()
13
+ * hls.loadSource(playlistUrl)
14
+ * hls.attachMedia(video)
15
+ * const bitsub = attachBitSubToHls(hls, { subUrl: '/subs/movie.sup' })
16
+ * // later
17
+ * bitsub.dispose()
18
+ * ```
19
+ */
20
+ import { type AttachBitSubOptions, type BitSubController } from './shared';
21
+ /** Minimal hls.js surface used by the adapter. */
22
+ export interface HlsLike {
23
+ media: HTMLMediaElement | null;
24
+ on?(event: string, listener: (...args: unknown[]) => void): void;
25
+ off?(event: string, listener: (...args: unknown[]) => void): void;
26
+ /** hls.js Events map — optional so callers can pass event name strings. */
27
+ Events?: {
28
+ MEDIA_ATTACHED?: string;
29
+ MEDIA_DETACHED?: string;
30
+ DESTROYING?: string;
31
+ };
32
+ }
33
+ export type BitSubHlsOptions = AttachBitSubOptions;
34
+ export interface BitSubHlsHandle extends BitSubController {
35
+ /** Underlying hls.js instance. */
36
+ readonly hls: HlsLike;
37
+ }
38
+ /**
39
+ * Attach libbitsub to an hls.js instance.
40
+ * Binds to `hls.media` and re-attaches on MEDIA_ATTACHED when event APIs exist.
41
+ */
42
+ export declare function attachBitSubToHls(hls: HlsLike, options?: BitSubHlsOptions): BitSubHlsHandle;
43
+ export type { AttachBitSubOptions, BitSubController, BitSubSourceOptions, BitSubRenderer } from './shared';
44
+ export { attachBitSub, createBitSubRenderer } from './shared';
45
+ //# sourceMappingURL=hlsjs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hlsjs.d.ts","sourceRoot":"","sources":["../../src/integrations/hlsjs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAgB,KAAK,mBAAmB,EAAE,KAAK,gBAAgB,EAA4B,MAAM,UAAU,CAAA;AAElH,kDAAkD;AAClD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC9B,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;IAChE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;IACjE,2EAA2E;IAC3E,MAAM,CAAC,EAAE;QACP,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;CACF;AAED,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAA;AAElD,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,kCAAkC;IAClC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;CACtB;AAUD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAgG/F;AAED,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC1G,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Optional hls.js adapter for libbitsub bitmap subtitles.
3
+ *
4
+ * hls.js handles HLS media and WebVTT/IMSC text tracks; use this helper for
5
+ * external PGS/VobSub/MKS bitmap overlays on the same media element.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import Hls from 'hls.js'
10
+ * import { attachBitSubToHls } from 'libbitsub/hlsjs'
11
+ *
12
+ * const hls = new Hls()
13
+ * hls.loadSource(playlistUrl)
14
+ * hls.attachMedia(video)
15
+ * const bitsub = attachBitSubToHls(hls, { subUrl: '/subs/movie.sup' })
16
+ * // later
17
+ * bitsub.dispose()
18
+ * ```
19
+ */
20
+ import { attachBitSub } from './shared';
21
+ function eventName(hls, key, fallback) {
22
+ return hls.Events?.[key] ?? fallback;
23
+ }
24
+ function hasSubtitleSource(source) {
25
+ return Boolean(source.subUrl || source.subContent || source.idxUrl || source.idxContent || source.fileName);
26
+ }
27
+ /**
28
+ * Attach libbitsub to an hls.js instance.
29
+ * Binds to `hls.media` and re-attaches on MEDIA_ATTACHED when event APIs exist.
30
+ */
31
+ export function attachBitSubToHls(hls, options = {}) {
32
+ const initialMedia = hls.media;
33
+ if (initialMedia && !(initialMedia instanceof HTMLVideoElement)) {
34
+ throw new Error('libbitsub hls.js adapter requires hls.media to be an HTMLVideoElement');
35
+ }
36
+ // Allow constructing before attachMedia(); load waits until a video is available.
37
+ const placeholderVideo = initialMedia instanceof HTMLVideoElement ? initialMedia : document.createElement('video');
38
+ const { autoLoad: initialAutoLoad = true, ...initialSource } = options;
39
+ let lastSource = { ...initialSource };
40
+ let autoLoad = initialAutoLoad;
41
+ const controller = attachBitSub(placeholderVideo, {
42
+ ...initialSource,
43
+ autoLoad: initialMedia instanceof HTMLVideoElement ? initialAutoLoad : false
44
+ });
45
+ const bindMedia = (media) => {
46
+ if (controller.disposed)
47
+ return;
48
+ if (media && !(media instanceof HTMLVideoElement)) {
49
+ throw new Error('libbitsub hls.js adapter requires hls.media to be an HTMLVideoElement');
50
+ }
51
+ if (!media) {
52
+ controller.setVideo(null);
53
+ return;
54
+ }
55
+ // setVideo reloads the last source when present; otherwise load explicitly if autoLoad.
56
+ const needsExplicitLoad = autoLoad && hasSubtitleSource(lastSource) && controller.renderer === null;
57
+ controller.setVideo(media);
58
+ if (needsExplicitLoad && controller.renderer === null && hasSubtitleSource(lastSource)) {
59
+ controller.load(lastSource);
60
+ }
61
+ };
62
+ const onMediaAttached = () => bindMedia(hls.media);
63
+ const onMediaDetached = () => {
64
+ if (!controller.disposed)
65
+ controller.clear();
66
+ };
67
+ const onDestroying = () => dispose();
68
+ const mediaAttached = eventName(hls, 'MEDIA_ATTACHED', 'hlsMediaAttached');
69
+ const mediaDetached = eventName(hls, 'MEDIA_DETACHED', 'hlsMediaDetached');
70
+ const destroying = eventName(hls, 'DESTROYING', 'hlsDestroying');
71
+ hls.on?.(mediaAttached, onMediaAttached);
72
+ hls.on?.(mediaDetached, onMediaDetached);
73
+ hls.on?.(destroying, onDestroying);
74
+ if (initialMedia instanceof HTMLVideoElement) {
75
+ bindMedia(initialMedia);
76
+ }
77
+ const dispose = () => {
78
+ hls.off?.(mediaAttached, onMediaAttached);
79
+ hls.off?.(mediaDetached, onMediaDetached);
80
+ hls.off?.(destroying, onDestroying);
81
+ controller.dispose();
82
+ };
83
+ return {
84
+ hls,
85
+ get renderer() {
86
+ return controller.renderer;
87
+ },
88
+ get video() {
89
+ return controller.video;
90
+ },
91
+ get disposed() {
92
+ return controller.disposed;
93
+ },
94
+ load: (source) => {
95
+ lastSource = { ...source };
96
+ autoLoad = true;
97
+ if (!(controller.video instanceof HTMLVideoElement) || controller.video === placeholderVideo) {
98
+ const media = hls.media;
99
+ if (media instanceof HTMLVideoElement) {
100
+ controller.setVideo(media);
101
+ }
102
+ else {
103
+ throw new Error('libbitsub hls.js adapter: call hls.attachMedia(video) before load()');
104
+ }
105
+ }
106
+ return controller.load(source);
107
+ },
108
+ clear: () => {
109
+ autoLoad = false;
110
+ controller.clear();
111
+ },
112
+ dispose,
113
+ getDisplaySettings: () => controller.getDisplaySettings(),
114
+ setDisplaySettings: (settings) => controller.setDisplaySettings(settings),
115
+ resetDisplaySettings: () => controller.resetDisplaySettings(),
116
+ getStats: () => controller.getStats(),
117
+ setVideo: (video) => controller.setVideo(video)
118
+ };
119
+ }
120
+ export { attachBitSub, createBitSubRenderer } from './shared';
121
+ //# sourceMappingURL=hlsjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hlsjs.js","sourceRoot":"","sources":["../../src/integrations/hlsjs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Optional player integrations for libbitsub.
3
+ * Prefer deep imports (`libbitsub/videojs`, `libbitsub/shaka`, `libbitsub/hlsjs`, `libbitsub/react`)
4
+ * so unused peer dependencies stay out of your bundle.
5
+ */
6
+ export { attachBitSub, createBitSubRenderer, type AttachBitSubOptions, type BitSubController, type BitSubRenderer, type BitSubSourceOptions } from './shared';
7
+ export { registerBitSubPlugin, type BitSubVideoJsApi, type BitSubVideoJsOptions, type VideoJsBitSubPlayer, type VideoJsLike, type VideoJsPlayerLike } from './videojs';
8
+ export { attachBitSubToShaka, type BitSubShakaHandle, type BitSubShakaOptions, type ShakaPlayerLike } from './shaka';
9
+ export { attachBitSubToHls, type BitSubHlsHandle, type BitSubHlsOptions, type HlsLike } from './hlsjs';
10
+ export { BitSubOverlay, useBitSub, type BitSubOverlayProps, type BitSubReactSource, type UseBitSubOptions, type UseBitSubResult } from './react';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACzB,MAAM,UAAU,CAAA;AAEjB,OAAO,EACL,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAEpH,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtG,OAAO,EACL,aAAa,EACb,SAAS,EACT,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,SAAS,CAAA"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Optional player integrations for libbitsub.
3
+ * Prefer deep imports (`libbitsub/videojs`, `libbitsub/shaka`, `libbitsub/hlsjs`, `libbitsub/react`)
4
+ * so unused peer dependencies stay out of your bundle.
5
+ */
6
+ export { attachBitSub, createBitSubRenderer } from './shared';
7
+ export { registerBitSubPlugin } from './videojs';
8
+ export { attachBitSubToShaka } from './shaka';
9
+ export { attachBitSubToHls } from './hlsjs';
10
+ export { BitSubOverlay, useBitSub } from './react';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,YAAY,EACZ,oBAAoB,EAKrB,MAAM,UAAU,CAAA;AAEjB,OAAO,EACL,oBAAoB,EAMrB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,mBAAmB,EAAyE,MAAM,SAAS,CAAA;AAEpH,OAAO,EAAE,iBAAiB,EAA6D,MAAM,SAAS,CAAA;AAEtG,OAAO,EACL,aAAa,EACb,SAAS,EAKV,MAAM,SAAS,CAAA"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Optional React bindings for libbitsub bitmap subtitles.
3
+ *
4
+ * Peer dependency: react >= 18
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * import { useRef } from 'react'
9
+ * import { useBitSub } from 'libbitsub/react'
10
+ *
11
+ * function Player({ src, subUrl }: { src: string; subUrl: string }) {
12
+ * const videoRef = useRef<HTMLVideoElement>(null)
13
+ * useBitSub(videoRef, { subUrl })
14
+ * return (
15
+ * <div style={{ position: 'relative' }}>
16
+ * <video ref={videoRef} src={src} controls playsInline />
17
+ * </div>
18
+ * )
19
+ * }
20
+ * ```
21
+ *
22
+ * Prefer either `useBitSub` *or* `BitSubOverlay` for a given video — not both.
23
+ */
24
+ import { type CSSProperties, type ReactElement, type RefObject } from 'react';
25
+ import { type BitSubController, type BitSubSourceOptions } from './shared';
26
+ import type { SubtitleDisplaySettings } from '../wrapper';
27
+ export type BitSubReactSource = BitSubSourceOptions;
28
+ export interface UseBitSubOptions extends BitSubReactSource {
29
+ /** When false, do not load even if source fields are set. Default true. */
30
+ enabled?: boolean;
31
+ }
32
+ export interface UseBitSubResult {
33
+ controller: BitSubController | null;
34
+ error: Error | null;
35
+ }
36
+ /**
37
+ * Bind a libbitsub renderer to a video element ref for the lifetime of the source.
38
+ * Cleans up automatically on unmount or when the source identity changes.
39
+ */
40
+ export declare function useBitSub(videoRef: RefObject<HTMLVideoElement | null>, options: UseBitSubOptions | null): UseBitSubResult;
41
+ export interface BitSubOverlayProps extends UseBitSubOptions {
42
+ videoRef: RefObject<HTMLVideoElement | null>;
43
+ /** Optional class name applied to a zero-size host span for debugging. */
44
+ className?: string;
45
+ style?: CSSProperties;
46
+ }
47
+ /**
48
+ * Declarative overlay helper. Renders nothing visible itself — libbitsub attaches
49
+ * its canvas next to the video element. Useful when you want JSX-configured tracks.
50
+ */
51
+ export declare function BitSubOverlay(props: BitSubOverlayProps): ReactElement | null;
52
+ export type { AttachBitSubOptions, BitSubController, BitSubSourceOptions, BitSubRenderer } from './shared';
53
+ export { attachBitSub, createBitSubRenderer } from './shared';
54
+ export type { SubtitleDisplaySettings };
55
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/integrations/react.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAA+B,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC1G,OAAO,EAA0C,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAClH,OAAO,KAAK,EAAE,uBAAuB,EAAoD,MAAM,YAAY,CAAA;AAE3G,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,CAAA;AAEnD,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAA;IACnC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAoBD;;;GAGG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAC5C,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAC/B,eAAe,CAiFjB;AAED,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,QAAQ,EAAE,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;IAC5C,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,GAAG,IAAI,CAM5E;AAED,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC1G,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC7D,YAAY,EAAE,uBAAuB,EAAE,CAAA"}