@torrent-tv/proxy 2.55.5 → 2.55.6
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
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 2.55.6
|
|
2
|
+
|
|
3
|
+
- **Chore**: Every step of the subtitle push chain now logs on success, not only on failure. Field report 2026-08-22, playing `Minions.and.Monsters.1080p.mkv`: a track was switched on over a minute after the seed fetch found nothing (`bytes=7`, an empty `WEBVTT` — expected, the torrent had barely started), and no cues appeared. The proxy log carried no evidence either way — `warmActiveFiles` posted `Event.SUBTITLE_CUES_READY` silently, `publishSubtitleCues` sent (or found no subscriber for) a push silently, and `subscribeSubtitles` registered a channel silently. Confirmed separately by reading WebTorrent's own source that `verified` fires on every live piece completion (`_markVerified` inside `store.put`'s callback in `torrent.js`, not only at startup), so the event source itself is real; what could not be told apart without these lines is subscription, discovery, and delivery. Logs now name each: `subtitle push: channel subscribed to …`, `… cue(s) found, posting to main thread`, `… sent N cue(s) … to M/T channel(s)` (or `found no subscribed channel`).
|
|
4
|
+
|
|
1
5
|
## 2.55.5
|
|
2
6
|
|
|
3
7
|
- **New**: Subtitle cues are now PUSHED to the browser the moment they are read, over the WebRTC data channel — not fetched by the browser on a timer. Every declared track was already being warmed off the piece-`verified` event (2.55.4); what changed is that the result now travels to the browser unprompted instead of sitting on the proxy until the next poll asked for it. `data-channel-handler.js` remembers which channel last asked about a file's subtitles (piggy-backing on the browser's own first `/api/subtitles?trackIndex=` request — no separate subscribe message) and sends new cues there directly (`{ type: "subtitle-cues", fileIndex, trackIndex, cues, language }`), for every track the container declares, not only the one on screen. Rides the existing `proxy-control` data channel — the same one the request itself used, which is never the one carrying segment bytes, so a push cannot queue behind video. `finalizeCues` (end-time synthesis + ASS-dialogue stripping) is factored out of the HTTP route into `services/torrent-worker/subtitle-cues.js` so a pushed cue and a pulled one are built the same way. A browser's one-off seed fetch per track (for whatever is already read at the moment a file opens) and the external-subtitle-FILE path (`.srt`/`.ass` beside the video — a single whole-file read, no incremental delivery to begin with) are unchanged.
|
package/package.json
CHANGED
|
@@ -324,7 +324,11 @@ export function createDataChannelHandler({ proxyPort, onLog, getTransportSnapsho
|
|
|
324
324
|
set = new Set();
|
|
325
325
|
subtitleSubscribers.set(key, set);
|
|
326
326
|
}
|
|
327
|
+
const isNew = !set.has(channel);
|
|
327
328
|
set.add(channel);
|
|
329
|
+
if (isNew) {
|
|
330
|
+
log(`[dc] subtitle push: channel subscribed to ${key} (${set.size} channel(s) now)`);
|
|
331
|
+
}
|
|
328
332
|
}
|
|
329
333
|
|
|
330
334
|
/** @param {DataChannel} channel */
|
|
@@ -346,18 +350,29 @@ export function createDataChannelHandler({ proxyPort, onLog, getTransportSnapsho
|
|
|
346
350
|
function publishSubtitleCues({ sourceKey, fileIndex, trackIndex, cues, language }) {
|
|
347
351
|
const set = subtitleSubscribers.get(`${sourceKey}:${fileIndex}`);
|
|
348
352
|
if (!set || set.size === 0) {
|
|
353
|
+
log(
|
|
354
|
+
`[dc] subtitle push: ${cues.length} cue(s) for ${sourceKey.slice(0, 8)}:${fileIndex} track ${trackIndex} ` +
|
|
355
|
+
"found no subscribed channel"
|
|
356
|
+
);
|
|
349
357
|
return;
|
|
350
358
|
}
|
|
351
359
|
const message = { type: "subtitle-cues", fileIndex, trackIndex, cues, language };
|
|
360
|
+
const total = set.size;
|
|
361
|
+
let sent = 0;
|
|
352
362
|
for (const channel of set) {
|
|
353
363
|
try {
|
|
354
364
|
channel.sendMessage(JSON.stringify(message));
|
|
365
|
+
sent += 1;
|
|
355
366
|
} catch {
|
|
356
367
|
// Closed between the subscription and this send; onClosed will not
|
|
357
368
|
// fire for a channel that is already gone, so drop it here too.
|
|
358
369
|
set.delete(channel);
|
|
359
370
|
}
|
|
360
371
|
}
|
|
372
|
+
log(
|
|
373
|
+
`[dc] subtitle push: sent ${cues.length} cue(s) for ${sourceKey.slice(0, 8)}:${fileIndex} track ${trackIndex} ` +
|
|
374
|
+
`to ${sent}/${total} channel(s)`
|
|
375
|
+
);
|
|
361
376
|
}
|
|
362
377
|
|
|
363
378
|
/** Request id → its ASCII bytes; see {@link requestIdBytes}. */
|
|
@@ -525,6 +525,10 @@ function warmActiveFiles(sourceKey, torrent) {
|
|
|
525
525
|
warmSubtitleCues(torrent, fileIndex, sourceKey)
|
|
526
526
|
.then((fresh) => {
|
|
527
527
|
for (const entry of fresh) {
|
|
528
|
+
log(
|
|
529
|
+
`subtitle push ${sourceKey.slice(0, 8)}:${fileIndex} track ${entry.trackIndex}: ` +
|
|
530
|
+
`${entry.cues.length} new cue(s) found, posting to main thread`
|
|
531
|
+
);
|
|
528
532
|
parentPort.postMessage({
|
|
529
533
|
type: Event.SUBTITLE_CUES_READY,
|
|
530
534
|
sourceKey,
|