@torrent-tv/proxy 2.100.2 → 2.100.3
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
package/server.js
CHANGED
|
@@ -972,8 +972,12 @@ export async function startProxyServer({
|
|
|
972
972
|
const answer = input.read(source.fileIndex, start, end);
|
|
973
973
|
return answer && typeof answer.then !== "function" && answer.end === end ? answer.bytes : null;
|
|
974
974
|
};
|
|
975
|
+
const holdsUntil = start => {
|
|
976
|
+
const range = source.input.ranges.find(([first, last]) => first <= start && start <= last);
|
|
977
|
+
return range ? range[1] + 1 : null;
|
|
978
|
+
};
|
|
975
979
|
const startedAt = Date.now();
|
|
976
|
-
void container.learnPackets({ from: source.input.from, to: source.input.to, trackIds: [...sounds] }, read).then(learned =>
|
|
980
|
+
void container.learnPackets({ from: source.input.from, to: source.input.to, trackIds: [...sounds] }, read, holdsUntil).then(learned =>
|
|
977
981
|
logger.info(`encode input #${from}..#${to} of ${output.outputKey}: soundtrack packets of track(s) ${[...sounds].join(",")} ` +
|
|
978
982
|
`over ${source.input.from.toFixed(3)}-${source.input.to.toFixed(3)}s ` +
|
|
979
983
|
(learned === "walked" ? "walked" : `not all walked (${learned === "memory" ? "memory refused" : "the copy does not hold the rest"})`) +
|
|
@@ -792,7 +792,7 @@ export class MatroskaContainer extends Container {
|
|
|
792
792
|
* `account`, when given, is told how long each track's walk waited for
|
|
793
793
|
* that track's earlier walks and what it read (`lockMs`, `reads`, `bytes`).
|
|
794
794
|
*/
|
|
795
|
-
async readPacketIndex(interval, { isCurrent, readRange, account } = {}) {
|
|
795
|
+
async readPacketIndex(interval, { isCurrent, readRange, holdsUntil, account } = {}) {
|
|
796
796
|
if (this.#packets) return this.#packets;
|
|
797
797
|
const layout = await this.#segmentLayout();
|
|
798
798
|
if (!layout) throw new Error("Matroska Segment is absent.");
|
|
@@ -812,7 +812,7 @@ export class MatroskaContainer extends Container {
|
|
|
812
812
|
let whole = true;
|
|
813
813
|
for (const track of requested) {
|
|
814
814
|
const chain = await this.#readTrackPackets(layout, tracks, track, start, interval, isCurrent,
|
|
815
|
-
readRange ? strictReader(readRange, this.fileSize) : this.readRange, account);
|
|
815
|
+
readRange ? strictReader(readRange, this.fileSize) : this.readRange, account, readRange ? holdsUntil : null);
|
|
816
816
|
if (!chain) return null;
|
|
817
817
|
streams.set(track.trackNumber, chain.records);
|
|
818
818
|
if (chain.reachesEnd) complete.add(track.trackNumber);
|
|
@@ -837,13 +837,14 @@ export class MatroskaContainer extends Container {
|
|
|
837
837
|
*
|
|
838
838
|
* @param {{ from: number, to: number, trackIds: number[] }} interval
|
|
839
839
|
* @param {(start: number, end: number) => Buffer | null} readRange - Null where it does not hold the bytes.
|
|
840
|
+
* @param {(start: number) => number | null} [holdsUntil] - One past the last byte held from `start` on, if known.
|
|
840
841
|
* @returns {Promise<"walked" | "missing" | "memory">} Whether the
|
|
841
842
|
* interval's packets are recorded, or what stopped the walk: bytes the
|
|
842
843
|
* copy does not hold, or memory refused.
|
|
843
844
|
*/
|
|
844
|
-
async learnPackets(interval, readRange) {
|
|
845
|
+
async learnPackets(interval, readRange, holdsUntil = null) {
|
|
845
846
|
try {
|
|
846
|
-
return await this.readPacketIndex(interval, { readRange }) !== null ? "walked" : "missing";
|
|
847
|
+
return await this.readPacketIndex(interval, { readRange, holdsUntil }) !== null ? "walked" : "missing";
|
|
847
848
|
} catch (error) {
|
|
848
849
|
// The sound's own walk reads the rest later, from where this one stopped.
|
|
849
850
|
if (isUnavailable(error)) return "missing";
|
|
@@ -865,7 +866,7 @@ export class MatroskaContainer extends Container {
|
|
|
865
866
|
*
|
|
866
867
|
* @returns {Promise<{ records: PacketRecordsChain, startAt: number, reachesEnd: boolean }>}
|
|
867
868
|
*/
|
|
868
|
-
async #readTrackPackets(layout, tracks, track, start, interval, isCurrent, reader, account = null) {
|
|
869
|
+
async #readTrackPackets(layout, tracks, track, start, interval, isCurrent, reader, account = null, holdsUntil = null) {
|
|
869
870
|
const id = track.trackNumber;
|
|
870
871
|
const previous = this.#packetWalks.get(id) ?? Promise.resolve();
|
|
871
872
|
let finished;
|
|
@@ -930,7 +931,7 @@ export class MatroskaContainer extends Container {
|
|
|
930
931
|
const following = readings.find(reading => reading.startAt > current.startAt);
|
|
931
932
|
const outcome = await walkMatroskaPackets({ readRange: read, fileSize: this.fileSize,
|
|
932
933
|
portionBytes: this.portionBytes, layout, tracks, trackIds: [id], interval, packetMemory: this.packetMemory,
|
|
933
|
-
state: current, until: following?.startAt ?? null, isCovered: covered, readsThrough, isCurrent });
|
|
934
|
+
state: current, until: following?.startAt ?? null, isCovered: covered, readsThrough, isCurrent, holdsUntil });
|
|
934
935
|
if (outcome === "obsolete") return null;
|
|
935
936
|
if (outcome !== "until") break;
|
|
936
937
|
current.next = following;
|
|
@@ -49,7 +49,7 @@ function recordedTracks(tracks, trackIds) {
|
|
|
49
49
|
*
|
|
50
50
|
* @returns {Promise<"covered" | "until" | "end" | "obsolete">}
|
|
51
51
|
*/
|
|
52
|
-
export async function walkMatroskaPackets({ readRange, fileSize, portionBytes, layout, tracks, trackIds, interval, packetMemory, state, until = null, isCovered = null, readsThrough = null, isCurrent = null }) {
|
|
52
|
+
export async function walkMatroskaPackets({ readRange, fileSize, portionBytes, layout, tracks, trackIds, interval, packetMemory, state, until = null, isCovered = null, readsThrough = null, isCurrent = null, holdsUntil = null }) {
|
|
53
53
|
// INSIDE A CLUSTER EVERY BLOCK HEADER IS READ, so its bytes are read a
|
|
54
54
|
// portion at a time up to the cluster's end, and never past it. Read a
|
|
55
55
|
// header at a time, each a read of a few bytes from the torrent thread, the
|
|
@@ -61,8 +61,14 @@ export async function walkMatroskaPackets({ readRange, fileSize, portionBytes, l
|
|
|
61
61
|
// (r54). The headers lie throughout the portion, so it is all needed.
|
|
62
62
|
// Between clusters only their headers are read.
|
|
63
63
|
let readableUntil = null;
|
|
64
|
+
// `holdsUntil` bounds a portion by what the reader holds, so a walk over a
|
|
65
|
+
// copy reads up to its end what it needs, not a portion past it (r63).
|
|
64
66
|
const reader = new ElementReader({ read: readRange, fileSize, portionBytes, prefetch: true,
|
|
65
|
-
readableUntil: start =>
|
|
67
|
+
readableUntil: start => {
|
|
68
|
+
const reach = Math.max(readableUntil ?? start, readsThrough?.(start) ?? start);
|
|
69
|
+
const held = holdsUntil?.(start);
|
|
70
|
+
return Number.isFinite(held) ? Math.min(reach, held) : reach;
|
|
71
|
+
} });
|
|
66
72
|
const declared = recordedTracks(tracks, trackIds);
|
|
67
73
|
if (!state.packets) {
|
|
68
74
|
state.packets = new Map([...declared.keys()].map(id => [id, new PacketRecords(packetMemory)]));
|