libbitsub 1.10.2 → 1.12.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 (98) hide show
  1. package/README.md +296 -49
  2. package/dist/index.d.ts +3 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +3 -3
  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 +133 -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/capabilities.d.ts +8 -0
  31. package/dist/ts/capabilities.d.ts.map +1 -0
  32. package/dist/ts/capabilities.js +105 -0
  33. package/dist/ts/capabilities.js.map +1 -0
  34. package/dist/ts/diagnostics.d.ts.map +1 -1
  35. package/dist/ts/diagnostics.js.map +1 -1
  36. package/dist/ts/frame-export.d.ts.map +1 -1
  37. package/dist/ts/frame-export.js +4 -4
  38. package/dist/ts/frame-export.js.map +1 -1
  39. package/dist/ts/parsers.d.ts +46 -8
  40. package/dist/ts/parsers.d.ts.map +1 -1
  41. package/dist/ts/parsers.js +305 -14
  42. package/dist/ts/parsers.js.map +1 -1
  43. package/dist/ts/range-loader.d.ts +31 -0
  44. package/dist/ts/range-loader.d.ts.map +1 -0
  45. package/dist/ts/range-loader.js +220 -0
  46. package/dist/ts/range-loader.js.map +1 -0
  47. package/dist/ts/renderers.d.ts +140 -8
  48. package/dist/ts/renderers.d.ts.map +1 -1
  49. package/dist/ts/renderers.js +1773 -287
  50. package/dist/ts/renderers.js.map +1 -1
  51. package/dist/ts/types.d.ts +210 -7
  52. package/dist/ts/types.d.ts.map +1 -1
  53. package/dist/ts/utils.d.ts.map +1 -1
  54. package/dist/ts/utils.js +98 -2
  55. package/dist/ts/utils.js.map +1 -1
  56. package/dist/ts/video-frame-scheduler.d.ts +35 -0
  57. package/dist/ts/video-frame-scheduler.d.ts.map +1 -0
  58. package/dist/ts/video-frame-scheduler.js +98 -0
  59. package/dist/ts/video-frame-scheduler.js.map +1 -0
  60. package/dist/ts/wasm.d.ts +2 -0
  61. package/dist/ts/wasm.d.ts.map +1 -1
  62. package/dist/ts/wasm.js +12 -0
  63. package/dist/ts/wasm.js.map +1 -1
  64. package/dist/ts/webgl2-renderer.d.ts +9 -0
  65. package/dist/ts/webgl2-renderer.d.ts.map +1 -1
  66. package/dist/ts/webgl2-renderer.js +34 -0
  67. package/dist/ts/webgl2-renderer.js.map +1 -1
  68. package/dist/ts/webgpu-renderer.d.ts +9 -0
  69. package/dist/ts/webgpu-renderer.d.ts.map +1 -1
  70. package/dist/ts/webgpu-renderer.js +70 -2
  71. package/dist/ts/webgpu-renderer.js.map +1 -1
  72. package/dist/ts/worker.d.ts +11 -0
  73. package/dist/ts/worker.d.ts.map +1 -1
  74. package/dist/ts/worker.js +620 -158
  75. package/dist/ts/worker.js.map +1 -1
  76. package/dist/wrapper.d.ts +6 -3
  77. package/dist/wrapper.d.ts.map +1 -1
  78. package/dist/wrapper.js +5 -2
  79. package/dist/wrapper.js.map +1 -1
  80. package/examples/README.md +38 -0
  81. package/examples/hlsjs/README.md +53 -0
  82. package/examples/react/README.md +60 -0
  83. package/examples/shaka/README.md +61 -0
  84. package/examples/videojs/README.md +55 -0
  85. package/package.json +66 -8
  86. package/pkg/README.md +296 -49
  87. package/pkg/libbitsub.d.ts +65 -1
  88. package/pkg/libbitsub.js +228 -3
  89. package/pkg/libbitsub_bg.wasm +0 -0
  90. package/pkg/libbitsub_bg.wasm.d.ts +28 -0
  91. package/pkg/package.json +4 -4
  92. package/src/integrations/hlsjs.ts +154 -0
  93. package/src/integrations/index.ts +36 -0
  94. package/src/integrations/react.tsx +176 -0
  95. package/src/integrations/shaka.ts +92 -0
  96. package/src/integrations/shared.ts +171 -0
  97. package/src/integrations/videojs.ts +200 -0
  98. package/src/wrapper.ts +34 -2
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Optional Video.js plugin for libbitsub bitmap subtitles.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import videojs from 'video.js'
7
+ * import { registerBitSubPlugin } from 'libbitsub/videojs'
8
+ *
9
+ * registerBitSubPlugin(videojs)
10
+ * const player = videojs('my-video')
11
+ * player.bitsub({ subUrl: '/subs/movie.sup' })
12
+ * ```
13
+ */
14
+
15
+ import { attachBitSub, type AttachBitSubOptions, type BitSubController, type BitSubSourceOptions } from './shared'
16
+
17
+ /** Minimal Video.js surface used by the plugin (avoids a hard dependency). */
18
+ export interface VideoJsPlayerLike {
19
+ ready(callback: (this: this) => void): this
20
+ el(): HTMLElement | null
21
+ tech?: (asHtml?: boolean) => { el?: () => HTMLElement | null } | HTMLElement | null | undefined
22
+ on(type: string, handler: (...args: unknown[]) => void): this
23
+ off?(type: string, handler: (...args: unknown[]) => void): this
24
+ addClass?(className: string): void
25
+ removeClass?(className: string): void
26
+ trigger?(event: string, data?: unknown): void
27
+ }
28
+
29
+ export interface VideoJsPluginBase {
30
+ player: VideoJsPlayerLike
31
+ options_: unknown
32
+ dispose(): void
33
+ }
34
+
35
+ export interface VideoJsPluginConstructor {
36
+ new (player: VideoJsPlayerLike, options?: unknown): VideoJsPluginBase
37
+ prototype: VideoJsPluginBase
38
+ }
39
+
40
+ export interface VideoJsLike {
41
+ getPlugin(name: string): VideoJsPluginConstructor
42
+ registerPlugin(name: string, plugin: unknown): void
43
+ }
44
+
45
+ export type BitSubVideoJsOptions = AttachBitSubOptions
46
+
47
+ export interface BitSubVideoJsApi {
48
+ /** Active controller, if any. */
49
+ controller(): BitSubController | null
50
+ /** Load or replace the subtitle track. */
51
+ load(source: BitSubSourceOptions): void
52
+ /** Clear the current track. */
53
+ clear(): void
54
+ /** Dispose plugin-owned resources (also runs on player dispose). */
55
+ dispose(): void
56
+ setDisplaySettings(settings: Parameters<BitSubController['setDisplaySettings']>[0]): void
57
+ getDisplaySettings(): ReturnType<BitSubController['getDisplaySettings']>
58
+ getStats(): ReturnType<BitSubController['getStats']>
59
+ }
60
+
61
+ function resolveVideoElement(player: VideoJsPlayerLike): HTMLVideoElement | null {
62
+ const tech = typeof player.tech === 'function' ? player.tech(true) : undefined
63
+ const techEl =
64
+ tech && typeof (tech as { el?: () => HTMLElement | null }).el === 'function'
65
+ ? (tech as { el: () => HTMLElement | null }).el()
66
+ : (tech as HTMLElement | null | undefined)
67
+
68
+ if (techEl instanceof HTMLVideoElement) return techEl
69
+
70
+ const root = player.el()
71
+ if (!root) return null
72
+ return root.querySelector('video')
73
+ }
74
+
75
+ /**
76
+ * Register the `bitsub` Video.js plugin.
77
+ * Safe to call multiple times — subsequent calls are no-ops once registered.
78
+ */
79
+ export function registerBitSubPlugin(videojs: VideoJsLike, pluginName = 'bitsub'): void {
80
+ const existing = typeof videojs.getPlugin === 'function' ? videojs.getPlugin(pluginName) : undefined
81
+ // Only skip when a previous registerBitSubPlugin call marked the plugin.
82
+ if (existing && (existing as { __libbitsubPlugin?: boolean }).__libbitsubPlugin) {
83
+ return
84
+ }
85
+
86
+ const Plugin = videojs.getPlugin('plugin')
87
+
88
+ class BitSubPlugin extends Plugin implements BitSubVideoJsApi {
89
+ private controllerRef: BitSubController | null = null
90
+ private readonly onDispose: () => void
91
+ private readonly onLoadedData: () => void
92
+ private readonly initialOptions: BitSubVideoJsOptions
93
+
94
+ constructor(player: VideoJsPlayerLike, options: BitSubVideoJsOptions = {}) {
95
+ super(player, options)
96
+ this.initialOptions = options
97
+
98
+ this.onDispose = () => this.disposeController()
99
+ this.onLoadedData = () => this.ensureController(this.initialOptions, false)
100
+
101
+ player.ready(() => {
102
+ this.ensureController(options, true)
103
+ player.on('loadeddata', this.onLoadedData)
104
+ player.on('dispose', this.onDispose)
105
+ player.addClass?.('vjs-bitsub')
106
+ })
107
+ }
108
+
109
+ controller(): BitSubController | null {
110
+ return this.controllerRef
111
+ }
112
+
113
+ load(source: BitSubSourceOptions): void {
114
+ const controller = this.ensureController({}, false)
115
+ controller.load(source)
116
+ this.player.trigger?.('bitsubload', source)
117
+ }
118
+
119
+ clear(): void {
120
+ this.controllerRef?.clear()
121
+ this.player.trigger?.('bitsubclear')
122
+ }
123
+
124
+ setDisplaySettings(settings: Parameters<BitSubController['setDisplaySettings']>[0]): void {
125
+ this.controllerRef?.setDisplaySettings(settings)
126
+ }
127
+
128
+ getDisplaySettings(): ReturnType<BitSubController['getDisplaySettings']> {
129
+ return this.controllerRef?.getDisplaySettings() ?? null
130
+ }
131
+
132
+ getStats(): ReturnType<BitSubController['getStats']> {
133
+ return this.controllerRef?.getStats() ?? null
134
+ }
135
+
136
+ override dispose(): void {
137
+ this.player.off?.('loadeddata', this.onLoadedData)
138
+ this.player.off?.('dispose', this.onDispose)
139
+ this.player.removeClass?.('vjs-bitsub')
140
+ this.disposeController()
141
+ super.dispose()
142
+ }
143
+
144
+ private disposeController(): void {
145
+ this.controllerRef?.dispose()
146
+ this.controllerRef = null
147
+ }
148
+
149
+ private ensureController(options: BitSubVideoJsOptions, allowAutoload: boolean): BitSubController {
150
+ const video = resolveVideoElement(this.player)
151
+ if (!video) {
152
+ throw new Error('libbitsub Video.js plugin could not resolve an HTMLVideoElement')
153
+ }
154
+
155
+ if (this.controllerRef && !this.controllerRef.disposed) {
156
+ if (this.controllerRef.video !== video) {
157
+ this.controllerRef.setVideo(video)
158
+ }
159
+ return this.controllerRef
160
+ }
161
+
162
+ const { autoLoad = true, ...source } = options
163
+ this.controllerRef = attachBitSub(video, {
164
+ ...source,
165
+ autoLoad: allowAutoload ? autoLoad : false
166
+ })
167
+ return this.controllerRef
168
+ }
169
+ }
170
+
171
+ ;(BitSubPlugin as unknown as { __libbitsubPlugin?: boolean }).__libbitsubPlugin = true
172
+ videojs.registerPlugin(pluginName, BitSubPlugin)
173
+ }
174
+
175
+ /**
176
+ * Ambient augmentation helper for apps using the default plugin name `bitsub`.
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * import 'libbitsub/videojs' // side-effect free; types only when referenced
181
+ * // or in a global.d.ts:
182
+ * // import type {} from 'libbitsub/videojs'
183
+ * ```
184
+ *
185
+ * For full player typing, extend your video.js module:
186
+ * ```ts
187
+ * import type { BitSubVideoJsApi, BitSubVideoJsOptions } from 'libbitsub/videojs'
188
+ * declare module 'video.js' {
189
+ * interface VideoJsPlayer {
190
+ * bitsub(options?: BitSubVideoJsOptions): BitSubVideoJsApi
191
+ * }
192
+ * }
193
+ * ```
194
+ */
195
+ export type VideoJsBitSubPlayer = VideoJsPlayerLike & {
196
+ bitsub(options?: BitSubVideoJsOptions): BitSubVideoJsApi
197
+ }
198
+
199
+ export type { AttachBitSubOptions, BitSubController, BitSubSourceOptions, BitSubRenderer } from './shared'
200
+ export { attachBitSub, createBitSubRenderer } from './shared'
package/src/wrapper.ts CHANGED
@@ -5,8 +5,10 @@
5
5
 
