libbitsub 1.7.3 → 1.8.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 +21 -6
- package/dist/ts/parsers.d.ts +8 -0
- package/dist/ts/parsers.d.ts.map +1 -1
- package/dist/ts/parsers.js +27 -3
- package/dist/ts/parsers.js.map +1 -1
- package/dist/ts/renderers.d.ts +1 -0
- package/dist/ts/renderers.d.ts.map +1 -1
- package/dist/ts/renderers.js +36 -13
- package/dist/ts/renderers.js.map +1 -1
- package/dist/ts/types.d.ts +6 -0
- package/dist/ts/types.d.ts.map +1 -1
- package/dist/ts/utils.d.ts +1 -0
- package/dist/ts/utils.d.ts.map +1 -1
- package/dist/ts/utils.js +20 -0
- package/dist/ts/utils.js.map +1 -1
- package/dist/ts/wasm.d.ts.map +1 -1
- package/dist/ts/wasm.js +4 -7
- package/dist/ts/wasm.js.map +1 -1
- package/dist/ts/worker.d.ts.map +1 -1
- package/dist/ts/worker.js +63 -61
- package/dist/ts/worker.js.map +1 -1
- package/package.json +1 -1
- package/pkg/README.md +21 -6
- package/pkg/libbitsub.d.ts +11 -0
- package/pkg/libbitsub.js +44 -9
- package/pkg/libbitsub_bg.wasm +0 -0
- package/pkg/libbitsub_bg.wasm.d.ts +3 -0
- package/pkg/package.json +1 -1
package/pkg/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# libbit(map)sub
|
|
2
2
|
|
|
3
|
-
High-performance WASM renderer for graphical subtitles (PGS and VobSub), written in Rust.
|
|
3
|
+
High-performance WASM renderer for graphical subtitles (PGS, VobSub, and MKS-embedded VobSub), written in Rust.
|
|
4
4
|
|
|
5
5
|
Started as a fork of Arcus92's [libpgs-js](https://github.com/Arcus92/libpgs-js), this project was reworked for higher performance and broader format support. It keeps the familiar high-level PGS-oriented API while adding a lower-level parser surface, VobSub support, GPU backends, and worker-backed rendering.
|
|
6
6
|
|
|
@@ -8,6 +8,7 @@ Started as a fork of Arcus92's [libpgs-js](https://github.com/Arcus92/libpgs-js)
|
|
|
8
8
|
|
|
9
9
|
- PGS (Blu-ray) subtitle parsing and rendering
|
|
10
10
|
- VobSub (DVD) subtitle parsing and rendering
|
|
11
|
+
- Matroska `.mks` extraction for embedded `S_VOBSUB` tracks
|
|
11
12
|
- WebGPU, WebGL2, and Canvas2D rendering with automatic fallback
|
|
12
13
|
- Worker-backed parsing/rendering for large subtitle files
|
|
13
14
|
- Rich layout controls: scale, horizontal/vertical offsets, alignment, bottom padding, safe area, opacity
|
|
@@ -46,15 +47,16 @@ deno add jsr:@altq/libbitsub
|
|
|
46
47
|
|
|
47
48
|
## Worker setup
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
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.
|
|
51
|
+
|
|
52
|
+
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`:
|
|
50
53
|
|
|
51
54
|
```bash
|
|
52
55
|
mkdir -p public/libbitsub
|
|
53
56
|
cp node_modules/libbitsub/pkg/libbitsub_bg.wasm public/libbitsub/
|
|
54
|
-
cp node_modules/libbitsub/pkg/libbitsub.js public/libbitsub/
|
|
55
57
|
```
|
|
56
58
|
|
|
57
|
-
`workerUrl`
|
|
59
|
+
The worker is still created inline. `workerUrl` remains in the option type only for compatibility and does not change runtime behavior.
|
|
58
60
|
|
|
59
61
|
## Building from source
|
|
60
62
|
|
|
@@ -130,6 +132,12 @@ const renderer = new VobSubRenderer({
|
|
|
130
132
|
idxUrl: '/subtitles/movie.idx'
|
|
131
133
|
})
|
|
132
134
|
|
|
135
|
+
const mksRenderer = new VobSubRenderer({
|
|
136
|
+
video: videoElement,
|
|
137
|
+
subUrl: '/subtitles/movie.mks',
|
|
138
|
+
fileName: 'movie.mks'
|
|
139
|
+
})
|
|
140
|
+
|
|
133
141
|
renderer.setDebandThreshold(64)
|
|
134
142
|
renderer.setDebandRange(15)
|
|
135
143
|
```
|
|
@@ -146,7 +154,7 @@ const renderer = createAutoSubtitleRenderer({
|
|
|
146
154
|
})
|
|
147
155
|
```
|
|
148
156
|
|
|
149
|
-
Automatic detection uses file hints when available and otherwise inspects the binary payload. If the format cannot be identified confidently, it throws instead of silently forcing a parser.
|
|
157
|
+
Automatic detection uses file hints when available and otherwise inspects the binary payload. `.mks` sources are treated as VobSub only when they contain an embedded `S_VOBSUB` track. If the format cannot be identified confidently, it throws instead of silently forcing a parser.
|
|
150
158
|
|
|
151
159
|
## Layout controls
|
|
152
160
|
|
|
@@ -194,8 +202,11 @@ Low-level parsers expose the same model:
|
|
|
194
202
|
```ts
|
|
195
203
|
import { PgsParser, UnifiedSubtitleParser, VobSubParserLowLevel } from 'libbitsub'
|
|
196
204
|
|
|
205
|
+
const vob = new VobSubParserLowLevel()
|
|
206
|
+
vob.loadFromMks(new Uint8Array(mksBuffer))
|
|
207
|
+
|
|
197
208
|
const parser = new UnifiedSubtitleParser()
|
|
198
|
-
const detected = parser.loadAuto({ data: subtitleBytes, fileName: 'track.
|
|
209
|
+
const detected = parser.loadAuto({ data: subtitleBytes, fileName: 'track.mks' })
|
|
199
210
|
|
|
200
211
|
console.log(detected)
|
|
201
212
|
console.log(parser.getMetadata())
|
|
@@ -210,6 +221,10 @@ Metadata includes:
|
|
|
210
221
|
- PGS composition count, palette ID, composition state
|
|
211
222
|
- VobSub language, track ID, IDX metadata presence, file position where available
|
|
212
223
|
|
|
224
|
+
## MKS security and corruption checks
|
|
225
|
+
|
|
226
|
+
The `.mks` path validates Matroska structure before handing payloads to the VobSub decoder. Embedded subtitle blocks are size-checked, compressed blocks use bounded zlib inflation, and extracted SPU packets are rejected if their declared payload lengths or control offsets are inconsistent. Malformed or oversized `.mks` payloads fail fast instead of being partially decoded.
|
|
227
|
+
|
|
213
228
|
## Cache control and prefetching
|
|
214
229
|
|
|
215
230
|
High-level renderers expose cache helpers:
|
package/pkg/libbitsub.d.ts
CHANGED
|
@@ -194,6 +194,10 @@ export class SubtitleRenderer {
|
|
|
194
194
|
* Load VobSub subtitle data from IDX and SUB.
|
|
195
195
|
*/
|
|
196
196
|
loadVobSub(idx_content: string, sub_data: Uint8Array): void;
|
|
197
|
+
/**
|
|
198
|
+
* Load VobSub subtitle data from a Matroska subtitle container.
|
|
199
|
+
*/
|
|
200
|
+
loadVobSubMks(mks_data: Uint8Array): void;
|
|
197
201
|
/**
|
|
198
202
|
* Load VobSub from SUB file only.
|
|
199
203
|
*/
|
|
@@ -303,6 +307,10 @@ export class VobSubParser {
|
|
|
303
307
|
* Load VobSub from IDX content and SUB data.
|
|
304
308
|
*/
|
|
305
309
|
loadFromData(idx_content: string, sub_data: Uint8Array): void;
|
|
310
|
+
/**
|
|
311
|
+
* Load VobSub from a Matroska subtitle container with embedded S_VOBSUB tracks.
|
|
312
|
+
*/
|
|
313
|
+
loadFromMks(mks_data: Uint8Array): void;
|
|
306
314
|
/**
|
|
307
315
|
* Load VobSub from SUB file only (scans for timestamps).
|
|
308
316
|
*/
|
|
@@ -414,6 +422,7 @@ export interface InitOutput {
|
|
|
414
422
|
readonly subtitlerenderer_language: (a: number) => [number, number];
|
|
415
423
|
readonly subtitlerenderer_loadPgs: (a: number, b: number, c: number) => number;
|
|
416
424
|
readonly subtitlerenderer_loadVobSub: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
425
|
+
readonly subtitlerenderer_loadVobSubMks: (a: number, b: number, c: number) => [number, number];
|
|
417
426
|
readonly subtitlerenderer_loadVobSubOnly: (a: number, b: number, c: number) => void;
|
|
418
427
|
readonly subtitlerenderer_new: () => number;
|
|
419
428
|
readonly subtitlerenderer_renderAtIndex: (a: number, b: number) => number;
|
|
@@ -441,6 +450,7 @@ export interface InitOutput {
|
|
|
441
450
|
readonly vobsubparser_hasIdxMetadata: (a: number) => number;
|
|
442
451
|
readonly vobsubparser_language: (a: number) => [number, number];
|
|
443
452
|
readonly vobsubparser_loadFromData: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
453
|
+
readonly vobsubparser_loadFromMks: (a: number, b: number, c: number) => [number, number];
|
|
444
454
|
readonly vobsubparser_loadFromSubOnly: (a: number, b: number, c: number) => void;
|
|
445
455
|
readonly vobsubparser_new: () => number;
|
|
446
456
|
readonly vobsubparser_renderAtIndex: (a: number, b: number) => number;
|
|
@@ -458,6 +468,7 @@ export interface InitOutput {
|
|
|
458
468
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
459
469
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
460
470
|
readonly __wbindgen_externrefs: WebAssembly.Table;
|
|
471
|
+
readonly __externref_table_dealloc: (a: number) => void;
|
|
461
472
|
readonly __wbindgen_start: () => void;
|
|
462
473
|
}
|
|
463
474
|
|
package/pkg/libbitsub.js
CHANGED
|
@@ -494,6 +494,18 @@ export class SubtitleRenderer {
|
|
|
494
494
|
const len1 = WASM_VECTOR_LEN;
|
|
495
495
|
wasm.subtitlerenderer_loadVobSub(this.__wbg_ptr, ptr0, len0, ptr1, len1);
|
|
496
496
|
}
|
|
497
|
+
/**
|
|
498
|
+
* Load VobSub subtitle data from a Matroska subtitle container.
|
|
499
|
+
* @param {Uint8Array} mks_data
|
|
500
|
+
*/
|
|
501
|
+
loadVobSubMks(mks_data) {
|
|
502
|
+
const ptr0 = passArray8ToWasm0(mks_data, wasm.__wbindgen_malloc);
|
|
503
|
+
const len0 = WASM_VECTOR_LEN;
|
|
504
|
+
const ret = wasm.subtitlerenderer_loadVobSubMks(this.__wbg_ptr, ptr0, len0);
|
|
505
|
+
if (ret[1]) {
|
|
506
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
497
509
|
/**
|
|
498
510
|
* Load VobSub from SUB file only.
|
|
499
511
|
* @param {Uint8Array} sub_data
|
|
@@ -772,6 +784,18 @@ export class VobSubParser {
|
|
|
772
784
|
const len1 = WASM_VECTOR_LEN;
|
|
773
785
|
wasm.vobsubparser_loadFromData(this.__wbg_ptr, ptr0, len0, ptr1, len1);
|
|
774
786
|
}
|
|
787
|
+
/**
|
|
788
|
+
* Load VobSub from a Matroska subtitle container with embedded S_VOBSUB tracks.
|
|
789
|
+
* @param {Uint8Array} mks_data
|
|
790
|
+
*/
|
|
791
|
+
loadFromMks(mks_data) {
|
|
792
|
+
const ptr0 = passArray8ToWasm0(mks_data, wasm.__wbindgen_malloc);
|
|
793
|
+
const len0 = WASM_VECTOR_LEN;
|
|
794
|
+
const ret = wasm.vobsubparser_loadFromMks(this.__wbg_ptr, ptr0, len0);
|
|
795
|
+
if (ret[1]) {
|
|
796
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
775
799
|
/**
|
|
776
800
|
* Load VobSub from SUB file only (scans for timestamps).
|
|
777
801
|
* @param {Uint8Array} sub_data
|
|
@@ -865,7 +889,7 @@ export function init() {
|
|
|
865
889
|
function __wbg_get_imports() {
|
|
866
890
|
const import0 = {
|
|
867
891
|
__proto__: null,
|
|
868
|
-
|
|
892
|
+
__wbg___wbindgen_throw_81fc77679af83bc6: function(arg0, arg1) {
|
|
869
893
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
870
894
|
},
|
|
871
895
|
__wbg_error_a6fa202b58aa1cd3: function(arg0, arg1) {
|
|
@@ -879,7 +903,7 @@ function __wbg_get_imports() {
|
|
|
879
903
|
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
|
880
904
|
}
|
|
881
905
|
},
|
|
882
|
-
|
|
906
|
+
__wbg_length_0c32cb8543c8e4c8: function(arg0) {
|
|
883
907
|
const ret = arg0.length;
|
|
884
908
|
return ret;
|
|
885
909
|
},
|
|
@@ -887,22 +911,22 @@ function __wbg_get_imports() {
|
|
|
887
911
|
const ret = new Error();
|
|
888
912
|
return ret;
|
|
889
913
|
},
|
|
890
|
-
|
|
914
|
+
__wbg_new_from_slice_2580ff33d0d10520: function(arg0, arg1) {
|
|
891
915
|
const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
|
|
892
916
|
return ret;
|
|
893
917
|
},
|
|
894
|
-
|
|
895
|
-
const ret = new
|
|
918
|
+
__wbg_new_with_length_6402c1de5dfd4085: function(arg0) {
|
|
919
|
+
const ret = new Float64Array(arg0 >>> 0);
|
|
896
920
|
return ret;
|
|
897
921
|
},
|
|
898
|
-
|
|
899
|
-
const ret = new
|
|
922
|
+
__wbg_new_with_length_9cedd08484b73942: function(arg0) {
|
|
923
|
+
const ret = new Uint8Array(arg0 >>> 0);
|
|
900
924
|
return ret;
|
|
901
925
|
},
|
|
902
|
-
|
|
926
|
+
__wbg_prototypesetcall_3e05eb9545565046: function(arg0, arg1, arg2) {
|
|
903
927
|
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
904
928
|
},
|
|
905
|
-
|
|
929
|
+
__wbg_set_index_e93e681c9c5b6486: function(arg0, arg1, arg2) {
|
|
906
930
|
arg0[arg1 >>> 0] = arg2;
|
|
907
931
|
},
|
|
908
932
|
__wbg_stack_3b0d974bbf31e44f: function(arg0, arg1) {
|
|
@@ -912,6 +936,11 @@ function __wbg_get_imports() {
|
|
|
912
936
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
913
937
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
914
938
|
},
|
|
939
|
+
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
940
|
+
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
941
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
942
|
+
return ret;
|
|
943
|
+
},
|
|
915
944
|
__wbindgen_init_externref_table: function() {
|
|
916
945
|
const table = wasm.__wbindgen_externrefs;
|
|
917
946
|
const offset = table.grow(4);
|
|
@@ -1020,6 +1049,12 @@ function passStringToWasm0(arg, malloc, realloc) {
|
|
|
1020
1049
|
return ptr;
|
|
1021
1050
|
}
|
|
1022
1051
|
|
|
1052
|
+
function takeFromExternrefTable0(idx) {
|
|
1053
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
1054
|
+
wasm.__externref_table_dealloc(idx);
|
|
1055
|
+
return value;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1023
1058
|
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
1024
1059
|
cachedTextDecoder.decode();
|
|
1025
1060
|
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
package/pkg/libbitsub_bg.wasm
CHANGED
|
Binary file
|
|
@@ -49,6 +49,7 @@ export const subtitlerenderer_hasIdxMetadata: (a: number) => number;
|
|
|
49
49
|
export const subtitlerenderer_language: (a: number) => [number, number];
|
|
50
50
|
export const subtitlerenderer_loadPgs: (a: number, b: number, c: number) => number;
|
|
51
51
|
export const subtitlerenderer_loadVobSub: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
52
|
+
export const subtitlerenderer_loadVobSubMks: (a: number, b: number, c: number) => [number, number];
|
|
52
53
|
export const subtitlerenderer_loadVobSubOnly: (a: number, b: number, c: number) => void;
|
|
53
54
|
export const subtitlerenderer_new: () => number;
|
|
54
55
|
export const subtitlerenderer_renderAtIndex: (a: number, b: number) => number;
|
|
@@ -76,6 +77,7 @@ export const vobsubparser_getTimestamps: (a: number) => any;
|
|
|
76
77
|
export const vobsubparser_hasIdxMetadata: (a: number) => number;
|
|
77
78
|
export const vobsubparser_language: (a: number) => [number, number];
|
|
78
79
|
export const vobsubparser_loadFromData: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
80
|
+
export const vobsubparser_loadFromMks: (a: number, b: number, c: number) => [number, number];
|
|
79
81
|
export const vobsubparser_loadFromSubOnly: (a: number, b: number, c: number) => void;
|
|
80
82
|
export const vobsubparser_new: () => number;
|
|
81
83
|
export const vobsubparser_renderAtIndex: (a: number, b: number) => number;
|
|
@@ -93,4 +95,5 @@ export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
|
93
95
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
94
96
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
95
97
|
export const __wbindgen_externrefs: WebAssembly.Table;
|
|
98
|
+
export const __externref_table_dealloc: (a: number) => void;
|
|
96
99
|
export const __wbindgen_start: () => void;
|