@torrent-tv/proxy 2.96.7 → 2.96.9
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/package.json
CHANGED
|
@@ -372,6 +372,14 @@ export class AviContainer extends Container {
|
|
|
372
372
|
const stream = index.packets[track.trackNumber];
|
|
373
373
|
packets.declareTrack(track.trackNumber, { type: "audio", codecId: track.codecId,
|
|
374
374
|
codecRanges: streams[track.trackNumber].codecRanges });
|
|
375
|
+
// The index says how many packets there are, so the memory they take is
|
|
376
|
+
// asked for at once. Asked for block by block, a refusal named one
|
|
377
|
+
// block, the table was discarded and built again for the next one:
|
|
378
|
+
// field 2026-10-10, 3485 refusals of 64 KB for a two-hour film's
|
|
379
|
+
// soundtrack, and no soundtrack encoder in three minutes.
|
|
380
|
+
let count = 0;
|
|
381
|
+
for (let at = 0; at < stream.count; at++) if (stream.lengths[at]) count++;
|
|
382
|
+
packets.reservePackets(track.trackNumber, count);
|
|
375
383
|
let previous = -1;
|
|
376
384
|
const append = (end) => {
|
|
377
385
|
packets.append(track.trackNumber, { pts: stream.times[previous], duration: Math.max(0, end - stream.times[previous]),
|
|
@@ -72,7 +72,13 @@ export class PacketIndex {
|
|
|
72
72
|
if (track.type !== "audio" || !isMp3Codec(track.codecId) ||
|
|
73
73
|
(interval?.trackIds && !interval.trackIds.includes(id)) || interval?.modes?.[id] === "copy") continue;
|
|
74
74
|
const records = track.packets;
|
|
75
|
-
|
|
75
|
+
// As in inputFor: records in time order are searched rather than read
|
|
76
|
+
// in full; one that starts too early to reach the interval is skipped
|
|
77
|
+
// below unless a record its preroll frames ahead does reach it.
|
|
78
|
+
const ordered = interval && records.ptsAscending;
|
|
79
|
+
const scanFrom = ordered ? Math.max(0, records.firstAtOrAfter(interval.from - records.longestDuration) - track.prerollFrames) : 0;
|
|
80
|
+
const scanTo = ordered ? records.firstAtOrAfter(interval.to) : records.length;
|
|
81
|
+
for (let position = scanFrom; position < scanTo; position++) {
|
|
76
82
|
const packet = records.at(position);
|
|
77
83
|
if (!packet.decodeDependencyUnknown || (interval &&
|
|
78
84
|
(packet.pts >= interval.to || (packet.pts < interval.from && packet.pts + packet.duration <= interval.from &&
|
|
@@ -174,7 +180,15 @@ export class PacketIndex {
|
|
|
174
180
|
const packets = track.packets;
|
|
175
181
|
const startAt = from - (track.type === "audio" && mode === "transcode" ? track.prerollSeconds : 0);
|
|
176
182
|
const selected = [];
|
|
177
|
-
|
|
183
|
+
// Records in time order are searched: only one starting within the
|
|
184
|
+
// longest duration before the interval can reach into it. Read in full,
|
|
185
|
+
// a two-hour soundtrack is 340 thousand records per interval, and the
|
|
186
|
+
// download map asked for two thousand intervals at once: the proxy's main
|
|
187
|
+
// thread stopped for minutes (Home Assistant 2026-10-10, torrent-tv/meta#166).
|
|
188
|
+
const ordered = packets.ptsAscending;
|
|
189
|
+
const scanFrom = ordered ? packets.firstAtOrAfter(startAt - packets.longestDuration) : 0;
|
|
190
|
+
const scanTo = ordered ? packets.firstAtOrAfter(to) : packets.length;
|
|
191
|
+
for (let index = scanFrom; index < scanTo; index++) {
|
|
178
192
|
const pts = packets.ptsAt(index);
|
|
179
193
|
if (pts < to && (pts >= startAt ||
|
|
180
194
|
((mode === "transcode" || track.type === "audio") && pts + packets.durationAt(index) > startAt))) selected.push(index);
|
|
@@ -17,6 +17,12 @@ export class PacketRecords {
|
|
|
17
17
|
#onDispose;
|
|
18
18
|
#disposed = false;
|
|
19
19
|
#prepaid = 0;
|
|
20
|
+
// Where the records first go back in time (-1 while they never do), the last
|
|
21
|
+
// time pushed, and the longest duration any record has had: what lets a
|
|
22
|
+
// reader find an interval by search instead of reading every record.
|
|
23
|
+
#descentAt = -1;
|
|
24
|
+
#lastPts = -Infinity;
|
|
25
|
+
#longest = 0;
|
|
20
26
|
|
|
21
27
|
constructor(memory = {}) {
|
|
22
28
|
const allocation = memory.forRecord?.(this) ?? memory;
|
|
@@ -77,9 +83,30 @@ export class PacketRecords {
|
|
|
77
83
|
this.#bytes = [...this.#blocks, ...this.#addresses].reduce((sum, buffer) => sum + buffer.length, 0);
|
|
78
84
|
}
|
|
79
85
|
this.#length = value;
|
|
86
|
+
if (this.#descentAt >= value) this.#descentAt = -1;
|
|
87
|
+
this.#lastPts = value ? this.ptsAt(value - 1) : -Infinity;
|
|
88
|
+
if (!value) this.#longest = 0;
|
|
80
89
|
if (previousBytes !== this.#bytes) this.#release(previousBytes - this.#bytes);
|
|
81
90
|
}
|
|
82
91
|
|
|
92
|
+
/** Whether every record's time is at least the one before it. */
|
|
93
|
+
get ptsAscending() { return this.#descentAt < 0; }
|
|
94
|
+
|
|
95
|
+
/** No record has lasted longer than this, though a removed one may have: a bound, not a measurement. */
|
|
96
|
+
get longestDuration() { return this.#longest; }
|
|
97
|
+
|
|
98
|
+
/** The first record whose time is at least `seconds`, `length` when there is none; only when the times ascend. */
|
|
99
|
+
firstAtOrAfter(seconds) {
|
|
100
|
+
if (!this.ptsAscending) throw new Error("Records whose times go back cannot be searched by time.");
|
|
101
|
+
let low = 0, high = this.#length;
|
|
102
|
+
while (low < high) {
|
|
103
|
+
const middle = (low + high) >>> 1;
|
|
104
|
+
if (this.ptsAt(middle) < seconds) low = middle + 1;
|
|
105
|
+
else high = middle;
|
|
106
|
+
}
|
|
107
|
+
return low;
|
|
108
|
+
}
|
|
109
|
+
|
|
83
110
|
push(packet) {
|
|
84
111
|
if (this.#disposed) throw new Error("Packet records were released.");
|
|
85
112
|
if (!Number.isFinite(packet.pts) || !Array.isArray(packet.ranges) ||
|
|
@@ -137,6 +164,9 @@ export class PacketRecords {
|
|
|
137
164
|
if (packet.streamId !== undefined) block.writeUInt32LE(packet.streamId, at + bytes - 4 - (packet.decodeFromIndex !== undefined ? 4 : 0));
|
|
138
165
|
if (packet.decodeFromIndex !== undefined) block.writeUInt32LE(packet.decodeFromIndex, at + bytes - 4);
|
|
139
166
|
this.#used += bytes;
|
|
167
|
+
if (this.#descentAt < 0 && packet.pts < this.#lastPts) this.#descentAt = this.#length;
|
|
168
|
+
this.#lastPts = packet.pts;
|
|
169
|
+
if (packet.duration > this.#longest) this.#longest = packet.duration;
|
|
140
170
|
return ++this.#length;
|
|
141
171
|
}
|
|
142
172
|
|
|
@@ -204,7 +234,9 @@ export class PacketRecords {
|
|
|
204
234
|
extendLastPresentation(seconds) {
|
|
205
235
|
if (!this.#length) return;
|
|
206
236
|
const [block, at] = this.#address(this.#length - 1);
|
|
207
|
-
block.
|
|
237
|
+
const duration = block.readDoubleLE(at + 8) + seconds;
|
|
238
|
+
block.writeDoubleLE(duration, at + 8);
|
|
239
|
+
if (duration > this.#longest) this.#longest = duration;
|
|
208
240
|
}
|
|
209
241
|
|
|
210
242
|
setDuration(index, seconds, derived = false) {
|
|
@@ -213,6 +245,7 @@ export class PacketRecords {
|
|
|
213
245
|
}
|
|
214
246
|
const [block, at] = this.#address(index);
|
|
215
247
|
block.writeDoubleLE(seconds, at + 8);
|
|
248
|
+
if (seconds > this.#longest) this.#longest = seconds;
|
|
216
249
|
const flags = block.readUInt32LE(at + 48);
|
|
217
250
|
block.writeUInt32LE(derived ? flags | 4 : flags & ~4, at + 48);
|
|
218
251
|
}
|