stremio/docs/f1tv-events-design.md
Jos Vooges | STH 8685870358 Add F1TV Scripts integration with multi-account sync and Events merge.
Tabbed Scripts UI keeps Odido and F1TV separate; F1TV syncs calendar sessions into Events and exposes hub play APIs for upcoming Android TV work.
2026-09-22 03:43:56 +02:00

11 KiB
Raw Blame History

F1TV → Events & F1 Hub — Technisch design

Status: backend MVP gebouwd (Scripts + sync + Events-merge + hub-API). Android TV hub volgt.
Datum: 2026-09-22
Doel: F1 live-sessies én terugkijken in de app, met een dedicated F1-hub onder Events.


1. Antwoord op “kan terugkijken ook?”

Ja. De spelend.har bewijst het al: we speelden 2026 Grand Prix van Nederland als VIDEO/REPLAY af via:

GET /3.0/R/{locale}/WEB_HLS/ALL/CONTENT/PLAY?contentId={id}&player=player_tm
→ HLS URL op ott-video-fer-cf.formula1.com
→ fMP4/CMAF-segmenten (de .mp4’s die je zag)

In die capture: geen Widevine / geen EXT-X-KEY — clear HLS. Playback voor Events is daardoor eenvoudiger dan Odido (geen CDM voor dit pad).

Conclusie:

Content Discovery Play In scope?
Aankomende sessies (LIVE_EVENT / Pre-Live) Meeting-PAGE + start/stop Later via zelfde PLAY Ja — Events + hub
Live sessie (state: Live) Zelfde PLAY (HLS; live mogelijk DASH+DRM) Ja — MVP live; DRM-pad valideren tijdens raceweekend
Terugkijken (REPLAY) Meeting-PAGE / VIDEO-detail Zelfde PLAY (bewezen) Ja — F1-hub, niet in de algemene Events-agenda

Terugkijken hoort niet in de gewone Events-lijst (die filtert ended weg en is “nu/straks”). Het hoort wél in de F1-hub (agenda + archief).


2. Context in huidige architectuur

Wat Events nu is

  • Bron: externe FAAB JSON (liveEventsUrl)
  • API: GET /client/events, /:id, /:id/play
  • Play: pre-resolved streamUrl + ClearKey keys; alleen phase === "live"
  • Clients (iOS / Android TV): sport-chips → shelves → detail → player
  • F1 valt nu alleen onder sport-bucket racing als FAAB het levert — geen F1TV-provider

Wat Odido is (niet het Events-model)

  • 24/7 zenders, LiveChannel, sync worker, Widevine→ClearKey
  • Herbruikbaar: IntegrationSetting, encrypted secrets, admin Scripts-UI, CDM-helper als live DRM nodig blijkt

Wat F1TV moet worden

Een first-party event-provider (niet alleen feed-merge):

  1. Auth + tokens
  2. Periodieke discovery (kalender → meetings → sessies)
  3. On-demand play resolve bij /:id/play
  4. Client: F1-hub UI + bestaande player

3. Doelen & non-goals

Doelen (MVP+)

  1. Provider f1tv in Events-pipeline (admin/viewer toggles)
  2. Upcoming + live F1-sessies in Events (bucket racing) én in F1-hub
  3. F1-hub: agenda weekend + terugkijken (efficient, Events-achtige shelves)
  4. Play via server-side CONTENT/PLAY → HLS naar clients
  5. Multi-account optioneel later (1 Premium account eerst)

Non-goals (later)

  • Volledige F1TV VOD-catalogus (documentaires, shows, F2/F3 alles)
  • Onboard camera picker UI (MVP: default feed / F1 LIVE channel)
  • Imperva-bypass reverse-engineeren in productie zonder browser-sessie
  • Live timing / telemetry overlay

4. F1TV API-model (uit HARs)

Auth-tokens

Token Rol
ascendontoken / subscriptionToken Login-resultaat; header voor entitlement
entitlementtoken Catalogus + PLAY; vernieuwd via USER/ENTITLEMENT of in PLAY-response
sessionid WEB-uuid; meenemen op AGL-calls
Imperva / reese84 Blokkeert server-side password-login

Aanbeveling auth-MVP: admin plakt / vernieuwt tokens (of browser-assisted login later). Password + Imperva is fase 2.

Discovery

PAGE/12343 (seizoen 2026)
  → BUNDLE/MEETING { MeetingKey, pageUri → PAGE/{meetingId} }

