diff --git a/Dockerfile.laya b/Dockerfile.laya new file mode 100644 index 0000000..d1e380b --- /dev/null +++ b/Dockerfile.laya @@ -0,0 +1,23 @@ +FROM python:3.12-slim + +ARG TORCH_VERSION=2.14.1 + +# Install the CPU wheel explicitly before Laya so pip does not select the much +# larger CUDA build. Model weights remain runtime-only in the mounted cache. +RUN python -m pip install --no-cache-dir \ + "torch==${TORCH_VERSION}" \ + --index-url https://download.pytorch.org/whl/cpu \ + && python -m pip install --no-cache-dir "laya[serve]>=0.3.22,<0.4" \ + && python -m pip check \ + && python -c "import torch; assert torch.version.cuda is None, torch.version.cuda" + +ENV HF_HOME=/models \ + LAYA_HOST=0.0.0.0 \ + LAYA_PORT=8000 \ + LAYA_PRELOAD=0 \ + LAYA_DEVICE=cpu + +VOLUME ["/models"] +EXPOSE 8000 + +CMD ["laya-serve"] diff --git a/docker-compose.yml b/docker-compose.yml index b088f7d..8231126 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,5 +13,20 @@ services: environment: - NODE_ENV=production - PORT=3000 # Internal container port + - LAYA_BASE_URL=http://laya:8000 devices: - /dev/dri:/dev/dri # Required for VAAPI/QuickSync/AMF (Linux) + + laya: + profiles: ["laya"] + build: + context: . + dockerfile: Dockerfile.laya + volumes: + - ./data/models/laya:/models + environment: + - HF_HOME=/models + - LAYA_PRELOAD=0 + - LAYA_HOST=0.0.0.0 + - LAYA_PORT=8000 + restart: unless-stopped diff --git a/public/css/main.css b/public/css/main.css index 32f45a1..740d055 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -725,6 +725,71 @@ h4 { white-space: nowrap; } +.channel-matching-settings { + margin-top: var(--space-lg); + padding-top: var(--space-md); + border-top: 1px solid var(--color-border); +} + +.matching-mode-options { + display: grid; + gap: var(--space-sm); + margin: var(--space-md) 0; +} + +.matching-mode-card { + display: flex; + align-items: flex-start; + gap: var(--space-sm); + padding: var(--space-md); + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + cursor: pointer; +} + +.matching-mode-card:has(input:checked) { + border-color: var(--color-accent); + background: var(--color-accent-dim); +} + +.matching-mode-card span, +.matching-mode-card small { + display: block; +} + +.matching-mode-card small { + margin-top: 4px; + color: var(--color-text-muted); +} + +.laya-model-panel { + padding: var(--space-md); + border-radius: var(--radius-sm); + background: var(--color-bg-tertiary); +} + +.laya-model-heading, +.laya-model-actions { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-sm); +} + +.laya-model-actions { + justify-content: flex-start; + margin: var(--space-md) 0; +} + +.laya-language-notice { + margin: var(--space-sm) var(--space-md); + padding: var(--space-sm); + border-radius: var(--radius-sm); + background: var(--color-bg-tertiary); + color: var(--color-text-muted); + font-size: .75rem; +} + .variant-name { overflow: hidden; text-overflow: ellipsis; diff --git a/public/index.html b/public/index.html index c65bf4e..47dfdea 100644 --- a/public/index.html +++ b/public/index.html @@ -10,7 +10,7 @@ nodecast-tv | IPTV Player - + Turn off to show all channels in a single list. Stream variants remain grouped by channel. +
+

Channel matching

+

Choose how Nodecast TV identifies matching streams and languages.

+
+ + + +
+
+
+
Local AI model · Laya
Checking status…
+ +
+
+
+ + +
+

The model runs on this server. Channel names and metadata are not sent to an AI service.

+
+
@@ -1137,11 +1167,12 @@ - - + + - - + + + @@ -1149,7 +1180,7 @@ - +