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.
- package/README.md +184 -34
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/hlsjs.d.ts +45 -0
- package/dist/integrations/hlsjs.d.ts.map +1 -0
- package/dist/integrations/hlsjs.js +121 -0
- package/dist/integrations/hlsjs.js.map +1 -0
- package/dist/integrations/index.d.ts +11 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +11 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/react.d.ts +55 -0
- package/dist/integrations/react.d.ts.map +1 -0
- package/dist/integrations/react.js +127 -0
- package/dist/integrations/react.js.map +1 -0
- package/dist/integrations/shaka.d.ts +38 -0
- package/dist/integrations/shaka.d.ts.map +1 -0
- package/dist/integrations/shaka.js +71 -0
- package/dist/integrations/shaka.js.map +1 -0
- package/dist/integrations/shared.d.ts +41 -0
- package/dist/integrations/shared.d.ts.map +1 -0
- package/dist/integrations/shared.js +123 -0
- package/dist/integrations/shared.js.map +1 -0
- package/dist/integrations/videojs.d.ts +85 -0
- package/dist/integrations/videojs.d.ts.map +1 -0
- package/dist/integrations/videojs.js +111 -0
- package/dist/integrations/videojs.js.map +1 -0
- package/dist/ts/diagnostics.d.ts.map +1 -1
- package/dist/ts/diagnostics.js.map +1 -1
- package/dist/ts/frame-export.d.ts.map +1 -1
- package/dist/ts/frame-export.js +4 -4
- package/dist/ts/frame-export.js.map +1 -1
- package/dist/ts/parsers.d.ts +7 -6
- package/dist/ts/parsers.d.ts.map +1 -1
- package/dist/ts/parsers.js +76 -13
- package/dist/ts/parsers.js.map +1 -1
- package/dist/ts/range-loader.d.ts +31 -0
- package/dist/ts/range-loader.d.ts.map +1 -0
- package/dist/ts/range-loader.js +220 -0
- package/dist/ts/range-loader.js.map +1 -0
- package/dist/ts/renderers.d.ts +14 -0
- package/dist/ts/renderers.d.ts.map +1 -1
- package/dist/ts/renderers.js +445 -162
- package/dist/ts/renderers.js.map +1 -1
- package/dist/ts/types.d.ts +51 -1
- package/dist/ts/types.d.ts.map +1 -1
- package/dist/ts/utils.d.ts.map +1 -1
- package/dist/ts/utils.js.map +1 -1
- package/dist/ts/wasm.d.ts +2 -0
- package/dist/ts/wasm.d.ts.map +1 -1
- package/dist/ts/wasm.js +12 -0
- package/dist/ts/wasm.js.map +1 -1
- package/dist/ts/webgl2-renderer.d.ts +9 -0
- package/dist/ts/webgl2-renderer.d.ts.map +1 -1
- package/dist/ts/webgl2-renderer.js +34 -0
- package/dist/ts/webgl2-renderer.js.map +1 -1
- package/dist/ts/webgpu-renderer.d.ts +9 -0
- package/dist/ts/webgpu-renderer.d.ts.map +1 -1
- package/dist/ts/webgpu-renderer.js +70 -2
- package/dist/ts/webgpu-renderer.js.map +1 -1
- package/dist/ts/worker.d.ts +11 -0
- package/dist/ts/worker.d.ts.map +1 -1
- package/dist/ts/worker.js +229 -161
- package/dist/ts/worker.js.map +1 -1
- package/dist/wrapper.d.ts +3 -1
- package/dist/wrapper.d.ts.map +1 -1
- package/dist/wrapper.js +2 -0
- package/dist/wrapper.js.map +1 -1
- package/examples/README.md +38 -0
- package/examples/hlsjs/README.md +53 -0
- package/examples/react/README.md +60 -0
- package/examples/shaka/README.md +61 -0
- package/examples/videojs/README.md +55 -0
- package/package.json +64 -7
- package/pkg/README.md +184 -34
- package/pkg/libbitsub.d.ts +14 -0
- package/pkg/libbitsub.js +50 -0
- package/pkg/libbitsub_bg.wasm +0 -0
- package/pkg/libbitsub_bg.wasm.d.ts +7 -0
- package/pkg/package.json +1 -1
- package/src/integrations/hlsjs.ts +154 -0
- package/src/integrations/index.ts +36 -0
- package/src/integrations/react.tsx +170 -0
- package/src/integrations/shaka.ts +92 -0
- package/src/integrations/shared.ts +170 -0
- package/src/integrations/videojs.ts +200 -0
- package/src/wrapper.ts +12 -0
package/dist/ts/worker.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Web Worker management for libbitsub.
|
|
3
3
|
* Handles off-main-thread subtitle parsing and rendering.
|
|
4
4
|
*/
|
|
5
|
-
import { getWasmUrl } from './wasm';
|
|
5
|
+
import { getWasmGlueUrl, getWasmUrl } from './wasm';
|
|
6
6
|
let sharedWorker = null;
|
|
7
7
|
let workerInitPromise = null;
|
|
8
8
|
let messageId = 0;
|
|
@@ -15,61 +15,9 @@ export function isWorkerAvailable() {
|
|
|
15
15
|
function createWorkerScript() {
|
|
16
16
|
return `
|
|
17
17
|
let wasmModule = null;
|
|
18
|
-
let wasm;
|
|
19
|
-
let cachedUint8Memory = null;
|
|
20
|
-
let WASM_VECTOR_LEN = 0;
|
|
21
|
-
let cachedTextEncoder = new TextEncoder();
|
|
22
|
-
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
23
18
|
const pgsParsers = new Map();
|
|
24
19
|
const vobSubParsers = new Map();
|
|
25
20
|
|
|
26
|
-
function getUint8Memory() {
|
|
27
|
-
if (cachedUint8Memory === null || cachedUint8Memory.byteLength === 0) {
|
|
28
|
-
cachedUint8Memory = new Uint8Array(wasm.memory.buffer);
|
|
29
|
-
}
|
|
30
|
-
return cachedUint8Memory;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function passArray8ToWasm(arg) {
|
|
34
|
-
const ptr = wasm.__wbindgen_malloc(arg.length);
|
|
35
|
-
getUint8Memory().set(arg, ptr);
|
|
36
|
-
WASM_VECTOR_LEN = arg.length;
|
|
37
|
-
return ptr;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const encodeString = typeof cachedTextEncoder.encodeInto === 'function'
|
|
41
|
-
? function(arg, view) { return cachedTextEncoder.encodeInto(arg, view); }
|
|
42
|
-
: function(arg, view) {
|
|
43
|
-
const buf = cachedTextEncoder.encode(arg);
|
|
44
|
-
view.set(buf);
|
|
45
|
-
return { read: arg.length, written: buf.length };
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
function passStringToWasm(arg) {
|
|
49
|
-
let len = arg.length;
|
|
50
|
-
let ptr = wasm.__wbindgen_malloc(len);
|
|
51
|
-
const mem = getUint8Memory();
|
|
52
|
-
let offset = 0;
|
|
53
|
-
for (; offset < len; offset++) {
|
|
54
|
-
const code = arg.charCodeAt(offset);
|
|
55
|
-
if (code > 0x7F) break;
|
|
56
|
-
mem[ptr + offset] = code;
|
|
57
|
-
}
|
|
58
|
-
if (offset !== len) {
|
|
59
|
-
if (offset !== 0) arg = arg.slice(offset);
|
|
60
|
-
ptr = wasm.__wbindgen_realloc(ptr, len, len = offset + arg.length * 3);
|
|
61
|
-
const view = getUint8Memory().subarray(ptr + offset, ptr + len);
|
|
62
|
-
const ret = encodeString(arg, view);
|
|
63
|
-
offset += ret.written;
|
|
64
|
-
}
|
|
65
|
-
WASM_VECTOR_LEN = offset;
|
|
66
|
-
return ptr;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function getStringFromWasm(ptr, len) {
|
|
70
|
-
return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));
|
|
71
|
-
}
|
|
72
|
-
|
|
73
21
|
function buildPgsMetadata(parser) {
|
|
74
22
|
return {
|
|
75
23
|
format: 'pgs',
|
|
@@ -104,72 +52,18 @@ function disposeSession(sessionId) {
|
|
|
104
52
|
}
|
|
105
53
|
}
|
|
106
54
|
|
|
107
|
-
async function initWasm(wasmUrl) {
|
|
108
|
-
if (
|
|
55
|
+
async function initWasm(wasmUrl, glueUrl) {
|
|
56
|
+
if (wasmModule) return;
|
|
109
57
|
|
|
110
|
-
|
|
111
|
-
if (!
|
|
112
|
-
|
|
58
|
+
let jsGlueUrl = glueUrl;
|
|
59
|
+
if (!jsGlueUrl) {
|
|
60
|
+
const derivedUrl = new URL(wasmUrl);
|
|
61
|
+
derivedUrl.pathname = derivedUrl.pathname.replace(/_bg\.wasm$/, '.js');
|
|
62
|
+
jsGlueUrl = derivedUrl.href;
|
|
113
63
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
__wbindgen_placeholder__: {
|
|
118
|
-
__wbindgen_throw: function(ptr, len) {
|
|
119
|
-
throw new Error(getStringFromWasm(ptr, len));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
wasm = result.instance.exports;
|
|
124
|
-
|
|
125
|
-
wasmModule = {
|
|
126
|
-
PgsParser: class {
|
|
127
|
-
constructor() { this.ptr = wasm.pgsparser_new(); }
|
|
128
|
-
parse(data) {
|
|
129
|
-
const ptr = passArray8ToWasm(data);
|
|
130
|
-
return wasm.pgsparser_parse(this.ptr, ptr, WASM_VECTOR_LEN);
|
|
131
|
-
}
|
|
132
|
-
getTimestamps() { return wasm.pgsparser_getTimestamps(this.ptr); }
|
|
133
|
-
renderAtIndex(idx) { return wasm.pgsparser_renderAtIndex(this.ptr, idx); }
|
|
134
|
-
findIndexAtTimestamp(ts) { return wasm.pgsparser_findIndexAtTimestamp(this.ptr, ts); }
|
|
135
|
-
clearCache() { wasm.pgsparser_clearCache(this.ptr); }
|
|
136
|
-
free() { wasm.pgsparser_free(this.ptr); }
|
|
137
|
-
get count() { return wasm.pgsparser_count(this.ptr); }
|
|
138
|
-
get screenWidth() { return wasm.pgsparser_screenWidth(this.ptr); }
|
|
139
|
-
get screenHeight() { return wasm.pgsparser_screenHeight(this.ptr); }
|
|
140
|
-
},
|
|
141
|
-
VobSubParser: class {
|
|
142
|
-
constructor() { this.ptr = wasm.vobsubparser_new(); }
|
|
143
|
-
loadFromData(idx, sub) {
|
|
144
|
-
const idxPtr = passStringToWasm(idx);
|
|
145
|
-
const idxLen = WASM_VECTOR_LEN;
|
|
146
|
-
const subPtr = passArray8ToWasm(sub);
|
|
147
|
-
wasm.vobsubparser_loadFromData(this.ptr, idxPtr, idxLen, subPtr, sub.length);
|
|
148
|
-
}
|
|
149
|
-
loadFromMks(sub) {
|
|
150
|
-
const ptr = passArray8ToWasm(sub);
|
|
151
|
-
wasm.vobsubparser_loadFromMks(this.ptr, ptr, WASM_VECTOR_LEN);
|
|
152
|
-
}
|
|
153
|
-
loadFromSubOnly(sub) {
|
|
154
|
-
const ptr = passArray8ToWasm(sub);
|
|
155
|
-
wasm.vobsubparser_loadFromSubOnly(this.ptr, ptr, WASM_VECTOR_LEN);
|
|
156
|
-
}
|
|
157
|
-
getTimestamps() { return wasm.vobsubparser_getTimestamps(this.ptr); }
|
|
158
|
-
renderAtIndex(idx) { return wasm.vobsubparser_renderAtIndex(this.ptr, idx); }
|
|
159
|
-
findIndexAtTimestamp(ts) { return wasm.vobsubparser_findIndexAtTimestamp(this.ptr, ts); }
|
|
160
|
-
clearCache() { wasm.vobsubparser_clearCache(this.ptr); }
|
|
161
|
-
free() { wasm.vobsubparser_free(this.ptr); }
|
|
162
|
-
setDebandEnabled(enabled) { wasm.vobsubparser_setDebandEnabled(this.ptr, enabled); }
|
|
163
|
-
setDebandThreshold(threshold) { wasm.vobsubparser_setDebandThreshold(this.ptr, threshold); }
|
|
164
|
-
setDebandRange(range) { wasm.vobsubparser_setDebandRange(this.ptr, range); }
|
|
165
|
-
get count() { return wasm.vobsubparser_count(this.ptr); }
|
|
166
|
-
get screenWidth() { return wasm.vobsubparser_screenWidth(this.ptr); }
|
|
167
|
-
get screenHeight() { return wasm.vobsubparser_screenHeight(this.ptr); }
|
|
168
|
-
get language() { return wasm.vobsubparser_language(this.ptr); }
|
|
169
|
-
get trackId() { return wasm.vobsubparser_trackId(this.ptr); }
|
|
170
|
-
get hasIdxMetadata() { return !!wasm.vobsubparser_hasIdxMetadata(this.ptr); }
|
|
171
|
-
}
|
|
172
|
-
};
|
|
64
|
+
const mod = await import(jsGlueUrl);
|
|
65
|
+
await mod.default({ module_or_path: wasmUrl });
|
|
66
|
+
wasmModule = mod;
|
|
173
67
|
}
|
|
174
68
|
|
|
175
69
|
function convertFrame(frame, isVobSub) {
|
|
@@ -205,7 +99,7 @@ self.onmessage = async function(event) {
|
|
|
205
99
|
try {
|
|
206
100
|
switch (request.type) {
|
|
207
101
|
case 'init': {
|
|
208
|
-
await initWasm(request.wasmUrl);
|
|
102
|
+
await initWasm(request.wasmUrl, request.glueUrl);
|
|
209
103
|
postResponse({ type: 'initComplete', success: true }, [], _id);
|
|
210
104
|
break;
|
|
211
105
|
}
|
|
@@ -222,6 +116,50 @@ self.onmessage = async function(event) {
|
|
|
222
116
|
);
|
|
223
117
|
break;
|
|
224
118
|
}
|
|
119
|
+
case 'beginPgs': {
|
|
120
|
+
disposeSession(request.sessionId);
|
|
121
|
+
const parser = new wasmModule.PgsParser();
|
|
122
|
+
parser.reset();
|
|
123
|
+
pgsParsers.set(request.sessionId, parser);
|
|
124
|
+
const timestamps = parser.getTimestamps();
|
|
125
|
+
postResponse(
|
|
126
|
+
{ type: 'pgsProgress', count: 0, added: 0, partial: true, metadata: buildPgsMetadata(parser), timestamps },
|
|
127
|
+
[timestamps.buffer],
|
|
128
|
+
_id
|
|
129
|
+
);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case 'appendPgs': {
|
|
133
|
+
let parser = pgsParsers.get(request.sessionId);
|
|
134
|
+
if (!parser) {
|
|
135
|
+
parser = new wasmModule.PgsParser();
|
|
136
|
+
parser.reset();
|
|
137
|
+
pgsParsers.set(request.sessionId, parser);
|
|
138
|
+
}
|
|
139
|
+
const added = parser.feed(new Uint8Array(request.data));
|
|
140
|
+
const timestamps = parser.getTimestamps();
|
|
141
|
+
postResponse(
|
|
142
|
+
{ type: 'pgsProgress', count: parser.count, added, partial: true, metadata: buildPgsMetadata(parser), timestamps },
|
|
143
|
+
[timestamps.buffer],
|
|
144
|
+
_id
|
|
145
|
+
);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
case 'finishPgs': {
|
|
149
|
+
const parser = pgsParsers.get(request.sessionId);
|
|
150
|
+
if (!parser) {
|
|
151
|
+
postResponse({ type: 'error', message: 'PGS session not found for finishPgs' }, [], _id);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
const count = parser.finishFeed();
|
|
155
|
+
const timestamps = parser.getTimestamps();
|
|
156
|
+
postResponse(
|
|
157
|
+
{ type: 'pgsProgress', count, added: 0, partial: false, metadata: buildPgsMetadata(parser), timestamps },
|
|
158
|
+
[timestamps.buffer],
|
|
159
|
+
_id
|
|
160
|
+
);
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
225
163
|
case 'loadVobSub': {
|
|
226
164
|
disposeSession(request.sessionId);
|
|
227
165
|
const parser = new wasmModule.VobSubParser();
|
|
@@ -235,6 +173,48 @@ self.onmessage = async function(event) {
|
|
|
235
173
|
);
|
|
236
174
|
break;
|
|
237
175
|
}
|
|
176
|
+
case 'loadVobSubIdx': {
|
|
177
|
+
disposeSession(request.sessionId);
|
|
178
|
+
const parser = new wasmModule.VobSubParser();
|
|
179
|
+
parser.loadFromIdx(request.idxContent);
|
|
180
|
+
const timestamps = parser.getTimestamps();
|
|
181
|
+
vobSubParsers.set(request.sessionId, parser);
|
|
182
|
+
postResponse(
|
|
183
|
+
{
|
|
184
|
+
type: 'vobSubProgress',
|
|
185
|
+
count: parser.count,
|
|
186
|
+
partial: true,
|
|
187
|
+
hasSubData: !!parser.hasSubData,
|
|
188
|
+
metadata: buildVobSubMetadata(parser),
|
|
189
|
+
timestamps
|
|
190
|
+
},
|
|
191
|
+
[timestamps.buffer],
|
|
192
|
+
_id
|
|
193
|
+
);
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case 'attachVobSubData': {
|
|
197
|
+
const parser = vobSubParsers.get(request.sessionId);
|
|
198
|
+
if (!parser) {
|
|
199
|
+
postResponse({ type: 'error', message: 'VobSub session not found for attachVobSubData' }, [], _id);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
parser.attachSubData(new Uint8Array(request.subData));
|
|
203
|
+
const timestamps = parser.getTimestamps();
|
|
204
|
+
postResponse(
|
|
205
|
+
{
|
|
206
|
+
type: 'vobSubProgress',
|
|
207
|
+
count: parser.count,
|
|
208
|
+
partial: false,
|
|
209
|
+
hasSubData: !!parser.hasSubData,
|
|
210
|
+
metadata: buildVobSubMetadata(parser),
|
|
211
|
+
timestamps
|
|
212
|
+
},
|
|
213
|
+
[timestamps.buffer],
|
|
214
|
+
_id
|
|
215
|
+
);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
238
218
|
case 'loadVobSubMks': {
|
|
239
219
|
disposeSession(request.sessionId);
|
|
240
220
|
const parser = new wasmModule.VobSubParser();
|
|
@@ -350,57 +330,108 @@ self.onmessage = async function(event) {
|
|
|
350
330
|
}
|
|
351
331
|
};`;
|
|
352
332
|
}
|
|
333
|
+
/** Whether the shared worker has finished WASM initialization. */
|
|
334
|
+
export function isWorkerReady() {
|
|
335
|
+
return sharedWorker !== null;
|
|
336
|
+
}
|
|
353
337
|
/** Create or get the shared worker instance. */
|
|
354
338
|
export function getOrCreateWorker() {
|
|
355
339
|
if (sharedWorker)
|
|
356
340
|
return Promise.resolve(sharedWorker);
|
|
357
341
|
if (workerInitPromise)
|
|
358
342
|
return workerInitPromise;
|
|
359
|
-
|
|
343
|
+
const initPromise = initializeWorker();
|
|
344
|
+
workerInitPromise = initPromise;
|
|
345
|
+
void initPromise.then(() => {
|
|
346
|
+
if (workerInitPromise === initPromise)
|
|
347
|
+
workerInitPromise = null;
|
|
348
|
+
}, () => {
|
|
349
|
+
if (workerInitPromise === initPromise)
|
|
350
|
+
workerInitPromise = null;
|
|
351
|
+
});
|
|
352
|
+
return initPromise;
|
|
353
|
+
}
|
|
354
|
+
/** Pre-initialize the shared subtitle worker. */
|
|
355
|
+
export function warmup() {
|
|
356
|
+
return ready();
|
|
357
|
+
}
|
|
358
|
+
/** Wait until the shared worker is ready for parse/render requests. */
|
|
359
|
+
export async function ready() {
|
|
360
|
+
if (!isWorkerAvailable())
|
|
361
|
+
return;
|
|
362
|
+
if (sharedWorker)
|
|
363
|
+
return;
|
|
364
|
+
await getOrCreateWorker();
|
|
365
|
+
}
|
|
366
|
+
async function initializeWorker() {
|
|
367
|
+
const blob = new Blob([createWorkerScript()], { type: 'application/javascript' });
|
|
368
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
369
|
+
let worker;
|
|
370
|
+
try {
|
|
371
|
+
worker = new Worker(workerUrl, { type: 'module' });
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
URL.revokeObjectURL(workerUrl);
|
|
375
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
376
|
+
}
|
|
377
|
+
worker.onmessage = (event) => {
|
|
378
|
+
const { _id, ...response } = event.data;
|
|
379
|
+
if (_id === undefined)
|
|
380
|
+
return;
|
|
381
|
+
const callback = pendingCallbacks.get(_id);
|
|
382
|
+
if (!callback)
|
|
383
|
+
return;
|
|
384
|
+
pendingCallbacks.delete(_id);
|
|
385
|
+
if (response.type === 'error' && callback.requestType === 'init') {
|
|
386
|
+
callback.reject(new Error(response.message));
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
callback.resolve(response);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
worker.onerror = (event) => {
|
|
393
|
+
const error = event instanceof ErrorEvent ? new Error(event.message) : new Error(String(event));
|
|
394
|
+
rejectWorkerCallbacks(worker, error);
|
|
395
|
+
if (sharedWorker === worker)
|
|
396
|
+
sharedWorker = null;
|
|
360
397
|
try {
|
|
361
|
-
|
|
362
|
-
const workerUrl = URL.createObjectURL(blob);
|
|
363
|
-
const worker = new Worker(workerUrl, { type: 'module' });
|
|
364
|
-
let initialized = false;
|
|
365
|
-
worker.onmessage = (event) => {
|
|
366
|
-
const { _id, ...response } = event.data;
|
|
367
|
-
if (_id !== undefined) {
|
|
368
|
-
const callback = pendingCallbacks.get(_id);
|
|
369
|
-
if (callback) {
|
|
370
|
-
pendingCallbacks.delete(_id);
|
|
371
|
-
callback.resolve(response);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
};
|
|
375
|
-
worker.onerror = (error) => {
|
|
376
|
-
if (!initialized) {
|
|
377
|
-
URL.revokeObjectURL(workerUrl);
|
|
378
|
-
worker.terminate();
|
|
379
|
-
workerInitPromise = null;
|
|
380
|
-
reject(error instanceof ErrorEvent ? new Error(error.message) : new Error(String(error)));
|
|
381
|
-
}
|
|
382
|
-
};
|
|
383
|
-
sendToWorkerInstance(worker, { type: 'init', wasmUrl: getWasmUrl() })
|
|
384
|
-
.then(() => {
|
|
385
|
-
URL.revokeObjectURL(workerUrl);
|
|
386
|
-
initialized = true;
|
|
387
|
-
sharedWorker = worker;
|
|
388
|
-
workerInitPromise = null;
|
|
389
|
-
resolve(worker);
|
|
390
|
-
})
|
|
391
|
-
.catch((err) => {
|
|
392
|
-
URL.revokeObjectURL(workerUrl);
|
|
393
|
-
worker.terminate();
|
|
394
|
-
workerInitPromise = null;
|
|
395
|
-
reject(err);
|
|
396
|
-
});
|
|
398
|
+
worker.terminate();
|
|
397
399
|
}
|
|
398
|
-
catch
|
|
399
|
-
|
|
400
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
400
|
+
catch {
|
|
401
|
+
/* ignore */
|
|
401
402
|
}
|
|
402
|
-
}
|
|
403
|
-
|
|
403
|
+
};
|
|
404
|
+
try {
|
|
405
|
+
const initResponse = await sendToWorkerInstance(worker, {
|
|
406
|
+
type: 'init',
|
|
407
|
+
wasmUrl: getWasmUrl(),
|
|
408
|
+
glueUrl: getWasmGlueUrl()
|
|
409
|
+
});
|
|
410
|
+
if (initResponse.type === 'error') {
|
|
411
|
+
throw new Error(initResponse.message);
|
|
412
|
+
}
|
|
413
|
+
if (initResponse.type !== 'initComplete' || !initResponse.success) {
|
|
414
|
+
throw new Error('Worker WASM initialization failed');
|
|
415
|
+
}
|
|
416
|
+
sharedWorker = worker;
|
|
417
|
+
return worker;
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
const workerError = error instanceof Error ? error : new Error(String(error));
|
|
421
|
+
rejectWorkerCallbacks(worker, workerError);
|
|
422
|
+
if (sharedWorker === worker)
|
|
423
|
+
sharedWorker = null;
|
|
424
|
+
try {
|
|
425
|
+
worker.terminate();
|
|
426
|
+
}
|
|
427
|
+
catch {
|
|
428
|
+
/* ignore */
|
|
429
|
+
}
|
|
430
|
+
throw workerError;
|
|
431
|
+
}
|
|
432
|
+
finally {
|
|
433
|
+
URL.revokeObjectURL(workerUrl);
|
|
434
|
+
}
|
|
404
435
|
}
|
|
405
436
|
/** Default timeout for worker operations (30 seconds for large files) */
|
|
406
437
|
const WORKER_TIMEOUT = 30000;
|
|
@@ -419,6 +450,8 @@ function sendToWorkerInstance(worker, request, timeout = WORKER_TIMEOUT) {
|
|
|
419
450
|
reject(new Error(`Worker operation timed out after ${timeout}ms`));
|
|
420
451
|
}, timeout);
|
|
421
452
|
pendingCallbacks.set(id, {
|
|
453
|
+
worker,
|
|
454
|
+
requestType: request.type,
|
|
422
455
|
resolve: (response) => {
|
|
423
456
|
clearTimeout(timeoutId);
|
|
424
457
|
resolve(response);
|
|
@@ -433,7 +466,42 @@ function sendToWorkerInstance(worker, request, timeout = WORKER_TIMEOUT) {
|
|
|
433
466
|
transfers.push(request.data);
|
|
434
467
|
if ('subData' in request && request.subData instanceof ArrayBuffer)
|
|
435
468
|
transfers.push(request.subData);
|
|
436
|
-
|
|
469
|
+
try {
|
|
470
|
+
worker.postMessage({ ...request, _id: id }, transfers);
|
|
471
|
+
}
|
|
472
|
+
catch (error) {
|
|
473
|
+
pendingCallbacks.delete(id);
|
|
474
|
+
clearTimeout(timeoutId);
|
|
475
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
476
|
+
}
|
|
437
477
|
});
|
|
438
478
|
}
|
|
479
|
+
function rejectWorkerCallbacks(worker, error) {
|
|
480
|
+
for (const [id, callback] of pendingCallbacks) {
|
|
481
|
+
if (callback.worker !== worker)
|
|
482
|
+
continue;
|
|
483
|
+
pendingCallbacks.delete(id);
|
|
484
|
+
callback.reject(error);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Test-only helper: tear down shared worker state between Bun test files.
|
|
489
|
+
* Not part of the public runtime API.
|
|
490
|
+
*/
|
|
491
|
+
export function resetWorkerForTests() {
|
|
492
|
+
if (sharedWorker) {
|
|
493
|
+
try {
|
|
494
|
+
sharedWorker.terminate();
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
/* ignore */
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
sharedWorker = null;
|
|
501
|
+
workerInitPromise = null;
|
|
502
|
+
for (const [, callback] of pendingCallbacks) {
|
|
503
|
+
callback.reject(new Error('Worker reset for tests'));
|
|
504
|
+
}
|
|
505
|
+
pendingCallbacks.clear();
|
|
506
|
+
}
|
|
439
507
|
//# sourceMappingURL=worker.js.map
|
package/dist/ts/worker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/ts/worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/ts/worker.ts"],"names":[],"mappings":"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"}
|
package/dist/wrapper.d.ts
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
* TypeScript wrapper for the libbitsub Rust rendering engine.
|
|
3
3
|
* Provides a compatible API with the original libpgs-js implementation.
|
|
4
4
|
*/
|
|
5
|
-
export type { AutoSubtitleSource, AutoVideoSubtitleOptions, OpenedSubtitles, SubtitleAspectMode, SubtitleCacheStats, SubtitleFrameCanvasOptions, SubtitleFrameCanvasTarget, SubtitleFrameCropMode, SubtitleFrameRenderOptions, SubtitleRenderedFrameData, SubtitleCueBounds, SubtitleCueMetadata, SubtitleData, SubtitleDiagnosticDetailValue, SubtitleDiagnosticErrorCode, SubtitleDiagnosticErrorLike, SubtitleDiagnosticsOptions, SubtitleDiagnosticWarning, SubtitleDiagnosticWarningCode, SubtitleCompositionData, SubtitleDisplaySettings, SubtitleFormatName, SubtitleHorizontalAlign, SubtitleLastRenderInfo, SubtitleParserMetadata, SubtitleRendererBackend, SubtitleRendererEvent, SubtitleRendererStatsSnapshot, VideoSubtitleOptions, VideoVobSubOptions, RenderResult, SubtitleFrame, VobSubFrame } from './ts/types';
|
|
5
|
+
export type { AssetFetchStrategy, AutoSubtitleSource, AutoVideoSubtitleOptions, OpenedSubtitles, SubtitleAspectMode, SubtitleCacheStats, SubtitleFrameCanvasOptions, SubtitleFrameCanvasTarget, SubtitleFrameCropMode, SubtitleFrameRenderOptions, SubtitleRenderedFrameData, SubtitleCueBounds, SubtitleCueMetadata, SubtitleData, SubtitleDiagnosticDetailValue, SubtitleDiagnosticErrorCode, SubtitleDiagnosticErrorLike, SubtitleDiagnosticsOptions, SubtitleDiagnosticWarning, SubtitleDiagnosticWarningCode, SubtitleCompositionData, SubtitleDisplaySettings, SubtitleFormatName, SubtitleHorizontalAlign, SubtitleLastRenderInfo, SubtitleParserMetadata, SubtitleRendererBackend, SubtitleRendererEvent, SubtitleRendererStatsSnapshot, VideoSubtitleOptions, VideoVobSubOptions, RenderResult, SubtitleFrame, VobSubFrame } from './ts/types';
|
|
6
6
|
export { SubtitleDiagnosticError, createSubtitleDiagnosticError, normalizeSubtitleError } from './ts/diagnostics';
|
|
7
7
|
export { initWasm, isWasmInitialized } from './ts/wasm';
|
|
8
|
+
export { warmup, ready, isWorkerAvailable, isWorkerReady } from './ts/worker';
|
|
8
9
|
export { isWebGPUSupported } from './ts/webgpu-renderer';
|
|
9
10
|
export { PgsParser, VobSubParserLowLevel, UnifiedSubtitleParser, openSubtitles } from './ts/parsers';
|
|
10
11
|
export { renderFrameData, toBlob, toCanvas, toImageBitmap } from './ts/frame-export';
|
|
11
12
|
export { PgsRenderer, VobSubRenderer, createAutoSubtitleRenderer, type SubtitleRendererStats } from './ts/renderers';
|
|
12
13
|
export { detectSubtitleFormat } from './ts/utils';
|
|
14
|
+
export { fetchSubtitleAsset, fetchSubtitleText, probeRangeSupport, type AssetFetchOptions, type AssetFetchProgress, type RangeProbeResult } from './ts/range-loader';
|
|
13
15
|
import { PgsRenderer as _PgsRenderer, VobSubRenderer as _VobSubRenderer } from './ts/renderers';
|
|
14
16
|
import { UnifiedSubtitleParser as _UnifiedSubtitleParser } from './ts/parsers';
|
|
15
17
|
/** @deprecated Use PgsRenderer instead */
|
package/dist/wrapper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,6BAA6B,EAC7B,2BAA2B,EAC3B,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,WAAW,EACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAGjH,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,6BAA6B,EAC7B,2BAA2B,EAC3B,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,WAAW,EACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAGjH,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAEvD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAGpG,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGpF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,0BAA0B,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAGpH,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAA;AAM1B,OAAO,EAAE,WAAW,IAAI,YAAY,EAAE,cAAc,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EAAE,qBAAqB,IAAI,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAE9E,0CAA0C;AAC1C,eAAO,MAAM,WAAW,qBAAe,CAAA;AAEvC,6CAA6C;AAC7C,eAAO,MAAM,cAAc,wBAAkB,CAAA;AAE7C,oDAAoD;AACpD,eAAO,MAAM,uBAAuB,+BAAyB,CAAA"}
|
package/dist/wrapper.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export { SubtitleDiagnosticError, createSubtitleDiagnosticError, normalizeSubtitleError } from './ts/diagnostics';
|
|
6
6
|
// Re-export WASM management
|
|
7
7
|
export { initWasm, isWasmInitialized } from './ts/wasm';
|
|
8
|
+
export { warmup, ready, isWorkerAvailable, isWorkerReady } from './ts/worker';
|
|
8
9
|
// Re-export WebGPU utilities
|
|
9
10
|
export { isWebGPUSupported } from './ts/webgpu-renderer';
|
|
10
11
|
// Re-export parsers
|
|
@@ -15,6 +16,7 @@ export { renderFrameData, toBlob, toCanvas, toImageBitmap } from './ts/frame-exp
|
|
|
15
16
|
export { PgsRenderer, VobSubRenderer, createAutoSubtitleRenderer } from './ts/renderers';
|
|
16
17
|
// Re-export format detection utilities
|
|
17
18
|
export { detectSubtitleFormat } from './ts/utils';
|
|
19
|
+
export { fetchSubtitleAsset, fetchSubtitleText, probeRangeSupport } from './ts/range-loader';
|
|
18
20
|
// =============================================================================
|
|
19
21
|
// Legacy Aliases (for backward compatibility)
|
|
20
22
|
// =============================================================================
|
package/dist/wrapper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwCH,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAEjH,4BAA4B;AAC5B,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAEvD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE7E,6BAA6B;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAExD,oBAAoB;AACpB,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEpG,iCAAiC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEpF,sBAAsB;AACtB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,0BAA0B,EAA8B,MAAM,gBAAgB,CAAA;AAEpH,uCAAuC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EAIlB,MAAM,mBAAmB,CAAA;AAE1B,gFAAgF;AAChF,8CAA8C;AAC9C,gFAAgF;AAEhF,OAAO,EAAE,WAAW,IAAI,YAAY,EAAE,cAAc,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EAAE,qBAAqB,IAAI,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAE9E,0CAA0C;AAC1C,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAA;AAEvC,6CAA6C;AAC7C,MAAM,CAAC,MAAM,cAAc,GAAG,eAAe,CAAA;AAE7C,oDAAoD;AACpD,MAAM,CAAC,MAAM,uBAAuB,GAAG,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# libbitsub player integration recipes
|
|
2
|
+
|
|
3
|
+
Optional adapters ship with the core package as **subpath exports**. They keep `libbitsub` itself dependency-free: player/React packages are optional peer dependencies and are only required when you import that adapter.
|
|
4
|
+
|
|
5
|
+
| Integration | Import | Peer dependency |
|
|
6
|
+
| ----------------- | ----------------------------------------- | ----------------------- |
|
|
7
|
+
| Shared controller | `libbitsub/integrations` (`attachBitSub`) | none beyond `libbitsub` |
|
|
8
|
+
| Video.js | `libbitsub/videojs` | `video.js` >= 7 |
|
|
9
|
+
| Shaka Player | `libbitsub/shaka` | `shaka-player` >= 4 |
|
|
10
|
+
| hls.js | `libbitsub/hlsjs` | `hls.js` >= 1 |
|
|
11
|
+
| React | `libbitsub/react` | `react` >= 18 |
|
|
12
|
+
|
|
13
|
+
Bitmap PGS / VobSub / MKS tracks are **not** native HTML text tracks. Each adapter overlays libbitsub on the player's `HTMLVideoElement`.
|
|
14
|
+
|
|
15
|
+
See the per-player folders for copy-paste recipes:
|
|
16
|
+
|
|
17
|
+
- [videojs](./videojs)
|
|
18
|
+
- [shaka](./shaka)
|
|
19
|
+
- [hlsjs](./hlsjs)
|
|
20
|
+
- [react](./react)
|
|
21
|
+
|
|
22
|
+
## Shared controller
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { attachBitSub } from 'libbitsub/integrations'
|
|
26
|
+
|
|
27
|
+
const bitsub = attachBitSub(videoElement, {
|
|
28
|
+
subUrl: '/subs/movie.sup',
|
|
29
|
+
displaySettings: { scale: 1.05, bottomPadding: 4 }
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
bitsub.setDisplaySettings({ opacity: 0.9 })
|
|
33
|
+
bitsub.load({ subUrl: '/subs/other.sup' })
|
|
34
|
+
bitsub.clear()
|
|
35
|
+
bitsub.dispose()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Prefer deep imports (`libbitsub/videojs`, …) in apps so unused adapters stay out of the bundle graph.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# hls.js + libbitsub
|
|
2
|
+
|
|
3
|
+
## Install
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install libbitsub hls.js
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Recipe
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import Hls from 'hls.js'
|
|
13
|
+
import { attachBitSubToHls } from 'libbitsub/hlsjs'
|
|
14
|
+
|
|
15
|
+
const video = document.getElementById('video') as HTMLVideoElement
|
|
16
|
+
const hls = new Hls()
|
|
17
|
+
|
|
18
|
+
hls.loadSource('/media/master.m3u8')
|
|
19
|
+
hls.attachMedia(video)
|
|
20
|
+
|
|
21
|
+
// Can be created before or after attachMedia().
|
|
22
|
+
const bitsub = attachBitSubToHls(hls, {
|
|
23
|
+
subUrl: '/subs/movie.sup',
|
|
24
|
+
displaySettings: { aspectMode: 'contain' },
|
|
25
|
+
onEvent: (event) => {
|
|
26
|
+
if (event.type === 'loaded') {
|
|
27
|
+
console.log('bitmap track ready', event.metadata)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// Runtime swap:
|
|
33
|
+
bitsub.load({ subUrl: '/subs/commentary.sup', fileName: 'commentary.sup' })
|
|
34
|
+
bitsub.clear()
|
|
35
|
+
|
|
36
|
+
// Cleanup (also runs if hls.destroy() fires DESTROYING)
|
|
37
|
+
bitsub.dispose()
|
|
38
|
+
hls.destroy()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## HTML sketch
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<div style="position: relative">
|
|
45
|
+
<video id="video" controls playsinline></video>
|
|
46
|
+
</div>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Notes
|
|
50
|
+
|
|
51
|
+
- Binds to `hls.media` and re-attaches on `MEDIA_ATTACHED`.
|
|
52
|
+
- Clears on `MEDIA_DETACHED` and disposes on `DESTROYING`.
|
|
53
|
+
- hls.js continues to own HLS text tracks (WebVTT, etc.); libbitsub only draws external bitmap overlays.
|