Add a browser-native casting service with Live and Watch player controls for Remote Playback and AirPlay-compatible devices.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update the Docker build/push helper to build and push both application and Laya images, and document the configurable image targets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Use configurable published images in docker-compose and update deployment docs so Compose works without a full checkout or local Dockerfiles.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update deployment guidance for standard and Laya-profile Compose flows, and mark the Laya service as profile-gated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Explain how to start the optional Laya runtime when model download fails because the service is unavailable, while keeping generic failures concise.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Require numeric query tokens to match numeric channel tokens exactly while preserving singular/plural and compact-name tolerance.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bound synchronous live channel enrichment and tolerate minimal projection payloads so analysis and listings do not blank the UI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Filter projected live channels locally in the browser and apply server-side search and language filters before costly enrichment work.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Render active and inactive EPG priority lists, support move controls, and persist complete EPG source ordering from the settings UI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add persistent EPG priority ordering, source reorder validation, and priority-aware EPG matching for live channels.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add language filter controls for projected live channels, preserve backend language views in the browser, and separate built-in EPG sources from custom sources.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add backend language detection, flexible live channel search, iptv-org catalog caching, and protected built-in EPG source registration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Report post-projection Laya language detection as a busy analysis phase and normalize Laya language labels before caching and display.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Track the Laya identity phase separately from catalog projection progress and expose phase-specific counters through the live status API and Settings presentation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ensure Docker images keep their container-built native dependencies, wait for the Laya sidecar healthcheck, expose accurate Laya readiness, and treat empty AI language batches as fallback failures.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Treat successful but empty live projections with existing live input as stale, reject them on the frontend, and keep the previous visible channel state during rebuild failures.
Add DOM coverage for the Settings analysis flow and backend serialization coverage for empty projection state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fix the regression introduced by the weighted Laya signal (#16):
rebuild now merges exact fingerprints in every engine mode after
evaluating hard blockers, compares candidates against all variants
of a group, falls back to deterministic scoring when Laya is
unavailable, and reports transaction errors safely. Non-regression
tests cover the Laya-mode rebuild path; verified against a real
catalog copy (39,341 streams rebuilt successfully).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce a liveGroupingScoring engine that combines existing
membership signals (normalized name, brand, number, metadata tokens,
language, category/source when relevant) with a bounded Laya
contribution: Laya raises or lowers confidence instead of acting as
a final judge, with guard-rails against obvious contradictions.
Sanitize Laya batch identity inputs in layaService and wire the
weighted scoring into the live projection service. Weights are not
exposed in the Nodecast UI. Cover signal combination, bounds and
contradiction guard-rails with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
beIN Sports 1 variants stayed separated after projection because
names with region prefixes (C Car, C Reu, Thai), time-shift suffixes
(2h/4h/8h/12h) and language markers (En, Fr, Thai) produced distinct
fingerprints. Extend normalization in the server projection service
and the frontend grouping fallback to fold these into one logical
channel, with tests on the exact reported names. Clarify the Laya
language detection warning so a language-matching failure is not
mistaken for a grouping failure, and bump script versions for cache
refresh.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a Settings action to manually rerun Live TV stream analysis:
it triggers an admin-guarded projection rebuild endpoint that
groups streams into logical channels (covering channels present
before the projection existed) and reruns language/Laya detection,
with progress presented via liveAnalysisPresentation. Harden the
Laya batch path that failed with 'Local AI language matching
failed' by surfacing the underlying cause and falling back to
standard matching cleanly. Guard admin-only rebuild through a new
authz helper and cover routes, service and presentation with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move variant grouping work out of Live TV rendering into the
catalog pipeline: a liveProjectionService builds the logical channel
projection (schema in liveProjectionSchema) whenever a source is
added, synced or modified (name change, new address), and the
projection is served through a /live route. ChannelList now consumes
the precomputed projection via a liveChannelProjection client
service, recalculating only when the catalog changes. Cover
projection building, incremental recompute and client consumption
with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two fixes: the ChannelList local-AI warning kept showing after the
runtime became available because status changes were not re-evaluated
on refresh; and selecting a language in the player did not switch the
stream variant immediately. Refresh warning visibility from the
latest laya status and apply the chosen variant/language on
selection, with tests for both behaviors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Offer the right actions in Settings when Laya is ready/available
instead of leaving irrelevant ones, and stop showing the ChannelList
local-AI warning once the runtime is actually available. Derive both
from layaStatusPresentation and cover the ready/available action set
with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The model was reported as ready while the AI runtime was actually
unreachable, and the Download action stayed visible afterwards.
Distinguish model-downloaded from runtime-available in
layaStatusPresentation, derive the Download action from the real
combined state, and align Settings and ChannelList rendering on that
single source of truth. Cover the combined status cases with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Track download progress in layaService (bytes/total, phase, error
state) and expose it through the laya status route. Render a progress
bar during model download in Settings via a layaStatusPresentation
service, and display download/status errors inline instead of failing
silently. Cover progress tracking and status presentation with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a languageDetectionMode setting (algo | laya | laya+algo) exposed
in Settings with three engine choices. When Laya is enabled, a laya
service (Dockerfile.laya, optional compose profile, models stored
outside the repo under ./data/models/laya) can be started, with model
download and deletion from the UI via /laya routes to manage disk
space. Add a channelLanguageFusion service combining Laya results
with the existing algorithm, and wire detection mode through
grouping, channel list and player. Cover engine selection, fusion
and laya service behavior with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a liveChannelListMode setting (default 'grouped') with a Settings
toggle to display the Live TV channel list flat, without category
group sections. When enabled, logical channels are listed directly
with their stream variants still grouped as in #9/#10. Cover the
setting default and flat-list behavior with tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>