6
6
  // Re-export all types
7
7
  export type {
8
+ AssetFetchStrategy,
8
9
  AutoSubtitleSource,
9
10
  AutoVideoSubtitleOptions,
11
+ LiveSubtitleRenderer,
10
12
  OpenedSubtitles,
11
13
  SubtitleAspectMode,
12
14
  SubtitleCacheStats,
@@ -33,6 +35,10 @@ export type {
33
35
  SubtitleRendererBackend,
34
36
  SubtitleRendererEvent,
35
37
  SubtitleRendererStatsSnapshot,
38
+ SubtitleSynchronizationMode,
39
+ SubtitleStreamChunk,
40
+ RuntimeCapabilities,
41
+ SubtitlePresentPath,
36
42
  VideoSubtitleOptions,
37
43
  VideoVobSubOptions,
38
44
  RenderResult,
@@ -45,21 +51,47 @@ export { SubtitleDiagnosticError, createSubtitleDiagnosticError, normalizeSubtit
45
51
  // Re-export WASM management
46
52
  export { initWasm, isWasmInitialized } from './ts/wasm'
47
53
 
54
+ export { warmup, ready, isWorkerAvailable, isWorkerReady } from './ts/worker'
55
+
48
56
  // Re-export WebGPU utilities
49
57
  export { isWebGPUSupported } from './ts/webgpu-renderer'
50
58
 
59
+ export {
60
+ getRuntimeCapabilities,
61
+ canUseWorkerOffscreenRender,
62
+ isOffscreenCanvasSupported,
63
+ isOffscreenCanvas2DSupported,
64
+ isTransferControlToOffscreenSupported,
65
+ isCanvas2DSupported
66
+ } from './ts/capabilities'
67
+
51
68
  // Re-export parsers
52
- export { PgsParser, VobSubParserLowLevel, UnifiedSubtitleParser, openSubtitles } from './ts/parsers'
69
+ export { PgsParser, DvbParser, VobSubParserLowLevel, UnifiedSubtitleParser, openSubtitles } from './ts/parsers'
53
70
 
54
71
  // Re-export frame export helpers
55
72
  export { renderFrameData, toBlob, toCanvas, toImageBitmap } from './ts/frame-export'
56
73
 
57
74
  // Re-export renderers
58
- export { PgsRenderer, VobSubRenderer, createAutoSubtitleRenderer, type SubtitleRendererStats } from './ts/renderers'
75
+ export {
76
+ PgsRenderer,
77
+ DvbRenderer,
78
+ VobSubRenderer,
79
+ createAutoSubtitleRenderer,
80
+ type SubtitleRendererStats
81
+ } from './ts/renderers'
59
82
 
60
83
  // Re-export format detection utilities
61
84
  export { detectSubtitleFormat } from './ts/utils'
62
85
 
86
+ export {
87
+ fetchSubtitleAsset,
88
+ fetchSubtitleText,
89
+ probeRangeSupport,
90
+ type AssetFetchOptions,
91
+ type AssetFetchProgress,
92
+ type RangeProbeResult
93
+ } from './ts/range-loader'
94
+
63
95
  // =============================================================================
64
96
  // Legacy Aliases (for backward compatibility)
65
97
  // =============================================================================