Commit Graph
903 Commits
Author SHA1 Message Date
euzuandGitHub 978b3bb4f0 api-proxy: configurable credential generation for new users (#942)
* api-proxy: configurable credential generation for new users
* fix: HLS test fail
2026-10-27 21:55:55 +01:00
euzuandGitHub ab4f41e517 fix: accept ranged VOD responses mislabeled text/html (#940)
* fix: accept ranged VOD responses mislabeled text/html

Skip the HTML content-type rejection for 206 and Content-Range
responses so valid media from providers with a wrong Content-Type
plays in reverse proxy mode.

* add playback_provider to bind provider profile

Lets mapped provider:// playback URLs resolve on inputs whose url and
aliases are plain http(s), fixing 503 "Provider config not found".
2026-10-27 14:39:12 +01:00
0892c9d9e6 Feature/hls origin telemetry (#939)
* hls: add origin transfer telemetry

Measure existing shared-HLS origin fetches (segment, map, key,
manifest) and expose per-input availability and transfer quality at
GET /api/v1/hls/origin-telemetry and via the MCP tool
get_hls_origin_telemetry. Off by default via
reverse_proxy.hls_origin_telemetry, configurable in the Web UI.

Also split the reverse proxy config page into tabs.

* hls: add origin transfer telemetry

Measure existing shared-HLS origin fetches (segment, map, key,
manifest) and expose per-input availability and transfer quality at
GET /api/v1/hls/origin-telemetry and via the MCP tool
get_hls_origin_telemetry. Off by default via
reverse_proxy.hls_origin_telemetry, configurable in the Web UI.

Also split the reverse proxy config page into tabs.

* hls: add origin transfer telemetry

Measure existing shared-HLS origin fetches (segment, map, key,
manifest) and expose per-input availability and transfer quality at
GET /api/v1/hls/origin-telemetry and via the MCP tool
get_hls_origin_telemetry. Off by default via
reverse_proxy.hls_origin_telemetry, configurable in the Web UI.

Also split the reverse proxy config page into tabs.

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-27 13:27:21 +01:00
euzuandGitHub c0673ccec9 hls: do not require account credentials for token-only provider urls (#938)
The provider:// origin rewrite called get_user_info() before checking
whether a credential rewrite is needed. Token-only M3U accounts have no
username/password, so the media manifest failed with 503 before
2026-10-27 10:16:07 +01:00
euzuandGitHub ed264f0f4d keep distinct item identity and expose posters (#937)
Media-server items shared one UUID in duplicate_filter, so Jellyfin
catalogs collapsed to a single entry. Derive the UUID from the stable
media-server id. Set header.logo for movies, series and episodes so
Xtream and M3U clients show posters.
2026-10-27 09:37:31 +01:00
euzuandGitHub 0cb5e5e7df - Dependency upgrade (#934)
* - Dependency upgrade
- Slotfree HLS manifest fetch (partial)
2026-10-24 16:33:30 +02:00
euzuandGitHub 7c82bf0b5d Feature/mcp (#933)
* Added
 - MCP server with Web UI config, stdio bridge and docs

Fixes
- GET /api/v1/stream-history rejected the `search_field` parameter the Web UI
  sends (400), because axum's Query cannot read repeated keys into a list.
  Add a FormQuery extractor (serde_html_form) and use it there.
- hls tests were flaky: HlsProxyManager::new() put every test manager's
  segment cache into the shared /tmp/tuliprox/cache/hls, and the orphan
  session cleanup of one manager deleted the files of parallel tests
  (surfacing as MissingTimestampAnchor / TerminalUnavailable). Each manager
  now owns a private cache directory that is removed on drop.

* fixed documentation: db dump paths and flag usage in operations-debugging

* Logs is a standalone Web UI view.

* mcp playlist iterator

* mcp playlist iterator

* media server import uses own categories

* mcp playlist iterator

* Playlit Update view layout changed
2026-10-24 09:49:44 +02:00
euzuandGitHub d9597c46ee Fix/media server url (#931)
* media-server scheme or jellyfin_emby_plex

select_provider_stream_url now accepts a media-server:// reference when
the input type is Emby, Jellyfin or Plex. Other input types still reject
it.
2026-10-23 12:57:14 +02:00
knylbyte 46cb2480de fix (chore): clippy 2026-10-23 11:53:23 +02:00
knylbyte b551ecc5ec fix (hls): retry reserved provider admission within manifest budget 2026-10-23 09:27:14 +02:00
knylbyte 1ef097cbd0 fix (hls): preserve live playback across origin binding changes 2026-10-23 00:22:09 +02:00
knylbyte 25335baa86 fix (hls): bound manifest retries and revalidate live playback entries 2026-10-22 18:52:53 +02:00
knylbyte ea206629b6 fix (hls): correct live reserve accounting and terminal cutover 2026-10-22 10:38:06 +02:00
knylbyte 3a451fc955 merge (hls): retain published manifests during live window transitions 2026-10-22 10:37:40 +02:00
knylbyte a9f68431d1 feat (hls): add HLS origin recovery preferences and automatic segment timeouts 2026-10-22 10:28:59 +02:00
knylbyte 4ed2efa6de fix (hls): retain published manifests during live window transitions 2026-10-21 13:35:57 +02:00
knylbyteandGitHub 69cfbab900 fix (hls): recover shared playback and correct live startup windows (#928)
* fix (hls): recover shared HLS retries and stream the first lease segment

* fix (hls): select fast-start live windows from the stripped live edge

Plan each lease's three-segment entry after applying strip to the full
origin window. Share the plan across rendering, required fetches and
publication, then grow activated windows forwards while preserving cached
predecessors.

Retain current-origin mappings during cache eviction and retire obsolete,
unprotected metadata during GC. Add window-selection, lease-boundary and
metadata-lifecycle regression tests and document the live entry behavior.

Validation: 1,238 HLS tests passed (2 ignored); 5 manifest API tests passed;
the independent 100-window metadata probe passed.

* fix (hls): preserve startup fallback and scope metadata cleanup

* fix (hls): wake fast-start fetches from provider fallback

* test (hls): cover unpublished fallback during lease recovery
2026-10-21 00:23:30 +02:00
knylbyte 305c7f6e6f test (hls): cover unpublished fallback during lease recovery 2026-10-20 23:01:36 +02:00
knylbyte 6060a7b789 fix (hls): wake fast-start fetches from provider fallback 2026-10-20 22:23:54 +02:00
knylbyte 57e4babae9 fix (hls): preserve startup fallback and scope metadata cleanup 2026-10-20 21:37:28 +02:00
knylbyte 0bbd037433 fix (hls): select fast-start live windows from the stripped live edge
Plan each lease's three-segment entry after applying strip to the full
origin window. Share the plan across rendering, required fetches and
publication, then grow activated windows forwards while preserving cached
predecessors.

Retain current-origin mappings during cache eviction and retire obsolete,
unprotected metadata during GC. Add window-selection, lease-boundary and
metadata-lifecycle regression tests and document the live entry behavior.

Validation: 1,238 HLS tests passed (2 ignored); 5 manifest API tests passed;
the independent 100-window metadata probe passed.
2026-10-20 20:56:03 +02:00
knylbyte 49ff4e452f fix (hls): recover shared HLS retries and stream the first lease segment 2026-10-20 20:56:03 +02:00
euzuandGitHub bdd5850cd4 addded Emby/Jellyfin catalog import to media-server (#927)
- Emby/Jellyfin client: token/api_key/login auth, paging, Range playback, artwork
- Jellyfin uses only Authorization: MediaBrowser header (Jellyfin 12 compatible)
- AnyMediaServerCatalogClient dispatch, shared helpers reused by Plex
- Update/Refresh for Emby/Jellyfin inputs in the Web UI
- BREAKING: remove unused media_server options (playback, image_policy,
  catalog.refresh_mode/refresh_on_startup/include_paths/include_user_state)
2026-10-20 19:56:10 +02:00
knylbyteandGitHub 5ae547f5e5 FIX: stabilize shared HLS playback, recovery and account handovers (#925)
* fix (hls): preserve playback reserve across cache eviction

keep a stable session media clock and completed segment timings so cache
eviction and origin rollovers cannot reset playback reserve.

update segment fixtures and cover reserve stability after collection.

* fix (hls): prevent playback stalls during origin manifest retries

mark the origin as degraded on the first retryable manifest failure, cap
retry-after delays, and reevaluate reserve independently of client polling.

use a bounded state commit after an expired splice deadline instead of
leaving the lease live when terminal media cannot be published safely.

* fix (hls): serve custom responses after the live splice deadline

publish a finite lease-bound channel_unavailable playlist on the existing
manifest route when a safe live splice is no longer possible.

renew lease and session activity on successful custom-segment requests
and retain concrete preparation failure diagnostics.

* fix(hls): persist origin qualification for short playlists

Share qualification and retry receipts across leases, preserve them while media publication is pending, and allow controlled recovery after expired acceptance episodes. Prefer eligible regular candidates before short fallbacks.

Add startup, revalidation, replay, cookie and endpoint regression coverage, and document short-window behavior.

Validation during implementation: Linux make test (7009 passed, 23 ignored), focused HLS and endpoint suites, format checks, Clippy and Markdown lint. Offline production library and backend checks passed after the import fix.

* fix(hls): reconcile cache write budgets and revision reclamation

Transfer reserved bytes atomically through staging and publication, preserve cleanup ownership across cancellation, and retire unpinned revisions during local and global reclamation.

Version temp registrations during inventory scans, remove production panic calls, and isolate debug diagnostics from admission results.

Validation: 1,162 HLS tests and 7,038 workspace tests passed; fmt-check, lint, test, markdown-lint and isolated production Clippy passed with dev-slim.

* feat (ai): add local codex files

* fix (hls): replace invalid origin accounts in shared HLS sessions

* fix (hls): synchronize origin account handovers across WebUI viewers

* fix (hls): preserve same-account resume work and backpressure

* fix (hls): resume reduced retries without crossing generations
Allow eligible exhausted acceptance episodes to select reduced retry candidates
while preserving generation, candidate, workload and timing guards. Keep
recovery chains bound to their generation, including changes between selection
and commit.

Add regressions for repaired and persistent resource conflicts, generation
isolation and media delivery through the app's local HTTP origin. Keep shared
manifest fixtures under test/fixtures/hls/reduced-retry.
2026-10-19 17:42:50 +02:00
euzuandGitHub fae862b78a Feature/hdhomerun auto channel (#920)
* hdhomnerun auto_channel
2026-10-16 10:42:04 +02:00
euzuandGitHub 4aa4fd30ad fix hls keep cached predecessors in optimistic startup windows (#919)
With startup.mode = optimistic, session.startup stays set for the whole
session lifetime on clear MPEG-TS sources. select_window's startup branch
returned before retain_published_predecessors, so the v3.3.153
three-target-duration retention never ran in that mode. A 3-segment
origin window was served unchanged (e.g. 17.96 s with target 7), both on
retained-session return entries and during steady playback.

Apply the retention after the startup branch's MIN_VISIBLE_SEGMENTS check.
The retention rules are unchanged: only contiguous Ready, renderable,
non-provisioning predecessors are added, never before the previously
rendered first segment, and the window is capped at
TARGET_VISIBLE_SEGMENTS.
2026-10-14 20:36:50 +02:00
euzuandGitHub 824828f6c7 fix hls: stale stream rows, panel blanking and re-entry window jumps (#918)
* fix hls: stale stream rows, panel blanking and re-entry window jumps
* fix session: release grace-expired slot once, match rows by token
* rusttls vulnerability fixed
* fix testkit: keep scenario run id across bootstrap retries
2026-10-14 08:51:46 +02:00
euzuandGitHub 69040f022b Feature/maintenance (#916)
* Maintenance mode
* fix(hls): release origin slot before next origin I/O
2026-10-13 22:30:21 +02:00
euzuandGitHub 1f0ded31b6 fix hls expire idle sessions held by startup revisions (#915)
fix hls  expire idle sessions held by startup revisions
fix session reuse shared stream row per device session
2026-10-13 20:59:45 +02:00
euzuandGitHub 0ddc3e21cc feat(hls): add optimistic startup mode (#914) 2026-10-12 22:43:06 +02:00
euzuandGitHub dc6e22a70a fix(hls): skip unexposed 404 live head (#913) 2026-10-12 21:43:31 +02:00
euzuandGitHub b6bab647df feat(watch): group added/removed contexts per watch entry (#912)
* feat(watch): group added/removed contexts per watch entry

- watch entries: regex string or {pattern, on:
[channels|group_added|group_removed]}
- one playlist.watch.changed per refresh with WatchChange list;
playlist.groups.changed aliased
- Telegram/ntfy message length limits
- web UI: Mapping and Watch sub pages, new Mapping icon
- ClusterFlags on create_bitset!, bitflags removed

BREAKING CHANGE: playlist.watch.changed templates must use the new
watch.* fields

* feat(watch): group added/removed contexts per watch entry

- watch entries: regex string or {pattern, on:
[channels|group_added|group_removed]}
- one playlist.watch.changed per refresh with WatchChange list;
playlist.groups.changed aliased
- Telegram/ntfy message length limits
- web UI: Mapping and Watch sub pages, new Mapping icon
- ClusterFlags on create_bitset!, bitflags removed

BREAKING CHANGE: playlist.watch.changed templates must use the new
watch.* fields
2026-10-12 21:05:55 +02:00
euzuandGitHub 0d53b22479 fix hls: start rebased retained sessions on the new origin window (#911)
* fix hls: start rebased retained sessions on the new origin window

* fix hls: only drop rebase head when unused and tail is not continued
2026-10-12 16:35:17 +02:00
euzuandGitHub d1c4056965 fix hls: require fresh origin window for new playback on retained ses… (#910)
* fix hls: require fresh origin window for new playback on retained sessions, count known-length revision bodies as completed

- New playback leases joining a retained shared session no longer start
on
  a stale committed window. If the origin window was last confirmed more
  than two target durations ago, admission requires a fresh commit
  (StaleEntryWindow) using the strict pinned host and no recovery burst.
  This prevents the forward jump after fast-start entry.
- RevisionResponseStream tracks bytes sent. A known-length body that is
  dropped after its final byte is now recorded as completed and marks
  segment completion instead of logging outcome=dropped.
- Add an end-to-end re-entry regression test covering progressive,
  first_ready and conservative, plus unit tests for the commit
  requirement and revision completion.
2026-10-12 09:53:04 +02:00
euzuandGitHub a3124a37f5 fix epg: adopt guide channel ID casing on matched live streams, fix frontend: hide column rail on empty tables (#908)
* - fix epg: adopt guide channel ID casing on matched live streams
Synchronize the stream's `epg_channel_id` to the exact casing of the
matched XMLTV guide channel. This fixes exact-key B+Tree lookups in short
EPG and client API responses when stream and guide IDs differ in case.

- fix frontend: hide column rail on empty tables

* - fix epg: adopt guide channel ID casing on matched live streams
Synchronize the stream's `epg_channel_id` to the exact casing of the
matched XMLTV guide channel. This fixes exact-key B+Tree lookups in short
EPG and client API responses when stream and guide IDs differ in case.

- fix frontend: hide column rail on empty tables
2026-10-09 23:12:57 +02:00
d35875e3d1 fix hls close revision file at reader deadline (#907)
* fix hls close revision file at reader deadline

Move the progressive revision reader onto its own task and feed the
response stream through a bounded channel. At the deadline the watchdog
aborts the reader, so the file handle and revision pin are released
even if a stalled client never polls the stream again.

Each open revision file now holds its own pin, so GC cannot retire a
revision while a handle is open, including one held by an in-flight
blocking read.

* fix hls close revision file at reader deadline

Move the progressive revision reader onto its own task and feed the
response stream through a bounded channel. At the deadline the watchdog
aborts the reader, so the file handle and revision pin are released
even if a stalled client never polls the stream again.

Each open revision file now holds its own pin, so GC cannot retire a
revision while a handle is open, including one held by an in-flight
blocking read.

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-09 17:41:39 +02:00
euzuandGitHub 62aea2a2fe persist table layouts and unify column metadata (#906)
* **New Features**
  * Customize table columns by showing, hiding, and reordering them, with keyboard or pointer controls.
  * Save layouts per account, restore defaults, and resolve conflicts when preferences change elsewhere. On installations without web authentication, settings are shared.
  * CSV tables now support saved layouts for recognized table structures.
* **Bug Fixes**
  * Improved pagination bounds and page-size validation.
  * Settings requests now return clearer errors for oversized or unreadable request bodies, and recheck access after waiting for settings to become available.
* **Documentation**
  * Added guidance for table customization and the settings API.
2026-10-08 13:28:41 +02:00
75dab00847 fix(frontend): clean up websocket callbacks and reconnect timers on s… (#904)
* fix(frontend): clean up websocket callbacks and reconnect timers on session expiry

* fix(frontend): clean up websocket callbacks and reconnect timers on session expiry

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-07 18:41:13 +02:00
euzuandGitHub 91433fe37f Fix/dvr recording (#903)
* fix(dvr): correct source resolution, HLS headers and proxy routing

* fix(dvr): support concurrent live recordings within provider capacity
2026-10-07 15:41:19 +02:00
euzuandGitHub 8b4d27b79f fix(m3u): use alias token for Flussonic catch-up archives (#902)
* fix(m3u): use alias token for Flussonic catch-up archives

Catch-up archive URLs are built from the main account's live URL. On an
alias allocation the M3U URL index only knows live URLs, so the lookup
missed and the archive manifest was fetched with the main stream token.
DVR segments inherited it, and the provider attributed the playback to
the main account.

On an index miss for a Flussonic archive file, resolve the live file in
the same directory through the alias index (one lookup pass for all
candidates) and keep the requested archive file name with the alias
query.

Query-based catch-up templates (append mode) are not covered.

* fix(dvr): retry ffmpeg spawn while executable is busy

Spawning a just-written executable can fail with ETXTBSY when a
concurrently forked process still holds an inherited write descriptor
before its exec. This made run_recording_preempts_fake_ffmpeg_and_
preserves_window_semantics flaky on CI.

Retry the spawn up to five times with a short backoff on
ExecutableFileBusy; other errors fail immediately as before.

* fix(hls): resolve single-variant archive master in shared cache

Archive URLs that return a master playlist with one #EXT-X-STREA
child failed with segment_uri_without_extinf. The variant's media
playlist is now fetched and fed to the cache timeline.

- skip masters with several variants or separate #EXT-X-MEDIA tr
- send entry credentials only to the entry origin
- send master cookies only to the master origin
- merge master and variant session cookies by name
- keep the recovery binding on the entry URL
2026-10-06 19:28:11 +02:00
euzuandGitHub d27570bc79 Refactored EPG View (#901)
* **New Features**
  * Added an EPG group view with channel counts, programme details, and channel search.
  * Added timeline zooming and panning, recording controls for eligible upcoming programmes, and a resizable side panel with keyboard and pointer controls.
* **Improvements**
  * EPG group and grid results support JSON or CBOR responses and show up to 1,000 channels per group.
  * Channel filters support case-insensitive text and regular expressions; invalid patterns are rejected with an error.
2026-10-06 07:55:19 +02:00
euzuandGitHub 91f6c57159 Fix/merge live and vod recording (#876)
feat(dvr)!: unify live and VOD/series recording into one recoverable DVR

Merge fix/merge_live_and_vod_recording into develop.

- One recording queue for scheduled live captures and VOD/series transfers,
  with a shared transition graph, provider-slot scheduling, resumable HTTP
  transfers (strong ETag / Last-Modified validation) and ffmpeg live capture.
- Crash-recoverable persistence: B+Tree repository with a journal-first
  recovery history; one file can be shared by several library entries.
- Admission checks quota and disk on request, at transfer start (real size)
  and before an entry attaches to a finished file; idempotent requests.
- REST is command-only; state reaches clients via owner-filtered WebSocket
  snapshots.
- Deleting a recording removes the file once no entry holds it; removing an
  entry keeps a finished file and cleans up orphaned partials.
- User ids derive from the configured username (web:/api:); the identity
  registry is gone.
- Spanish locale added; ru/ar completed; locale parity test.

BREAKING CHANGE: `video.download` is now `video.recording` (nested
`recording` keys move up, `download_priority`/`recording_priority` become
`priority`); old configs fail to load with a migration hint.
BREAKING CHANGE: `/api/v1/file/download*` and `/file/record` are removed in
favour of `/api/v1/recording/*`.
BREAKING CHANGE: `download.*` and `recording.write` permissions are replaced
by `recording.read|create|manage|delete`; tokens from before the change must
re-authenticate.
BREAKING CHANGE: the old recording queue does not migrate; existing
`identity_registry.json` is ignored.
2026-10-04 16:02:55 +02:00
euzuandGitHub 3b656f56b5 fix(hls): return upstream status for HLS resources (#896)
* fix(hls): return upstream status for HLS resources

- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option

* fix(hls): return upstream status for HLS resources

- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option

* fix(hls): return upstream status for HLS resources

- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option
2026-10-03 18:07:59 +02:00
a4feb08c48 fix(hls): keep provider account across client IP changes (#895)
* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-02 20:16:20 +02:00
b8486cffc7 fix(hls): keep provider affinity after reconnect lease expiry (#894)
* fix(hls): keep provider affinity after reconnect lease expiry

- Remember the provider that last delivered media for reconnect-capable
  playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
  preference holds no slot, never forces grace and falls back to the
  lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
  terminate; stale cleanups are rejected by binding tag, request ID and
  session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
  max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
  m3u-hls-provider-affinity-after-lease-expiry scenario.

* fix(hls): keep provider affinity after reconnect lease expiry

- Remember the provider that last delivered media for reconnect-capable
  playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
  preference holds no slot, never forces grace and falls back to the
  lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
  terminate; stale cleanups are rejected by binding tag, request ID and
  session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
  max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
  m3u-hls-provider-affinity-after-lease-expiry scenario.

* fix(hls): keep provider affinity after reconnect lease expiry

- Remember the provider that last delivered media for reconnect-capable
  playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
  preference holds no slot, never forces grace and falls back to the
  lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
  terminate; stale cleanups are rejected by binding tag, request ID and
  session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
  max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
  m3u-hls-provider-affinity-after-lease-expiry scenario.

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-01 18:55:22 +02:00
1960861ee7 fix(provider): exclude and persist banned/expired accounts (#893)
- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked

Co-authored-by: euzu <euzu@proton.me>
2026-10-01 14:46:19 +02:00
euzuandGitHub 0bd087d288 fix(provider): exclude and persist banned/expired accounts (#891)
* fix(provider): exclude and persist banned/expired accounts

- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked

* fix(provider): exclude and persist banned/expired accounts

- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked
2026-10-01 14:24:02 +02:00
euzuandGitHub d280a5484f fix(hls): reuse stable provider lease owners across playback retries (#890)
* fix(hls): reuse stable provider lease owners across playback retries

Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.

Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.

* fix(hls): reuse stable provider lease owners across playback retries
- Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.

- Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.

fix: proxy external Xtream VOD sources in M3U reverse mode
- Resolve stored VOD URLs using the existing input identity.
- Use canonical movie URLs for alias accounts with the original stream ID.
- Keep redirects internal and stop forwarding upstream Referer headers.
- Add regression tests for CDN URLs, aliases, ranges, and URL leakage

* fix(hls): reuse stable provider lease owners across playback retries
- Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.

- Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.

fix: proxy external Xtream VOD sources in M3U reverse mode
- Resolve stored VOD URLs using the existing input identity.
- Use canonical movie URLs for alias accounts with the original stream ID.
- Keep redirects internal and stop forwarding upstream Referer headers.
- Add regression tests for CDN URLs, aliases, ranges, and URL leakage
2026-10-01 08:16:56 +02:00
euzuandGitHub 308fd87288 Fix/flussonic (#889)
* **New Features**
  * Added a setting to limit Flussonic HLS catch-up archive duration. Valid values range from 1 second to 7 days; the default is 4 hours.
  * Bounded archive requests are capped at the configured limit, while shorter valid requests retain their requested duration. Changes apply after a playlist refresh.
  * Added a dashboard credits card with app and TMDB attribution.
* **Bug Fixes**
  * Open filter dialogs now render in the document body when available, helping them display correctly.
* **Documentation**
  * Documented the archive-duration setting and bounded-archive behavior.
2026-10-01 01:21:50 +02:00
euzuandGitHub 89ec7c0e97 Fix/filter input and flussonic fix (#888)
* filter input for user form

* added opt-in bounded Flussonic HLS catch-up

- Add flussonic_hls_catchup input option with native default
- Generate bounded archive sources during M3U import
- Preserve live URLs and query tokens
- Expose native and bounded_archive in the WebUI select

* added opt-in bounded Flussonic HLS catch-up

- Add flussonic_hls_catchup input option with native default
- Generate bounded archive sources during M3U import
- Preserve live URLs and query tokens
- Expose native and bounded_archive in the WebUI select
2026-09-30 17:28:58 +02:00