@torrent-tv/proxy 2.99.6 → 2.99.8
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
|
@@ -653,16 +653,15 @@ export class MatroskaContainer extends Container {
|
|
|
653
653
|
* One preceding cluster retains preroll; one following cluster covers demux
|
|
654
654
|
* lookahead beyond the presentation cut. No packet payload is parsed here.
|
|
655
655
|
*/
|
|
656
|
-
async supportsOriginalSourceRanges(
|
|
656
|
+
async supportsOriginalSourceRanges() {
|
|
657
657
|
const cues = await this.readCues();
|
|
658
658
|
if (!cues?.points.length) return false;
|
|
659
659
|
const video = ContainerTrack.firstUsable(await this.readTracks(), "video");
|
|
660
|
-
//
|
|
661
|
-
// (
|
|
662
|
-
//
|
|
663
|
-
//
|
|
664
|
-
//
|
|
665
|
-
if (video && interval?.trackIds?.length && !interval.trackIds.includes(video.trackNumber)) return false;
|
|
660
|
+
// A soundtrack alone is read from the original file too, picture clusters
|
|
661
|
+
// included (38 MB for one piece of 171 KB of sound, r46). Read from its own
|
|
662
|
+
// packets (proxy 2.99.6), the soundtrack's packet table was refused memory
|
|
663
|
+
// on Home Assistant, its first run was given one piece and never closed
|
|
664
|
+
// it, and no Matroska film started (r47, torrent-tv/meta#178).
|
|
666
665
|
return cues.points.some(point => point.positions.some(position => !video || position.track === video.trackNumber));
|
|
667
666
|
}
|
|
668
667
|
|
|
@@ -94,19 +94,20 @@ export async function futureDownload(entries, { now = Date.now(), findStore = pi
|
|
|
94
94
|
continue;
|
|
95
95
|
}
|
|
96
96
|
const remaining = piece?.missing;
|
|
97
|
-
const
|
|
97
|
+
const holders = [];
|
|
98
|
+
for (const wire of torrent.wires ?? []) {
|
|
98
99
|
// Only a peer that can be asked for it now: one choking us is asked for
|
|
99
100
|
// nothing outside the pieces it allows, whatever it carried before.
|
|
100
|
-
if (wire.destroyed || !wire.peerPieces?.get(index) || !mayAsk(wire, index))
|
|
101
|
+
if (wire.destroyed || !wire.peerPieces?.get(index) || !mayAsk(wire, index)) continue;
|
|
101
102
|
// What it carried with its queue kept full, where it has been seen so:
|
|
102
103
|
// its speed while our selection gave it little measures our asking
|
|
103
104
|
// (`SelectionLimit`, torrent-tv/meta#178).
|
|
104
105
|
const rate = Number(limit?.capacityOf?.(wire) ?? wire.downloadSpeed?.());
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
pending.push({ arrivals, index, ...band,
|
|
108
|
-
Number.isSafeInteger(remaining) && remaining > 0 && remaining <= piece.length &&
|
|
109
|
-
? remaining
|
|
106
|
+
if (Number.isFinite(rate) && rate > 0) holders.push({ wire, rate });
|
|
107
|
+
}
|
|
108
|
+
pending.push({ arrivals, index, ...band, holders, remaining:
|
|
109
|
+
Number.isSafeInteger(remaining) && remaining > 0 && remaining <= piece.length && holders.length > 0
|
|
110
|
+
? remaining : null });
|
|
110
111
|
if (++steps % 256 === 0) {
|
|
111
112
|
await nextTurn();
|
|
112
113
|
if (!isCurrent()) return new Map();
|
|
@@ -120,15 +121,62 @@ export async function futureDownload(entries, { now = Date.now(), findStore = pi
|
|
|
120
121
|
// before it have. Charged the whole band's end instead, a band of many
|
|
121
122
|
// segments — the map states one per stretch of a level since 2.97.27 — would
|
|
122
123
|
// put its nearest piece at its farthest piece's time (torrent-tv/meta#178).
|
|
124
|
+
//
|
|
125
|
+
// AND IN PARALLEL WHERE THE PEERS DIFFER. A piece is brought by the peers
|
|
126
|
+
// holding it, each from when it has brought what was asked of it before, and
|
|
127
|
+
// no sooner than the measured supply of every peer that holds a piece still
|
|
128
|
+
// to come carries all the bytes ahead of it. Summed one piece after another
|
|
129
|
+
// at its own holders' speed, a two-hour film whose far pieces each had a few
|
|
130
|
+
// unchoked holders was forecast to arrive in 127 838 s at 2.33 MB/s, and a
|
|
131
|
+
// seek was held for 39 s on it (r49, torrent-tv/meta#178). One holder for
|
|
132
|
+
// every piece gives the sum it was; a piece nobody can be asked for still
|
|
133
|
+
// leaves every piece after it unknown.
|
|
123
134
|
pending.sort((left, right) => compareBands(left, right) || left.index - right.index);
|
|
124
|
-
|
|
125
|
-
for (const {
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
const supply = new Map();
|
|
136
|
+
for (const { holders } of pending) for (const { wire, rate } of holders) supply.set(wire, rate);
|
|
137
|
+
const total = [...supply.values()].reduce((sum, rate) => sum + rate, 0);
|
|
138
|
+
const freeAt = new Map();
|
|
139
|
+
let ahead = 0;
|
|
140
|
+
let known = true;
|
|
141
|
+
for (const { arrivals, index, holders, remaining } of pending) {
|
|
142
|
+
if (!known || remaining === null || !(total > 0)) {
|
|
143
|
+
known = false;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
ahead += remaining;
|
|
147
|
+
const finish = Math.max(sharedFinish(holders, freeAt, remaining, now), now + ahead / total * 1000);
|
|
148
|
+
for (const { wire } of holders) freeAt.set(wire, Math.max(freeAt.get(wire) ?? now, finish));
|
|
149
|
+
arrivals.set(index, finish);
|
|
128
150
|
}
|
|
129
151
|
return isCurrent() ? forecasts : new Map();
|
|
130
152
|
}
|
|
131
153
|
|
|
154
|
+
/**
|
|
155
|
+
* When peers bringing `bytes` together finish: each starts when it is free
|
|
156
|
+
* and brings at its own rate, so the finish is where their combined bytes
|
|
157
|
+
* reach `bytes` (the earliest of them working alone at first, more joining as
|
|
158
|
+
* they come free).
|
|
159
|
+
*
|
|
160
|
+
* @param {Array<{ wire: object, rate: number }>} holders - Bytes per second.
|
|
161
|
+
* @param {Map<object, number>} freeAt - Milliseconds.
|
|
162
|
+
* @param {number} bytes
|
|
163
|
+
* @param {number} now - Milliseconds.
|
|
164
|
+
* @returns {number} Milliseconds.
|
|
165
|
+
*/
|
|
166
|
+
function sharedFinish(holders, freeAt, bytes, now) {
|
|
167
|
+
const starts = holders.map(({ wire, rate }) => ({ at: Math.max(now, freeAt.get(wire) ?? now), rate }))
|
|
168
|
+
.sort((left, right) => left.at - right.at);
|
|
169
|
+
let rate = 0;
|
|
170
|
+
let weighted = 0;
|
|
171
|
+
for (let index = 0; index < starts.length; index++) {
|
|
172
|
+
rate += starts[index].rate;
|
|
173
|
+
weighted += starts[index].rate * starts[index].at;
|
|
174
|
+
const finish = (bytes * 1000 + weighted) / rate;
|
|
175
|
+
if (index === starts.length - 1 || finish <= starts[index + 1].at) return finish;
|
|
176
|
+
}
|
|
177
|
+
return now;
|
|
178
|
+
}
|
|
179
|
+
|
|
132
180
|
/**
|
|
133
181
|
* Whether this peer can be asked for this piece now: it is not choking us, or
|
|
134
182
|
* it allows this piece while it does (BEP 6, WebTorrent 2.8.5 `_updateWire`).
|