Fix Viaplay VOD live-edge seek and slow Token Tray typing.

Clips no longer use DASH live configuration (was jumping to end). Tray 0.1.2 types slower; no inter-account pause.
This commit is contained in:
Jos Vooges | STH 2026-09-23 02:38:26 +02:00
parent bedebf44f6
commit f9ec3be09e
9 changed files with 25 additions and 26 deletions

View file

@ -20,8 +20,8 @@ android {
applicationId = "nl.vonas.mediacluster.tv"
minSdk = 24
targetSdk = 36
versionCode = 147
versionName = "0.14.84"
versionCode = 148
versionName = "0.14.85"
buildConfigField("String", "DEFAULT_API_BASE", "\"https://master.vonas.nl\"")
ndk {
abiFilters += listOf("arm64-v8a", "armeabi-v7a")

View file

@ -340,12 +340,16 @@ private fun bytesToUuid(bytes: ByteArray): UUID {
return UUID(buf.long, buf.long)
}
/** TS / HLS / DASH(+ClearKey). */
/** TS / HLS / DASH(+ClearKey).
* @param live live-edge seek (IPTV/events). Zet false voor VOD/clips — anders landt
* ExoPlayer op het einde van een static/VOD-DASH (lijkt op “afgelopen”-scherm).
*/
@OptIn(UnstableApi::class)
fun liveMediaItem(
url: String,
format: String,
drm: DrmInfo? = null,
live: Boolean = true,
): MediaItem {
// URL wint: ESPN/FAAB levert .m3u8 terwijl de API soms format=dash hardcodet.
val isHls = url.contains("m3u8", ignoreCase = true) ||
@ -359,7 +363,7 @@ fun liveMediaItem(
else -> MimeTypes.VIDEO_MP2T
}
val builder = MediaItem.Builder().setUri(url).setMimeType(mime)
if (isHls) {
if (live && isHls) {
builder.setLiveConfiguration(
MediaItem.LiveConfiguration.Builder()
.setTargetOffsetMs(2_000)
@ -368,7 +372,7 @@ fun liveMediaItem(
.build(),
)
}
if (isDash) {
if (live && isDash) {
builder.setLiveConfiguration(
MediaItem.LiveConfiguration.Builder()
.setTargetOffsetMs(3_000)

View file

@ -168,8 +168,10 @@ fun EventPlayerScreen(
return@LaunchedEffect
}
// ClearKey optioneel: F1TV plain HLS heeft drm=null.
// VOD/clips: geen live-config — anders seek naar “live edge” = eindscherm.
val asVod = hubPlay && eventId.startsWith("viaplay-content:", ignoreCase = true)
val item = try {
liveMediaItem(url, play.format, play.drm)
liveMediaItem(url, play.format, play.drm, live = !asVod)
} catch (e: Exception) {
error = e.message ?: "Kon mediastream niet openen"
return@LaunchedEffect

View file

@ -1,6 +1,6 @@
{
"name": "@media-cluster/token-tray",
"version": "0.1.1",
"version": "0.1.2",
"private": true,
"description": "Windows system tray helper to refresh Viaplay/F1TV session tokens",
"author": "Vonas Media Cluster",

View file

@ -3,7 +3,6 @@ import type { TrayConfig } from "./config";
import { saveConfig } from "./config";
import { loginViaplayUi } from "./login/viaplay";
import { loginF1tvUi } from "./login/f1tv";
import { betweenAccounts } from "./login/human";
export type AgentAccount = {
provider: "viaplay" | "f1tv";
@ -145,17 +144,11 @@ export async function refreshAccountsSilent(
const notify = opts?.notify !== false;
const summary: RefreshSummary = { ok: 0, failed: 0, skipped: 0, errors: [] };
let attempted = 0;
for (const acc of accounts) {
if (!acc.password?.trim()) {
summary.skipped += 1;
continue;
}
if (attempted > 0) {
// Captcha-vriendelijk: niet back-to-back inloggen op meerdere accounts
await betweenAccounts();
}
attempted += 1;
try {
await refreshOne(cfg, acc, headless);
summary.ok += 1;

View file

@ -84,7 +84,7 @@ async function launchProfile(userDataDir: string, headless: boolean) {
headless,
viewport: { width: 1280, height: 900 } as const,
args: ["--disable-blink-features=AutomationControlled"],
slowMo: 40 + Math.floor(Math.random() * 50),
slowMo: 15 + Math.floor(Math.random() * 25),
};
for (const channel of ["chrome", "msedge"] as const) {
try {

View file

@ -18,7 +18,7 @@ export function afterNavigate(): Promise<void> {
return humanDelay(1800, 4200);
}
/** Pauze tussen accounts bij batch-refresh (captcha-vriendelijk). */
/** Pauze tussen accounts bij batch-refresh (optioneel; standaard niet gebruikt). */
export function betweenAccounts(): Promise<void> {
return humanDelay(12_000, 28_000);
}
@ -46,11 +46,11 @@ export async function humanType(
delay: 60 + Math.floor(Math.random() * 100),
});
await humanDelay(200, 550);
// Per-character delay; geen instant fill()
// Per-character delay; geen instant fill() — expres traag tegen CAPTCHA
await locator.pressSequentially(text, {
delay: 55 + Math.floor(Math.random() * 90),
delay: 110 + Math.floor(Math.random() * 160),
});
await humanDelay(280, 800);
await humanDelay(400, 1100);
}
/** Wacht tot password zichtbaar is, met menselijke poll i.p.v. agressief spammen. */

View file

@ -105,7 +105,8 @@ async function launchProfile(userDataDir: string, headless: boolean) {
headless,
viewport: { width: 1280, height: 900 } as const,
args: ["--disable-blink-features=AutomationControlled"],
slowMo: 40 + Math.floor(Math.random() * 50),
// Lichte slowMo; echte CAPTCHA-fix zit in humanType (toetsaanslagen)
slowMo: 15 + Math.floor(Math.random() * 25),
};
for (const channel of ["chrome", "msedge"] as const) {
try {

View file

@ -1,9 +1,8 @@
{
"version": "0.0.0",
"version": "0.1.2",
"filename": "token-tray-setup.exe",
"sizeBytes": 0,
"builtAt": null,
"sizeBytes": 84309324,
"builtAt": "2026-09-23T00:37:43.088Z",
"productName": "Media Cluster Token Tray",
"available": false,
"note": "Run apps/token-tray pack:win + publish:installer on Windows, copy token-tray-setup.exe into the Dokploy agent_install volume (/app/install/agent/), then refresh /agent."
}
"available": true
}