Fall back to KAP catch-up when an ended event has no byguid VOD.

This commit is contained in:
Jos Vooges | STH 2026-09-28 23:49:57 +02:00
parent 2137235881
commit d06b984b9d

View file

@ -458,21 +458,25 @@ async function dropEventMpdCache(mediaGuid: string, reason: string) {
}); });
} }
function isViaplayClipGuid(guid: string | null | undefined): boolean {
return /vp-sports-clip/i.test(String(guid || ""));
}
function isNoPrioritizedVideo(message: string | null | undefined): boolean {
return /no prioritized video found/i.test(String(message || ""));
}
function vodGuidCandidates(event: ViaplayEventSnapshot): string[] { function vodGuidCandidates(event: ViaplayEventSnapshot): string[] {
const out: string[] = []; const out: string[] = [];
const seen = new Set<string>(); const seen = new Set<string>();
const push = (raw: string | null | undefined) => { const push = (raw: string | null | undefined) => {
const g = String(raw || "").trim(); const g = String(raw || "").trim();
if (!g || seen.has(g)) return; if (!g || seen.has(g) || !isViaplayClipGuid(g)) return;
seen.add(g); seen.add(g);
out.push(g); out.push(g);
}; };
push(event.guid); push(event.guid);
push(event.mediaGuid); push(event.mediaGuid);
for (const g of [...out]) {
if (/-NL$/i.test(g)) push(g.replace(/-NL$/i, ""));
else if (!/vp-sports-clip/i.test(g)) push(`${g}-NL`);
}
return out; return out;
} }
@ -531,14 +535,13 @@ async function findCatchupClip(
} }
/** /**
* Terugkijken = VOD (HAR: play.viaplay.com/byguid → vod-dash / vp-sports-clip), * Alleen echte clips (HAR: vp-sports-clip → vod-dash). Live-EPG-id's (S2609…)
* niet KAP op een live-TV-MPD die al is afgelopen. * hebben geen byguid-VOD — die gaan via play-live + KAP.
*/ */
async function playEndedEventAsVod( async function tryEndedEventVod(
sessionSecret: string, sessionSecret: string,
event: ViaplayEventSnapshot event: ViaplayEventSnapshot
): Promise<ResolveViaplayPlayResult> { ): Promise<ResolveViaplayPlayResult | null> {
const errors: string[] = [];
const guids = vodGuidCandidates(event); const guids = vodGuidCandidates(event);
for (const guid of guids) { for (const guid of guids) {
@ -551,14 +554,12 @@ async function playEndedEventAsVod(
isLiveDashMpd(played.streamUrl) || isLiveDashMpd(played.streamUrl) ||
!isVodDashMpd(played.streamUrl) !isVodDashMpd(played.streamUrl)
) { ) {
errors.push(`${guid}: geen vod-dash (${mediaPathOf(played.streamUrl)})`);
continue; continue;
} }
return { ...played, live: false }; return { ...played, live: false };
} catch (err) { } catch (err) {
errors.push( const msg = err instanceof Error ? err.message : String(err);
`${guid}: ${err instanceof Error ? err.message : String(err)}` if (isNoPrioritizedVideo(msg)) break;
);
} }
} }
@ -569,29 +570,23 @@ async function playEndedEventAsVod(
settings.config.httpTimeoutMs, settings.config.httpTimeoutMs,
event event
); );
if (clip && !guids.includes(clip.guid)) { if (!clip || !isViaplayClipGuid(clip.guid) || guids.includes(clip.guid)) {
const played = await resolveViaplayGuidPlayInner(sessionSecret, clip.guid, { return null;
productUrl: clip.pageUrl,
});
if (
isDontGoPlaceholder(played.streamUrl) ||
isLiveDashMpd(played.streamUrl) ||
!isVodDashMpd(played.streamUrl)
) {
errors.push(`${clip.guid}: clip was Don't go of live-dash`);
} else {
return { ...played, live: false };
}
} }
} catch (err) { const played = await resolveViaplayGuidPlayInner(sessionSecret, clip.guid, {
errors.push(`clip: ${err instanceof Error ? err.message : String(err)}`); productUrl: clip.pageUrl,
});
if (
isDontGoPlaceholder(played.streamUrl) ||
isLiveDashMpd(played.streamUrl) ||
!isVodDashMpd(played.streamUrl)
) {
return null;
}
return { ...played, live: false };
} catch {
return null;
} }
throw new AppError(
"UPSTREAM",
`Geen VOD-replay (vod-dash/vp-sports-clip). ${errors.slice(-3).join(" · ")}`,
502
);
} }
export async function ensureViaplayEventReady( export async function ensureViaplayEventReady(
@ -609,7 +604,8 @@ export async function ensureViaplayEventReady(
const ended = Date.now() > event.endMs; const ended = Date.now() > event.endMs;
if (ended) { if (ended) {
return await playEndedEventAsVod(sessionSecret, event); const vod = await tryEndedEventVod(sessionSecret, event);
if (vod) return vod;
} }
const cachedMpd = channelMpdFromEvents(settings.config.events, event); const cachedMpd = channelMpdFromEvents(settings.config.events, event);
@ -1194,6 +1190,8 @@ async function resolveViaplayGuidPlayInner(
triedAccounts: triedLabels.length, triedAccounts: triedLabels.length,
triedLabels, triedLabels,
}); });
// Product heeft geen VOD — andere accounts geven hetzelfde.
if (isNoPrioritizedVideo(lastError.message)) break;
} }
} }