mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Addresses "some NIP-71 videos don't play / he has multiple links" + "speed the liveness check + don't render unplayable". - Phase 1 — multi-source capture: nip71IngestAdapter collectVideoSources() exposes a `sources` list (all video imeta urls, in order; audio/image excluded; deduped) so mirrors are preserved (the adapter previously kept only one url). - Phase 2 — multi-source liveness: urlHealthController.probeUrlList() probes every candidate (primary + sources) via the existing video-element playability probe — healthy as soon as one source plays, offline only if ALL fail. So a dead primary host no longer hides a video with a live mirror. (Card hide policy in cardSourceVisibility was already correct.) - Phase 3 — speed: URL_PROBE_TIMEOUT_MS 8s -> 4s for a fast verdict so dead cards hide quickly; WebTorrent swarm probe stays generous. Remaining (TODO #5): player-side fail-over at play time; hide-until-verified for foreign ingested videos. Tests + mutation-verified (collectVideoSources video-only filter, probeUrlList first-ok/offline/timeout). 1271/1272 unit (known UploadModal flake). Co-Authored-By: Claude Opus 4.8 <[email protected]>
58 lines
2.0 KiB
JavaScript
58 lines
2.0 KiB
JavaScript
// Multi-source URL liveness: probe candidate mirrors in order — healthy as soon
|
|
// as one plays, offline only if all fail (so a dead primary host doesn't hide a
|
|
// video that has a working mirror).
|
|
|
|
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import UrlHealthController from "../js/ui/urlHealthController.js";
|
|
|
|
function controllerWith(outcomesByUrl) {
|
|
const ctrl = new UrlHealthController({ logger: { warn() {} } });
|
|
const probed = [];
|
|
ctrl.probeUrl = async (url) => {
|
|
probed.push(url);
|
|
return { outcome: outcomesByUrl[url] || "error" };
|
|
};
|
|
return { ctrl, probed };
|
|
}
|
|
|
|
test("returns ok on the first playable source and stops probing further", async () => {
|
|
const { ctrl, probed } = controllerWith({
|
|
"https://dead/v.mp4": "error",
|
|
"https://live/v.mp4": "ok",
|
|
"https://other/v.mp4": "ok",
|
|
});
|
|
const res = await ctrl.probeUrlList([
|
|
"https://dead/v.mp4",
|
|
"https://live/v.mp4",
|
|
"https://other/v.mp4",
|
|
]);
|
|
assert.equal(res.outcome, "ok");
|
|
assert.equal(res.url, "https://live/v.mp4");
|
|
assert.deepEqual(probed, ["https://dead/v.mp4", "https://live/v.mp4"], "stops at first ok");
|
|
});
|
|
|
|
test("offline only when every source fails", async () => {
|
|
const { ctrl } = controllerWith({
|
|
"https://a/v.mp4": "error",
|
|
"https://b/v.mp4": "error",
|
|
});
|
|
const res = await ctrl.probeUrlList(["https://a/v.mp4", "https://b/v.mp4"]);
|
|
assert.equal(res.outcome, "offline");
|
|
});
|
|
|
|
test("reports timeout if none played but at least one timed out", async () => {
|
|
const { ctrl } = controllerWith({
|
|
"https://a/v.mp4": "error",
|
|
"https://b/v.mp4": "timeout",
|
|
});
|
|
const res = await ctrl.probeUrlList(["https://a/v.mp4", "https://b/v.mp4"]);
|
|
assert.equal(res.outcome, "timeout");
|
|
});
|
|
|
|
test("empty / invalid list returns error", async () => {
|
|
const { ctrl } = controllerWith({});
|
|
assert.equal((await ctrl.probeUrlList([])).outcome, "error");
|
|
assert.equal((await ctrl.probeUrlList(["", " "])).outcome, "error");
|
|
});
|