Files
obsidian-vault/personal/tech/inter-site-throughput-taiga-to-mac.md
T

172 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Межсайтовая пропускная способность — TrueNAS (Taiga) ↔ Mac/TV
created: '2026-09-02'
updated: '2026-09-21'
type: tech
namespace: personal
tags: [network, truenas, throughput, rtt, tcp, jellyfin, xray, bottleneck, webos, moonfin, breezyfin, prefetch, single-flow]
related:
- "[[xray-reverse-tunnel-kraken-truenas]]"
- "[[../how-to/truenas-infrastructure]]"
- "[[../family/how-to/kraken-network]]"
---
# Межсайтовая пропускная способность — TrueNAS ↔ Mac/TV
> Контекст: после восстановления стека медиа/права на Taiga (см. `family/documents/vault-sync/2026-09-02-restore-privilege-scope.md`) Jellyfin запустился и файлы читаются, но **прямое воспроизведение с ТВ «грузится кусками»**. Диагностика 2026-09-02 установила: это **НЕ транскодинг и НЕ тариф**, а ограничение сети между двумя физически разнесёнными локальными сетями.
## Cетевой layout (фактический)
| Узел | LAN | Шлюз | Egress IP | Провайдер |
|---|---|---|---|---|
| Mac / TV (дом) | `192.168.1.57` | `192.168.1.1` | динамический | ТТК (92.62.x / 185.20.x) |
| **TrueNAS (Taiga)** | `192.168.2.197` | `192.168.2.2` | `90.189.160.148` (`mallexxx.duckdns.org`) | Ростелеком (194.186.x → 217.107.x) |
**Ключевое:** TrueNAS НЕ в локальной сети Мака/ТВ. Трафик ТВ→Jellyfin идёт целиком по интернету между двумя разными операторами/домохозяйствами.
## Замеры (2026-09-02)
### Задержка / маршрут
- RTT Mac → TrueNAS: **~104 мс**.
- Traceroute: хопы 1–7 моего ISP (ТТК) — **3–6 мс** ✅ чисто. **На хопе 8 (`194.186.168.65`) прыжок до ~54 мс** — межоператорская передача в сеть Ростелекома, где живёт TrueNAS. Хоп 10 (`217.107.108.41`) ~60 мс.
- Этот +50 мс — физическое/пиринговое расстояние между региональными операторами, НЕ петля. Перенастройка маршрута полностью RTT не уберёт.
- Примечание: **дальние сети в целом** (8.8.8.8 ~100 мс) у ТТК тоже идут через ~50 мс переход — деградация на стороне выхода, а не только до TrueNAS.
### Пропускная способность (распутали про «тариф»)
- Mac download с CDN: **~78 Мбит/с** (линия Мака в порядке).
- **TrueNAS сторона**: NIC `enp3s0` 1 Gb/s, до шлюза 0.2–0.8 мс 0% loss. NAS→Cloudflare: **download ~184 Мбит/с, upload ~117 Мбит/с**. → **Лимита тарифа на TrueNAS НЕТ.**
- Mac → TrueNAS (SCP 200MB): **~28 Мбит/с** одним потоком.
- Mac → TrueNAS, **4 параллельных SCP потока: ~28 → ~51 Мбит/с** (агрегат растёт с параллельностью).
## Вывод (важно)
Ограничение — **НЕ по суммарной полосе транзита, а по одному TCP-потоку из-за высокого RTT (~104 мс) + BDP / congestion-window**. Доказательство: 4 потока дали рост ×1.8 (28→51) — при жёстком лимите линии рост не произошёл бы.
**Почему Jellyfin дёргается прямо:** Jellyfin отдаёт видео одним последовательным HLS-потоком (один TCP). Один поток душится RTT-штрафом до ~28–50 Мбит, а BluRay-файл в пиках идёт к 20+ Мбит → с 104 мс RTT сегменты не успевают → стоп-кары. Файл The.Jungle.Book.1967.720p.BluRay ≈ 7.1GB/~78мин → средний ~12 Мбит/с, пики выше.
## Факты ИЗ ЛОГОВ Jellyfin (подтверждают: транскодинг не причина в этих тестах)
- Реальный транскод с `libx264` + reduce был только на "Snatch" (тестовые короткие старты каждые ~5 с — клиент переподключался).
- "Один день в Стамбуле"/"Рождественские хроники" — ремукс `-codec:v:0 copy` в HLS (не перекодирование), стоп на ~2-3 сек.
- В моменте (пока ТВ крутит 720p) — ffmpeg-дочерних процессов нет, папка transcodes пуста → **прямой stream/direct, транскодинг не идёт**.
## 🧭 2026-09-21: развилка решена — многопоточный HLS не существует в Jellyfin/webOS
Перепроверено по первоисточникам (см. [[personal/tech/multistream-single-flow-limit]]):
- Jellyfin «multiple parallel connections» — **Planned** 5 лет, кода нет (230 голосов).
- hls.js multi-segment prefetch (#6753) — открыт, не реализован.
- webOS-приложения используют **нативный media pipeline** → подменить логику загрузки нельзя.
- **Несколько xray-туннелей не помогут** — один физический путь, одно congestion window.
- Speedtest 120 Мбит = 8 параллельных сессий. Одна сессия упирается в **~28–45 Мбит** (подтверждено замерами ниже).
**Рабочие пути:** ограничить битрейт в клиенте / Moonfin с буфером / **Lampac на Кра́кене**
(буфер 50–100 МБ + GStreamer транскод) / prefetch-proxy. Полный разбор — в
[[personal/tech/multistream-single-flow-limit]].
## Решение / направление
1. **Правильное лекарство** (не мультипоток ради мультипотока, а либо снижение латентности, либо запас по битрейту под single-flow): лимит транскода ~12–18 Мбит, ЛИБО гнать трафик ТВ→TrueNAS через **xray tunnel** (`vpn.mallexxx.duckdns.org`, смотри `[[xray-reverse-tunnel-kraken-truenas]]`) вместо прямого межоператорского пути.
2. Jellyfin **не умеет** штатно разбивать один плейбек на параллельные TCP. Параллельность (28→51 Мбит) достижима только поднятием файла способом «качалка в N коннектов» + прокси, либо через туннель.
3. Задача замера скорости через **`xray-test-client`** контейнер (teddysun/xray, SOCKS `127.0.0.1:1080`) — НЕ завершена: команда замера была заблокирована юзером; способ/endpoint (стучались на внутренний `192.168.2.197:8096`) предложен неверно.
## Связанный локальный кейс (Kraken, same-LAN)
> Тот же симптом «ТВ Jellyfin Direct Play дёргается» 2026-09-02, но в **локальной сети** (Kraken RPi5, дом) — причина ДРУГАЯ. См. `family/how-to/kraken-network.md`.
> **Как отличать кейсы:** если Jellyfin-хост в одной LAN с ТВ (ping < ~10 мс) → дёрганье Direct Play почти всегда из-за **линка 100 Мбит/с** на сервере, а НЕ полосы/RTT. Проверка: `cat /sys/class/net/<iface>/speed` (это Kракен упал 1G→100M). Если хост в другой сети/операторе (ping ~104 мс, как Taiga) → ограничение по одному TCP-потоку из-за RTT. «99 Mbps» в UI = битрейт 4K remux-файла (обычно ~60–100 Mbps), НЕ скорость сети/линка.
### Endpoint-факты для замера туннеля
- Локальный тестовый xray-клиент на Mac: контейнер **`xray-test-client`** (`127.0.0.1:1080->1080/tcp`), конфиг `/Users/admin/xray-test/config.json`, оставлен на `kraken-user`.
- Per-user egress на `vpn.mallexxx.duckdns.org`: `user1` → direct TrueNAS `90.189.160.148`; `kraken-user` → reverse через Kraken `92.62.70.41`.
- Конфиг клиента лежит на Mac отдельно (не в vault); бэкап direct-клиента: `/Users/admin/xray-test/config.json.bak-user1-direct-20260902-1227`.
---
## 🔴 2026-09-21 — РАЗБОР: почему speedtest 120 Мбит ≠ Jellyfin не тормозит. Что делать
> Контекст: Alex (Бишкек) сообщил, что плейбек Jellyfin на ТВ тормозит даже по проводу, но **speedtest через reverse-туннель показал до 120 Мбит**. Гипотеза Alex: «поднять реальный VPN в 192.168.2.x через VLESS и проверить, может заработает». Ниже — разбор, почему это не поможет, и что реально может.
### ❌ Что опровергнуто этой сессией
**1. «Speedtest доказал, что 120 Мбит физически можно — значит туннель/multi-tunnel даст столько же».**
Speedtest гоняет **8 параллельных TCP-сессий**, каждая со своим congestion window. 8 × ~15 Мбит = 120 Мбит. Это доказывает, что канал **пропускает** 120 Мбит суммарно. Это **НЕ** доказывает, что **одна** сессия получит 120 Мбит. Наши замеры это уже показывали: 1 поток = 28 Мбит, 4 потока = 51 Мбит (×1.8). Скорость TCP ≈ окно / RTT; при RTT 104 мс для 120 Мбит нужно окно ≈ **1.5 МБ «в полёте»**, одна сессия до такого не разгоняется при потерях на межоператорском стыке.
**Правильная модель (не «узкая труба», а «кассы»):** канал пропустит 120, но **только если запрашивать 8 потоками одновременно**. У Jellyfin — один покупатель в одной кассе.
**2. «Поднять несколько xray-туннелей и распараллелить».**
Не сработает: **физический путь один** (ТТК → Ростелеком, хоп 8 = +50 мс). N туннелей по одному пути делят один congestion window → суммарно не больше, чем один, плюс накладные расходы. Это MPTCP/bonding-территория, а он агрегирует **разные** пути. Аналогия Alex «узкое место — линк между провайдерами» — верно; вывод «значит, надо прокинуть больше туннелей» — нет, линк пропускает 120 Мбит, но не одному потоку.
- Честный путь к «несколько путей» — только **второй независимый линк** (мобильный 4G/5G backup-WAN на TrueNAS) + MPTCP/OpenMPTCProuter.
**3. «VLESS/REALITY-туннель уберёт лимит».**
Уже проверено 2026-09-02 (см. раздел «Замеры скорости туннелей» в `[[xray-reverse-tunnel-kraken-truenas]]`): direct через `vpn.mallexxx` = **~37 Мбит**, reverse через Kraken = **~45 Мбит** (нестабилен). Оба — в том же коридоре, что и прямой путь (28 Мбит single-flow). Туннель идёт тем же маршрутом; REALITY/Vision добавляет обёртки и обычно чуть хуже прямого. **Строить «реальный VPN в 192.168.2.x» смысла нет — он уже есть (`vpn.mallexxx`), и он не помог.**
### ✅ Что реально работает — ранжировано
| # | Подход | Механизм | Усилие | Шанс |
|---|---|---|---|---|
| 1 | **Лимит битрейта в клиенте** (10–15 Мбит) | Транскод на TrueNAS; один поток 10 Мбит проходит с запасом ×3 | 2 мин | **Высокий** |
| 2 | **Moonfin / Breezyfin** (webOS-клиенты) | Нативный pipeline + транскод-лимит в UI + лог «кто отказал в Direct Play» | ~30 мин (Homebrew Channel) | Средний (диагностика) |
| 3 | **Prefetch-proxy на стороне клиента** | Прокси тянет файл/HLS **8 параллельными Range-запросами**, отдаёт клиенту из локального кэша → клиент видит «быстрый сервер» | Высокое (писать/настраивать) | Средний |
| 4 | **BBR + HTTP/3 на TrueNAS** | BBR вместо CUBIC держит cwnd на long-haul; Caddy умеет HTTP/3, но webOS-клиент его не использует | 30 мин | +20–50%, не ×4 |
| 5 | **Второй ISP + MPTCP** | Настоящая агрегация разных путей | Очень высокое / деньги | **Ноль** без второго линка |
### 🔑 Ключевое различие для варианта 3 (и почему он единственный «правильный»)
Параллелизм рождается от **независимых HTTP-запросов** (каждый = своё TCP-окно), а НЕ от мультиплексирования транспорта.
- ✅ **Клиент/prefetch-proxy делает 8 Range-запросов** → 8 независимых окон → 120 Мбит возможно.
- ❌ **8 xray-туннелей + mux** → одно логическое окно, порезанное на 8 → head-of-line blocking, выигрыша нет.
Prefetch-proxy **обязан стоять на стороне клиента** (Mac/ТВ в Бишкеке), не на TrueNAS — иначе параллельные запросы всё равно идут через узкий канал по отдельности, выигрыш частичный.
### 🔴 КРИТИЧНО: клиент Alex — LG webOS (`Jellyfin for WebOS 1.2.2`)
Официальный webOS-клиент — **обёртка вокруг веб-интерфейса**, внутри **один HTML5 `<video>` element = один TCP-поток**. Ни настройки числа соединений, ни Range-префетча.
### 📋 Исследование альтернативных webOS-клиентов (2026-09-21)
**Оба проверены по первоисточникам (GitHub/вики).**
| | **Moonfin** | **Breezyfin** |
|---|---|---|
| Проект | `Moonfin-Client/Smart-TV` (общий код Tizen+webOS), 409★, 1153 коммита, 58 форков | `botagas/Breezyfin`, 63★, 6 форков |
| Версия | 2.5.1 | v0.2.1 (21 авг 2026), **beta**, 112 коммитов сверх upstream |
| Сайт | moonfin.io | breezyfin.app |
| webOS | **3.0+ / 2016+** | 5.0+ |
| Движок | Enact/Sandstone + **Starfish** (нативный webOS pipeline) | Enact Sandstone, HTML5 + нативный webOS player |
| **Параллельные потоки** | ❌ **НЕТ** (один HTML5 video element) | ❌ **НЕТ** |
| Транскод-лимит в UI | ✅ **есть** (*Playback & SyncPlay → Video Playback Preferences → Transcoding Limits*: Max Streaming Bitrate / Max Resolution) | не заявлено явно |
| Лог «кто отказал в Direct Play» | ✅ **есть** (*Settings > About > Diagnostics & Logging*; отчёт называет причину отказа) | Есть diagnostics/logs, формулировка не заявлена |
| Fallback-цепочка | Direct Play → native transcode → **hls.js** | Direct Play → Direct Stream → Transcode + explicit consent перед HDR/DV-даунгрейдом |
| Jellyfin backend | минимум **10.9.0**; **Jellyfin 12 совместим** (`ApiKey`) | 12 auth fix: legacy `X-Emby-Authorization`/`X-Emby-Token` за флагом `EnableLegacyAuthorization` (по умолчанию off) |
| Emby | ✅ | ❌ |
| codec-профиль | per-TV профиль, сообщается серверу; на webOS транскод fallback **HEVC→H264**, когда сервер запрещает HEVC; FLAC direct play в MP4/MKV на **webOS 5+** (до 8 каналов) | adaptive; JASSUB Canvas2D для сабтитров (WebGL на webOS ненадёжен) |
| Аудио passthrough | DTS/DTS-HD/TrueHD bitstream; **на webOS — экспериментально**; Force TrueHD/Atmos | не заявлено |
| Сабтитры | PGS client-side, ASS/SSA через **libass**, DVD/DVB burn-in сервером, отдельный стиль для HDR | configurable client/bitmap |
| Live TV/DVR | ✅ (webOS 5+) | ❌ |
| SyncPlay | ✅ | ✅ (native Jellyfin SyncPlay + JellyWatchParty) |
| Установка | **Homebrew Channel** (не истекает) или Dev Manager Desktop / `ares-install` | Homebrew catalog или IPK |
| Лицензия | MPL 2.0 | GPL-3.0-only |
**Ключевой факт по установке:** LG Developer Mode **истекает каждые 50 часов** → sideloaded-приложения удаляются. **Homebrew Channel-путь НЕ истекает** (root-эксплойт, не Dev Mode). Оба клиента есть в основном каталоге Homebrew Channel (`repo.webosbrew.org`). → Установка через Homebrew Channel убирает главный минус sideload.
**Проверка через Homebrew-каталог:** `https://repo.webosbrew.org/apps/com.breezyfin.app/`, `https://repo.webosbrew.org/apps/org.jellyfin.webos/`.
### ⚠️ Честный вывод по клиентам
Moonfin/Breezyfin **НЕ дадут 120 Мбит** — они не распараллеливают поток. Их ценность:
1. **Endpoint-лимит битрейта в UI** — то же лекарство, что ручной лимит, но штатно.
2. **Лог «почему не Direct Play»** — диагностика, которой у официального клиента нет. Сразу различит «сеть душит» vs «кодек/аудио отказали».
3. Нативный pipeline вместо веб-обёртки → меньше оверхеда.
4. Homebrew Channel = без истечения Dev Mode.
**Настоящее распараллеливание остаётся только за prefetch-proxy (вариант 3) — клиенты его не заменяют.**
### Готовые инструменты для prefetch-proxy (найдены 2026-09-21)
- **`aria3`** (PyPI) — multi-threaded streaming proxy с кэшем и умным prefetch.
- **`node-HLS-Proxy`** (warren-bank) — prefetch `.ts`-сегментов, hook-функции для управления префетчем.
- **`jspeedstreamer`** (conorh) — Java-прокси, multiple parallel requests.
- **nginx `proxy_cache` + `slice`** — кэширует byte-ranges, а не файлы целиком (штатный механизм под Range-prefetch).
- **`JellyfinCache`** (ArnyminerZ) — прокси-кэш между клиентом и Jellyfin-сервером. ⚠️ Ставится на стороне **клиента**, не сервера.
### Предложенный план (НЕ начат, ждёт решения Alex)
1. Проверить версию Jellyfin на TrueNAS (нужно ≥10.9.0 для Moonfin). *~2 мин, ничего не меняет.*
2. Поставить **Moonfin** через Homebrew Channel. *~30 мин.*
3. Включить Diagnostics & Logging, проиграть проблемный файл.
4. Прочитать лог: кто отказал в Direct Play и почему.
5. По результату: сеть → лимит битрейта или prefetch-proxy; кодек → подбор профиля.
**Статус: план предложен, Alex решения не дал. Ничего не менялось — ни на TrueNAS, ни на ТВ, ни в туннелях.**