PAGE/{meetingId}
  → VIDEO/LIVE_EVENT | VIDEO/REPLAY
  → contentId, title, sessionStartDate/EndDate, state (Pre-Live | Live | …), Series

Play

CONTENT/VIDEO/{contentId}     → metadata + additionalStreams (channelId, playbackUrl)
CONTENT/PLAY?contentId=&channelId=&player=player_tm
  headers: ascendontoken, entitlementtoken, sessionid
  → resultObj.tme.feeds[].url  (HLS)
  → streamType SDR_HD_CMAF

Multi-cam: ~26 feeds (channelId 1033 = F1 LIVE, plus OBC). MVP speelt default feed (F1 LIVE / eerste feed).


5. Backend-architectuur

Nieuwe module

apps/master-api/src/f1tv/

Bestand Verantwoordelijkheid
settings.ts IntegrationSetting id=f1tv: tokens, locale (NLD), device headers, tweaks
client.ts HTTP: PAGE, VIDEO, PLAY, ENTITLEMENT
auth.ts Token load/refresh/expiry; health
sync.ts Kalender → meetings → sessies → interne event-store
play.ts Resolve HLS (+ optioneel DRM later)
map.ts F1TV item → Events-shape + hub-shape

Data-model (intern)

Geen permanente DB-tabel verplicht voor MVP; wel cache + snapshot in IntegrationSetting of korte memory/redis-achtige cache zoals schedule-events.

Interne event-record:

{
  id: `f1tv:${contentId}`,          // stabiel
  contentId: number,
  provider: "f1tv",
  kind: "live_event" | "replay",
  phase: "upcoming" | "live" | "ended",
  name, meetingName, meetingKey, series,
  start, stop,                      // ISO uit sessionStart/End
  state,                            // F1TV raw
  imageLandscape?, imageBackdrop?,
  defaultChannelId?: number,        // 1033
  playable: boolean,                // live óf replay (hub); Events-list alleen live
}

Integratie met schedule-events.ts

Twee lagen:

  1. Merge in /client/events

    • Alleen kind=live_event met phase upcoming|live
    • sportBucket: "racing", provider: "f1tv"
    • playable alleen als phase === "live" (huidige Events-regel)
  2. Nieuwe hub-API (apart van FAAB-lijst)

GET /api/v1/client/f1/home
GET /api/v1/client/f1/meetings
GET /api/v1/client/f1/meetings/:meetingKey
GET /api/v1/client/f1/content/:contentId
GET /api/v1/client/f1/content/:contentId/play

Of één compacte home-payload:

{
  nextMeeting: { ... },
  agenda: Session[],          // komende 7–14 dagen
  live: Session[],
  recentReplays: Session[],   // laatste meeting(s)
  meetings: MeetingSummary[]  // seizoen, compact
}

Play voor hub mag replay én live; bestaande Events-play blijft live-only.

Admin

  • Scripts-pagina sectie F1TV (naast Odido): tokens, locale, sync-now, health, laatste sync-samenvatting
  • Settings IPTV: provider f1tv in disabled-providers / viewer allowlist (zelfde mechanisme)

Sync-strategie

Job Interval Actie
Seizoen-kalender 6–24u PAGE/12343 → meeting map
Actieve + aankomende meetings 5–15 min PAGE/{id} sessies
Live window 1–2 min state refresh rond start−1h … stop+2h
Play on-demand geen pre-fetch van HLS (TTL ~4u in URL)

HLS-URLs niet lang cachen; alleen metadata cachen. Play altijd vers CONTENT/PLAY.


6. DRM / playback-pad

Bewezen (replay HLS)

Client krijgt:

{
  streamUrl: "<hls master>",
  format: "hls",
  drm: null,   // of weglaten
}

iOS/Android moeten drm: null HLS al aankunnen (Events speelt nu ClearKey; check of plain HLS-pad bestaat — zo niet: kleine player-uitbreiding).

Onzeker (live)

Live kan DASH + Widevine zijn. Plan:

  1. MVP: aanname “zelfde HLS als replay”
  2. Raceweekend: live-HAR valideren
  3. Zo DRM: Odido-achtig Widevine→ClearKey of client Widevine (TV) — aparte beslissing

Geen CDM-werk in MVP tenzij live-HAR het afdwingt.


7. Client: F1-hub UX

Entry point

In Events (list):

  • Compacte F1-tile / chip / hero-rail bovenaan of in de chip-rij
    • Label: “F1” of “Formule 1”
    • Sub: “Agenda & terugkijken”
    • Tap → F1HubScreen

