@torrent-tv/proxy 2.56.0 → 2.57.1
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/CHANGELOG.md +17 -0
- package/bin/cli.js +494 -478
- package/package.json +1 -1
- package/services/container-index/matroska-subtitles.js +83 -4
- package/services/data-channel-handler.js +1133 -949
- package/services/delivery-probe.js +374 -255
- package/services/packet-witness.js +784 -406
- package/services/subtitle-defaults.js +28 -2
- package/test/delivery-probe.test.js +158 -78
- package/test/packet-witness-ring.test.js +236 -0
- package/test/packet-witness.test.js +148 -120
- package/test/subtitle-track-numbering.test.js +111 -3
- package/test/wedge-certainty.test.js +131 -0
package/package.json
CHANGED
|
@@ -34,6 +34,29 @@ const ID_CODEC_PRIVATE = 0x63a2;
|
|
|
34
34
|
const ID_LANGUAGE = 0x22b59c;
|
|
35
35
|
const ID_NAME = 0x536e;
|
|
36
36
|
const ID_FLAG_DEFAULT = 0x88;
|
|
37
|
+
/**
|
|
38
|
+
* The rest of what a TrackEntry says about itself, RFC 9559 §5.1.4.1. Read
|
|
39
|
+
* because the file states them and a releaser's own wording in `Name` is the
|
|
40
|
+
* only thing we had before: "fors" and "SDH" in a menu were whatever text
|
|
41
|
+
* someone happened to type.
|
|
42
|
+
*
|
|
43
|
+
* `FlagEnabled` defaults to 1 and means "the track is usable"; a track that
|
|
44
|
+
* says 0 is counted but not offered. `FlagForced` applies only to subtitles and
|
|
45
|
+
* defaults to 0. `FlagHearingImpaired` is set "if and only if the track is
|
|
46
|
+
* suitable for users with hearing impairments". `FlagVisualImpaired`,
|
|
47
|
+
* `FlagOriginal` and `FlagCommentary` bear on the AUDIO choice and are read
|
|
48
|
+
* with that work, not here — see roadmap item 55.
|
|
49
|
+
*/
|
|
50
|
+
const ID_FLAG_ENABLED = 0xb9;
|
|
51
|
+
const ID_FLAG_FORCED = 0x55aa;
|
|
52
|
+
const ID_FLAG_HEARING_IMPAIRED = 0x55ab;
|
|
53
|
+
/**
|
|
54
|
+
* The language as RFC 5646 writes it. The specification is a MUST: "If this
|
|
55
|
+
* element is used, then any Language elements used in the same TrackEntry MUST
|
|
56
|
+
* be ignored" — so where both are present, this one is the answer and the
|
|
57
|
+
* three-letter code is not.
|
|
58
|
+
*/
|
|
59
|
+
const ID_LANGUAGE_BCP47 = 0x22b59d;
|
|
37
60
|
const ID_CUES = 0x1c53bb6b;
|
|
38
61
|
const ID_CUE_POINT = 0xbb;
|
|
39
62
|
const ID_CUE_TRACK_POSITIONS = 0xb7;
|
|
@@ -69,9 +92,18 @@ const TEXT_CODECS = new Set(["S_TEXT/UTF8", "S_TEXT/ASS", "S_TEXT/SSA"]);
|
|
|
69
92
|
* ever names. Text tracks alone are not a numbering: a file whose PGS track
|
|
70
93
|
* comes first would have every text track one lower here than in the browser.
|
|
71
94
|
* @property {string} codecId
|
|
72
|
-
* @property {string} language - The
|
|
95
|
+
* @property {string} language - The language the file declares: its RFC 5646
|
|
96
|
+
* tag where it writes one, and the three-letter code otherwise. The
|
|
97
|
+
* specification requires that order — where `LanguageBCP47` is present, the
|
|
98
|
+
* `Language` element MUST be ignored.
|
|
99
|
+
* @property {string} languageBcp47 - The RFC 5646 tag alone, or "".
|
|
73
100
|
* @property {string} name - What the file calls the track, if anything.
|
|
74
101
|
* @property {boolean} isDefault
|
|
102
|
+
* @property {boolean} isForced - `FlagForced`: the track carries what a viewer
|
|
103
|
+
* needs even when they asked for no subtitles — signs, and dialogue in
|
|
104
|
+
* another language. It does NOT carry the film's own dialogue.
|
|
105
|
+
* @property {boolean} isHearingImpaired - `FlagHearingImpaired`: suitable for
|
|
106
|
+
* viewers who cannot hear, so it carries non-speech sound as well as speech.
|
|
75
107
|
* @property {string} codecPrivate - The ASS/SSA header, base64, or "".
|
|
76
108
|
* @property {number[]} clusterPositions - File offsets of clusters whose cue
|
|
77
109
|
* points name this track, ascending. Empty when the file indexes only its
|
|
@@ -156,6 +188,12 @@ export async function readSubtitlePlan(readRange, fileSize) {
|
|
|
156
188
|
// amounts to, and whether the file said anything at all.
|
|
157
189
|
let isDefault = true;
|
|
158
190
|
let declaresDefault = false;
|
|
191
|
+
// Defaults straight from RFC 9559: a track is usable and not forced unless
|
|
192
|
+
// the file says otherwise, and the impaired flags are absent until claimed.
|
|
193
|
+
let isEnabled = true;
|
|
194
|
+
let isForced = false;
|
|
195
|
+
let isHearingImpaired = false;
|
|
196
|
+
let languageBcp47 = "";
|
|
159
197
|
for (const field of iterateElements(head, entry.dataOffset, entryEnd)) {
|
|
160
198
|
if (field.id === ID_TRACK_NUMBER) {
|
|
161
199
|
trackNumber = readUint(head, field.dataOffset, field.size);
|
|
@@ -165,11 +203,23 @@ export async function readSubtitlePlan(readRange, fileSize) {
|
|
|
165
203
|
codecId = readString(head, field);
|
|
166
204
|
} else if (field.id === ID_LANGUAGE) {
|
|
167
205
|
language = readString(head, field);
|
|
206
|
+
} else if (field.id === ID_LANGUAGE_BCP47) {
|
|
207
|
+
languageBcp47 = readString(head, field);
|
|
168
208
|
} else if (field.id === ID_NAME) {
|
|
169
209
|
name = readString(head, field);
|
|
170
210
|
} else if (field.id === ID_FLAG_DEFAULT) {
|
|
171
211
|
isDefault = readUint(head, field.dataOffset, field.size) === 1;
|
|
172
212
|
declaresDefault = true;
|
|
213
|
+
} else if (field.id === ID_FLAG_ENABLED) {
|
|
214
|
+
// An element written with zero length carries its default, which for
|
|
215
|
+
// this one is 1 — so an empty element must not read as "unusable", and
|
|
216
|
+
// neither must a value outside the declared 0-1 range. Only an explicit
|
|
217
|
+
// zero takes a track away.
|
|
218
|
+
isEnabled = field.size === 0 || readUint(head, field.dataOffset, field.size) !== 0;
|
|
219
|
+
} else if (field.id === ID_FLAG_FORCED) {
|
|
220
|
+
isForced = field.size > 0 && readUint(head, field.dataOffset, field.size) !== 0;
|
|
221
|
+
} else if (field.id === ID_FLAG_HEARING_IMPAIRED) {
|
|
222
|
+
isHearingImpaired = field.size > 0 && readUint(head, field.dataOffset, field.size) !== 0;
|
|
173
223
|
} else if (field.id === ID_CODEC_PRIVATE) {
|
|
174
224
|
codecPrivate = head.toString("base64", field.dataOffset, field.dataOffset + field.size);
|
|
175
225
|
}
|
|
@@ -177,17 +227,46 @@ export async function readSubtitlePlan(readRange, fileSize) {
|
|
|
177
227
|
if (type !== TRACK_TYPE_SUBTITLE || trackNumber === null) {
|
|
178
228
|
continue;
|
|
179
229
|
}
|
|
180
|
-
|
|
181
|
-
|
|
230
|
+
// A track the file marks unusable is still COUNTED. FlagEnabled says "the
|
|
231
|
+
// track is usable", and a player should not offer it — but ffmpeg does not
|
|
232
|
+
// drop it: `matroskadec.c` parses `MATROSKA_ID_TRACKFLAGENABLED` as
|
|
233
|
+
// `EBML_NONE`, reading the element and keeping nothing, so the stream is
|
|
234
|
+
// created and numbered like any other. Leaving it out of this list would
|
|
235
|
+
// therefore shift `declaredIndex` off ffmpeg's `0:s:N` for every track
|
|
236
|
+
// after it, which is the numbering defect this file was fixed for a day
|
|
237
|
+
// earlier. It is counted here and refused where it is offered instead.
|
|
238
|
+
//
|
|
239
|
+
// `language` here stays the three-letter code, because this list exists to
|
|
240
|
+
// be lined up against ffmpeg's banner, which prints that code. The RFC 5646
|
|
241
|
+
// tag rides beside it for whoever displays the track.
|
|
242
|
+
declared.push({
|
|
243
|
+
trackNumber,
|
|
244
|
+
codecId,
|
|
245
|
+
language,
|
|
246
|
+
languageBcp47,
|
|
247
|
+
name,
|
|
248
|
+
isDefault,
|
|
249
|
+
declaresDefault,
|
|
250
|
+
isEnabled,
|
|
251
|
+
isForced,
|
|
252
|
+
isHearingImpaired
|
|
253
|
+
});
|
|
254
|
+
if (!TEXT_CODECS.has(codecId) || !isEnabled) {
|
|
182
255
|
continue;
|
|
183
256
|
}
|
|
184
257
|
tracks.push({
|
|
185
258
|
trackNumber,
|
|
186
259
|
declaredIndex: declared.length - 1,
|
|
187
260
|
codecId,
|
|
188
|
-
|
|
261
|
+
// This list is ours and is not compared with ffmpeg's, so it carries the
|
|
262
|
+
// language the file states most precisely: where RFC 5646 is written, the
|
|
263
|
+
// three-letter code MUST be ignored.
|
|
264
|
+
language: languageBcp47 || language,
|
|
265
|
+
languageBcp47,
|
|
189
266
|
name,
|
|
190
267
|
isDefault,
|
|
268
|
+
isForced,
|
|
269
|
+
isHearingImpaired,
|
|
191
270
|
codecPrivate,
|
|
192
271
|
clusterPositions: []
|
|
193
272
|
});
|