Fix Viaplay catch-up without live replay.
Reuse the channel MPD and keys with a KAP window instead of play-live plus CDM per account.
This commit is contained in:
parent
7cdff2bde4
commit
d1c3176ffe
2 changed files with 74 additions and 6 deletions
|
|
@ -1204,25 +1204,31 @@ export async function playByGuid(
|
|||
throw lastError || new Error("Viaplay VOD-play mislukt");
|
||||
}
|
||||
|
||||
/** Haal een eventuele /start/N/stop/N window uit de MPD-URL. */
|
||||
export function stripKapWindow(mpdUrl: string): string {
|
||||
return mpdUrl.replace(/\/start\/\d+\/stop\/\d+/g, "");
|
||||
}
|
||||
|
||||
/** Bouw MPD-URL met EPG start/stop kap (seconden). */
|
||||
export function kapMpdUrl(
|
||||
mpdUrl: string,
|
||||
startMs: number,
|
||||
endMs: number
|
||||
): string[] {
|
||||
const base = stripKapWindow(mpdUrl);
|
||||
const startSec = Math.floor(startMs / 1000);
|
||||
const stopSec = Math.floor(endMs / 1000);
|
||||
try {
|
||||
const u = new URL(mpdUrl);
|
||||
const u = new URL(base);
|
||||
const file = u.pathname.split("/").pop() || "dash.mpd";
|
||||
const dir = mpdUrl.replace(/\/[^/]+$/, "");
|
||||
const dir = base.replace(/\/[^/]+$/, "");
|
||||
return [
|
||||
`${dir}/start/${startSec}/stop/${stopSec}/${file}`,
|
||||
`${dir}/start/${startSec}/stop/${stopSec}/index.mpd`,
|
||||
mpdUrl,
|
||||
base,
|
||||
];
|
||||
} catch {
|
||||
return [mpdUrl];
|
||||
return [base];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,23 @@ function accountOrder(
|
|||
return ordered;
|
||||
}
|
||||
|
||||
function channelMpdFromEvents(
|
||||
events: ViaplayEventSnapshot[],
|
||||
event: ViaplayEventSnapshot
|
||||
): string | null {
|
||||
if (event.mpdUrl?.trim()) return event.mpdUrl.trim();
|
||||
const channel = event.channelName?.trim().toLowerCase();
|
||||
const station = event.stationId?.trim();
|
||||
if (!channel && !station) return null;
|
||||
for (const other of events) {
|
||||
const url = other.mpdUrl?.trim();
|
||||
if (!url) continue;
|
||||
if (station && other.stationId?.trim() === station) return url;
|
||||
if (channel && other.channelName?.trim().toLowerCase() === channel) return url;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function ensureViaplayEventReady(
|
||||
sessionSecret: string,
|
||||
event: ViaplayEventSnapshot,
|
||||
|
|
@ -174,13 +191,17 @@ export async function ensureViaplayEventReady(
|
|||
event.accountIds ||
|
||||
[];
|
||||
|
||||
const ended = Date.now() > event.endMs;
|
||||
const cachedMpd = channelMpdFromEvents(settings.config.events, event);
|
||||
|
||||
let cachedKeys = await keysForMediaGuid(sessionSecret, mediaGuid);
|
||||
if (!cachedKeys.length) {
|
||||
cachedKeys = await keysForChannelPath(sessionSecret, event.mpdUrl);
|
||||
cachedKeys = await keysForChannelPath(sessionSecret, event.mpdUrl || cachedMpd);
|
||||
}
|
||||
|
||||
const cacheFresh =
|
||||
!opts?.forceRefresh &&
|
||||
!ended &&
|
||||
!!event.mpdUrl &&
|
||||
isMpdCacheFresh(event.mpdCachedAt, tweaks.mpdCacheTtlMinutes);
|
||||
|
||||
|
|
@ -194,6 +215,40 @@ export async function ensureViaplayEventReady(
|
|||
};
|
||||
}
|
||||
|
||||
// Terugkijken: zelfde pad als het werkende script — KAP op zender-MPD, geen play-live.
|
||||
if (ended && cachedMpd && !opts?.forceRefresh) {
|
||||
try {
|
||||
const kap = await resolveKapMpd(
|
||||
cachedMpd,
|
||||
event.startMs,
|
||||
event.endMs,
|
||||
tweaks.httpTimeoutMs
|
||||
);
|
||||
if (!cachedKeys.length) {
|
||||
cachedKeys = await keysForChannelPath(sessionSecret, kap.mpdUrl);
|
||||
}
|
||||
if (cachedKeys.length) {
|
||||
await patchViaplayEventCache(mediaGuid, {
|
||||
mpdUrl: kap.mpdUrl,
|
||||
mpdCachedAt: new Date().toISOString(),
|
||||
hasPssh: kap.hasPssh,
|
||||
hasKeys: true,
|
||||
lastPlayError: null,
|
||||
lastPlayAt: new Date().toISOString(),
|
||||
});
|
||||
return {
|
||||
streamUrl: kap.mpdUrl,
|
||||
format: "dash",
|
||||
keys: cachedKeys,
|
||||
fromCache: true,
|
||||
mediaGuid,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
/* play-live hieronder */
|
||||
}
|
||||
}
|
||||
|
||||
// Cache MPD zonder keys is ok als keys later komen — of clear feed
|
||||
if (cacheFresh && event.mpdUrl && !(opts?.fetchKeys ?? tweaks.fetchKeysIfMissing)) {
|
||||
return {
|
||||
|
|
@ -243,6 +298,9 @@ export async function ensureViaplayEventReady(
|
|||
);
|
||||
|
||||
let keys = cachedKeys;
|
||||
if (!keys.length) {
|
||||
keys = await keysForChannelPath(sessionSecret, play.mpdUrl);
|
||||
}
|
||||
const wantKeys = opts?.fetchKeys ?? tweaks.fetchKeysIfMissing;
|
||||
if (wantKeys && play.licenseUrl && !keys.length) {
|
||||
const pssh =
|
||||
|
|
@ -314,7 +372,11 @@ export async function ensureViaplayEventReady(
|
|||
lastPlayError: lastError?.message || "Play mislukt",
|
||||
lastPlayAt: new Date().toISOString(),
|
||||
});
|
||||
throw lastError || new Error("Viaplay play mislukt");
|
||||
throw new AppError(
|
||||
"UPSTREAM",
|
||||
lastError?.message || "Viaplay play mislukt",
|
||||
502
|
||||
);
|
||||
}
|
||||
|
||||
export async function resolveViaplayPlay(
|
||||
|
|
|
|||
Loading…
Reference in a new issue