Niet alleen “racing-shelf”: racing kan MotoGP/etc. blijven; F1-hub is dedicated.

Navigatie

EventsScreen
  └─ F1HubScreen
       ├─ MeetingDetail (weekend)
       │    ├─ Session cards (upcoming / live / replay)
       │    └─ Play → bestaande PlayerScreen
       └─ ReplayDetail → Play

Android: f1_hub / f1_meeting/{key} / f1_play/{contentId} in McNav.
iOS: NavigationStack path of sheet binnen Events-stack.

Hub-layout (Events-DNA, F1-skin)

Spiegel EventsLook, maar F1-palette:

  • Rood accent (#E10600 F1-achtig), diep zwart, wit typografie
  • Geen dashboard-rommel: weinig chips, lange horizontale rails

Eerste viewport (efficient):

  1. Header “F1” + LIVE-pill als iets live is
  2. Nu / Volgende — 1 grote featured card (live of next session)
  3. Dit weekend — horizontale rail sessies (FP/Quali/Race)
  4. Terugkijken — rail laatste races (compacte kaarten)
  5. Kalender — verticale of horizontale meeting-rail (vlag/circuit-naam)

Focus-TV: D-pad FocusRestore zoals Events (filter → first rail).

Wat wél / niet in algemene Events

Events-tab F1-hub
Live F1-sessie Ja (racing, playable) Ja (featured)
Upcoming F1 Ja (upcoming phase) Ja (agenda)
Replay Nee Ja
Multi-cam Nee (MVP) Later

Zo blijft Events schoon; hub is de rijke F1-ervaring.


8. Implementatiefases

Fase 0 — Design locked (nu)

Dit document + akkoord scope hub.

Fase 1 — Backend skeleton

  • IntegrationSetting f1tv + Scripts UI (tokens handmatig)
  • Client: PAGE calendar + meeting parse + sync snapshot
  • Unit/probe script met tokens uit HAR (geen Imperva-login nog)

Fase 2 — Play path

  • play.ts → CONTENT/PLAY → HLS
  • Wire GET .../f1/.../play én Events /:id/play voor f1tv:* ids
  • Client player: plain HLS zonder ClearKey

Fase 3 — Events merge

  • Inject upcoming/live in /client/events
  • Provider toggle admin/viewer
  • Smoke: F1 verschijnt in racing-shelf

Fase 4 — F1 Hub UI

  • iOS + Android TV hub screens
  • Entry tile in Events
  • Agenda + terugkijken rails
  • Meeting detail

Fase 5 — Hardening

  • Token refresh flow / expiry health
  • Live-weekend validatie (DRM?)
  • Optioneel: multi-cam picker
  • Optioneel: Imperva-assisted login

9. Risico’s & open punten

Risico Mitigatie
Imperva blokkeert password-login vanaf server Tokens handmatig / browser-assisted; geen fake login in MVP
Live ≠ clear HLS Live-HAR vóór productie-claim; CDM-fallback klaarzetten
Token TTL / concurrent streams Health + rate-limit play; 1 account eerst
FAAB + F1TV dubbele F1-events Dedup op naam/tijd of disable FAAB F1 als f1tv aan staat
HLS auth cookies/headers op CDN PLAY-URL bevat signed pa_ path — test of clients zonder extra headers kunnen (HAR suggereert ja)

10. Success criteria

  1. Upcoming Azerbaijan-sessies zichtbaar in Events (upcoming) en F1-hub
  2. Tijdens live: playable in Events + hub
  3. Replay uit hub speelt beeld (zelfde pad als spelend.har)
  4. Viewer zonder f1tv in allowlist ziet geen F1TV-items
  5. Geen regressie Odido / bestaande Events-providers

11. Samenvatting

  • Terugkijken: ja, zelfde F1TV PLAY-pad — thuis in de F1-hub, niet in de standaard Events-lijst.
  • Live/upcoming: F1TV sync → Events (racing) + hub.
  • UI: F1-knoop onder Events → dedicated hub (agenda + replays), Events-layout-principes, F1-skin.
  • Auth: tokens eerst; Imperva-login later.
  • DRM: replay clear HLS; live valideren tijdens raceweekend.

Volgende stap na akkoord: Fase 1 (backend skeleton + token Settings), of eerst alleen hub wireframes als je de UI-richting wilt vastzetten vóór API-werk.