mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-09-16 04:01:37 +02:00
Prepare release 2.5.1
This commit is contained in:
+29
-30
@@ -1,34 +1,33 @@
|
||||
{
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"changes": [
|
||||
"Completed the large-scale migration of the admin interface to Bootstrap 5",
|
||||
"Rebuilt the admin shell with a modern responsive layout",
|
||||
"Migrated administration tables to clean JSON-based data endpoints",
|
||||
"Migrated streams, VOD, series, episodes, users, devices, servers, EPG, backups, security, logs and other management pages to Bootstrap 5",
|
||||
"Added Bootstrap 5 modal and tabbed form layouts",
|
||||
"Migrated the reseller panel to the Bootstrap 5 interface",
|
||||
"Redesigned admin and reseller login pages with a sci-fi HUD-style interface",
|
||||
"Rebuilt the admin dashboard using Bootstrap 5 statistics cards",
|
||||
"Added a world map visualization of active connections",
|
||||
"Added per-user UI customization persisted in users.ui_prefs",
|
||||
"Added global quick search with structured JSON results",
|
||||
"Reorganized the admin sidebar and navigation",
|
||||
"Added xcToast notifications to replace native browser alerts",
|
||||
"Added module provider contracts for topbar, tables, permissions and quick tools",
|
||||
"Improved module controller and REST integration",
|
||||
"Added configurable xc_fanout source backend",
|
||||
"Added per-repository update channels (Stable/Beta) for the panel, binaries and the xc_fanout daemon",
|
||||
"Added xc_fanout version tracking and integrity probing",
|
||||
"Improved HLS MEDIA-SEQUENCE handling across off-air and live transitions",
|
||||
"Improved stream entry point readability and stability",
|
||||
"Added synthetic input-free test patterns to the stream generator",
|
||||
"Improved VOD analyzer stability under PHP 8",
|
||||
"Added Playwright end-to-end smoke testing for the Bootstrap 5 admin",
|
||||
"Expanded test coverage for migrated admin tables",
|
||||
"Improved GeoIP release synchronization",
|
||||
"Fixed numerous admin UI, PHP 8, null-safety and streaming issues",
|
||||
"Updated contributor, module, FFmpeg and architecture documentation",
|
||||
"Removed obsolete DTS/AC3 testing helpers",
|
||||
"Updated PHPStan and other dependencies"
|
||||
"Added a complete Smart Activation Codes system with pre-generated voucher codes, delayed first-use activation, automatic subscriber line creation, batch management, mass editing, exports, admin/reseller interfaces, an activation portal and a public activation API.",
|
||||
"Added transactional activation-code generation with reseller credit validation, balance deductions and audit logging.",
|
||||
"Added configurable xc_fanout encoder supervision so live stream encoders can be managed and monitored by the streaming daemon instead of a separate PHP watchdog process.",
|
||||
"Added the fanout_supervise setting with a safe disabled default for existing installations and synchronized the setting into the daemon configuration.",
|
||||
"Added supervision reconciliation, health policies, source forcing and daemon-aware process management.",
|
||||
"Added reliable IngestFeeder support for PHP-based producers feeding MPEG-TS data into xc_fanout.",
|
||||
"Fixed short non-blocking socket writes, preventing incomplete TS packets from being silently discarded.",
|
||||
"Added daemon reconnect and re-registration handling with packet-aligned recovery after connection failures or daemon restarts.",
|
||||
"Added bounded ingest buffering with whole-packet shedding to prevent producers from blocking indefinitely.",
|
||||
"Added HLS key and IV propagation for encrypted streams handled through the fanout ingest path.",
|
||||
"Moved live encoder supervision and stream ownership handling further into the xc_fanout architecture.",
|
||||
"Improved on-demand stream startup by using the configured on_demand_wait_time and clearing stale PID and monitor files before restarting a stream.",
|
||||
"Fixed asynchronous file-operation caching and inotify timeout behavior, including stale cache invalidation when files appear.",
|
||||
"Improved stream monitoring with FPS-drop restarts, better backup-source priority handling and failed-probe recovery.",
|
||||
"Fixed catch-up routing, proxy-only checks and adaptive stream variant authentication behavior.",
|
||||
"Corrected VOD and catch-up byte ranges to provide proper seeking and delivery behavior.",
|
||||
"Fixed live HLS playlist sequence handling so playlists are not unnecessarily renumbered when segment durations exceed 10 seconds.",
|
||||
"Improved daemon viewer connection-limit enforcement and viewer kick handling.",
|
||||
"Added producer, CPU and memory information to the admin streams page.",
|
||||
"Improved stream supervision metadata so the panel correctly records which producer and process path owns a stream.",
|
||||
"Added version-at-error-time information to panel logs for more accurate troubleshooting of historical errors.",
|
||||
"Added new streaming documentation covering daemon feeds, kicks, HLS keys, byte ranges, stream supervision and the native remuxer.",
|
||||
"Added a shared synthetic test-stream generator with a TS encoder, keyframe-aligned joins and launcher support.",
|
||||
"Added and expanded fanout supervision and ingest tests.",
|
||||
"Added the database migration required for fanout_supervise and updated related settings handling.",
|
||||
"Fixed duplicate page selectors on mass operation pages.",
|
||||
"Added safeguards preventing update and rollback operations from being executed without root privileges.",
|
||||
"Simplified sourceContext value retrieval and integrated upstream/community changes from pull requests #186 and #187."
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,8 +20,11 @@ git log --pretty=format:"- %s (%h)" "$PREV_TAG"..main > dist/changes.md
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "X.Y.Z",
|
||||
"changes": ["Description of change 1", "Description of change 2"]
|
||||
"version": "X.Y.Z",
|
||||
"changes": [
|
||||
"Description of change 1",
|
||||
"Description of change 2"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -60,15 +63,15 @@ make docs-build # strict build — fails on any broken link/anchor
|
||||
```
|
||||
|
||||
- `make docs-translate` повторно переводятся только те файлы на английском языке, содержимое которых
|
||||
изменен (для каждого файлового кэша), так что при постепенном выпуске это происходит быстро.
|
||||
изменен (для каждого файлового кэша), так что при постепенном выпуске это происходит быстро.
|
||||
- **Review and commit the regenerated `docs/ru`** — он включен в единый
|
||||
снимите фиксацию (шаг 5). Никогда не редактируйте вручную `docs/ru`.
|
||||
- Документация публикуется **на каждый релиз, а не на каждый push**: `pages.yml`
|
||||
запускается при пуше версионного **тега** (шаг 7) и публикует документы этого выпуска
|
||||
как версионный снимок (`X.Y.Z` + псевдоним `latest`) в ветку `gh-pages` через
|
||||
`mike`. Правки, влитые в `main` между релизами, попадают в публикацию на следующем
|
||||
помеченном тегом релизе (тогда же регенерируется `docs/ru`). Селектор версий в шапке
|
||||
Material позволяет читателям переключаться между выпущенными версиями.
|
||||
снимите фиксацию (шаг 5). Никогда не редактируйте вручную `docs/ru`.
|
||||
- Documentation is published **per release, not per push**: `pages.yml` runs when
|
||||
будет запущена версия **метка** (шаг 7), и документы этого выпуска будут опубликованы в виде
|
||||
версионный снимок (`X.Y.Z` + псевдоним `latest`) в ветвь `gh-pages` через
|
||||
`mike`. Правки, объединенные в `main` между выпусками, будут опубликованы на следующем помеченном
|
||||
высвобождение (которое также происходит при регенерации `docs/ru`). Заголовок материала
|
||||
селектор версий позволяет читателям переключаться между выпущенными версиями.
|
||||
|
||||
---
|
||||
|
||||
@@ -131,6 +134,7 @@ cat src/migrations/deleted_files.txt
|
||||
> любой, кто доберется до панели. Этот шаг является мерой усиления безопасности — разблокировка никогда не должна
|
||||
> выходи на улицу в нем.
|
||||
|
||||
|
||||
```text
|
||||
src/Core/Config/AppConfig.php
|
||||
```
|
||||
@@ -171,12 +175,12 @@ make main
|
||||
|
||||
После построения `dist/` должно содержать:
|
||||
|
||||
| Файл | Описание |
|
||||
| --------------------- | ------------------------------------------------------ |
|
||||
| `XC_VM.zip` | ОСНОВНОЙ установщик (установить скрипт + xc_vm.tar.gz) |
|
||||
| `xc_vm.tar.gz` | ОСНОВНОЙ архив (установка и обновление) |
|
||||
| `loadbalancer.tar.gz` | Архив LB (установка и обновление) |
|
||||
| `hashes.md5` | Контрольные суммы MD5 |
|
||||
|Файл|Описание|
|
||||
| --- | --- |
|
||||
| `XC_VM.zip` |ОСНОВНОЙ установщик (установить скрипт + xc_vm.tar.gz)|
|
||||
| `xc_vm.tar.gz` |ОСНОВНОЙ архив (установка и обновление)|
|
||||
| `loadbalancer.tar.gz` |Архив LB (установка и обновление)|
|
||||
| `hashes.md5` |Контрольные суммы MD5|
|
||||
|
||||
> Один и тот же архив используется как для чистой установки, так и для обновлений.
|
||||
> Скрипт обновления (`src/update`) отфильтровывает двоичные/конфигурационные каталоги во время выполнения, используя жестко заданный список `UPDATE_EXCLUDE_DIRS` внутри самого скрипта Python.
|
||||
@@ -213,7 +217,7 @@ bash tools/test-install/test_release.sh
|
||||
- Прикрепите их к фиксатору
|
||||
- Отправьте уведомление в Telegram через `release-notifier.yml`
|
||||
- Опубликуйте документацию по этой версии на страницах GitHub через `pages.yml` (mike):
|
||||
моментальный снимок `X.Y.Z` плюс псевдоним `latest`, который можно выбрать из заголовка документа
|
||||
моментальный снимок `X.Y.Z` плюс псевдоним `latest`, который можно выбрать из заголовка документа
|
||||
|
||||
> ✅ Дождитесь завершения рабочего процесса действий, затем убедитесь, что все файлы доступны для загрузки.
|
||||
|
||||
@@ -226,6 +230,7 @@ bash tools/test-install/test_release.sh
|
||||
> в **та же версия** — LBs считывается база данных MAIN, и может возникнуть перекос в схеме/поведении
|
||||
> потоковый. Не оставляйте LBs без внимания.
|
||||
|
||||
|
||||
- [ ] Убедитесь, что все 4 ресурса присоединены к релизу
|
||||
- [ ] Выполнить `md5sum -c hashes.md5` для загруженных файлов
|
||||
- [ ] Проверьте, отправлено ли уведомление Telegram
|
||||
@@ -236,14 +241,14 @@ bash tools/test-install/test_release.sh
|
||||
## Если что-то пойдет не так
|
||||
|
||||
- **После публикации не удалось выполнить построение действий** — в релизе отсутствуют (или частично) ресурсы. Повторно запустите
|
||||
сбой рабочего процесса на вкладке Действия; если сам тег неверен, удалите выпуск **и**, который
|
||||
пометьте (`git push --delete origin vX.Y.Z`), исправьте и пометьте повторно. Не оставляйте опубликованный релиз с
|
||||
отсутствующие ресурсы — панели извлекают из него `hashes.md5` / архивы.
|
||||
сбой рабочего процесса на вкладке Действия; если сам тег неверен, удалите выпуск **и**, который
|
||||
пометьте (`git push --delete origin vX.Y.Z`), исправьте и пометьте повторно. Не оставляйте опубликованный релиз с
|
||||
отсутствующие ресурсы — панели извлекают из него `hashes.md5` / архивы.
|
||||
- **Выпущенный актив поврежден** — опубликовать выпуск исправления **заплатка** (новый тег) вместо редактирования
|
||||
опубликованный файл; клиенты прикрепляют его к тегу.
|
||||
опубликованный файл; клиенты прикрепляют его к тегу.
|
||||
- **Плохой релиз уже достиг серверов** — операторы могут понизить рейтинг каждого сервера с помощью панели управления
|
||||
(**Серверы → Откат версии**, см. [Механизм обновления → Откат](../administration/update-system.md#rollback-downgrade)); в MAIN сначала автоматически создается резервная копия базы данных. Миграции выполняются
|
||||
доступна только переадресация, поэтому, если исправление небольшое, предпочитайте исправление с переадресацией.
|
||||
(**Серверы → Откат версии**, см. [Механизм обновления → Откат](../administration/update-system.md#rollback-downgrade)); в MAIN сначала автоматически создается резервная копия базы данных. Миграции выполняются
|
||||
доступна только переадресация, поэтому, если исправление небольшое, предпочитайте исправление с переадресацией.
|
||||
|
||||
---
|
||||
|
||||
@@ -253,32 +258,32 @@ bash tools/test-install/test_release.sh
|
||||
|
||||
**Проверка качества** — сначала запустите `make dev-tools`, затем `make dev-clean`, когда закончите:
|
||||
|
||||
| Команда | Цель |
|
||||
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
||||
| `make dev-tools` | Установите инструменты разработки (PHPStan, phpcs) через `composer install` |
|
||||
| `make phpstan` | Статический анализ (также выявляет синтаксические ошибки) |
|
||||
| `make phpstan-baseline` | Восстановите базовую линию PHPStan |
|
||||
| `make cs` | Проверка стиля кода - импорт/гигиена пространства имен (phpcs + Slevomat) |
|
||||
| `make cs-fix` | Примените исправления в стиле кода на месте |
|
||||
| `make gates` | PSR-4 регрессионные шлюзы (для процедурного использования, для LB-архива, только для продукта поставщика) |
|
||||
| `make dev-clean` | Снова удалите инструменты разработки, восстановив только производственную версию `vendor/`. |
|
||||
| `php tools/.bin/phpunit.phar -c tests/phpunit.xml.dist` | Модульные тесты |
|
||||
|Команда|Цель|
|
||||
| --- | --- |
|
||||
| `make dev-tools` |Установите инструменты разработки (PHPStan, phpcs) через `composer install`|
|
||||
| `make phpstan` |Статический анализ (также выявляет синтаксические ошибки)|
|
||||
| `make phpstan-baseline` |Восстановите базовую линию PHPStan|
|
||||
| `make cs` |Проверка стиля кода - импорт/гигиена пространства имен (phpcs + Slevomat)|
|
||||
| `make cs-fix` |Примените исправления в стиле кода на месте|
|
||||
| `make gates` |PSR-4 регрессионные шлюзы (для процедурного использования, для LB-архива, только для продукта поставщика)|
|
||||
| `make dev-clean` |Снова удалите инструменты разработки, восстановив только производственную версию `vendor/`.|
|
||||
| `php tools/.bin/phpunit.phar -c tests/phpunit.xml.dist` |Модульные тесты|
|
||||
|
||||
**Release prep & build:**
|
||||
|
||||
| Команда | Цель |
|
||||
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `make generate_deleted_files` | Регенерировать `src/migrations/deleted_files.txt` |
|
||||
| `make new` | Wipe + recreate `dist/` — запускается ОДИН раз в начале (шаг 1), перед записью `dist/changes.md`; никогда больше перед созданием |
|
||||
| `make lb` | Создайте архив LoadBalancer в виде `dist/` |
|
||||
| `make main` | Соберите ОСНОВНОЙ архив в `dist/` |
|
||||
| `bash tools/test-install/test_release.sh` | Установочный тест Docker для встроенного выпуска |
|
||||
|Команда|Цель|
|
||||
| --- | --- |
|
||||
| `make generate_deleted_files` |Регенерировать `src/migrations/deleted_files.txt`|
|
||||
| `make new` |Wipe + recreate `dist/` — запускается ОДИН раз в начале (шаг 1), перед записью `dist/changes.md`; никогда больше перед созданием|
|
||||
| `make lb` |Создайте архив LoadBalancer в виде `dist/`|
|
||||
| `make main` |Соберите ОСНОВНОЙ архив в `dist/`|
|
||||
| `bash tools/test-install/test_release.sh` |Установочный тест Docker для встроенного выпуска|
|
||||
|
||||
**Документация** (английский источник в `docs/en`; `docs/ru` сгенерирован + зафиксирован):
|
||||
|
||||
| Команда | Цель |
|
||||
| --------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `make docs-venv` | Одноразовый: локальный venv (сборка + переводы) |
|
||||
| `make docs-translate` | Восстановить `docs/ru` из `docs/en` (перед выпуском) |
|
||||
| `make docs-build` | Строгая сборка MkDocs в `./build/site` (что запускает CI) |
|
||||
| `make docs-serve` | Предварительный просмотр документов в режиме реального времени на `http://127.0.0.1:8000` |
|
||||
|Команда|Цель|
|
||||
| --- | --- |
|
||||
| `make docs-venv` |Одноразовый: локальный venv (сборка + переводы)|
|
||||
| `make docs-translate` |Восстановить `docs/ru` из `docs/en` (перед выпуском)|
|
||||
| `make docs-build` |Строгая сборка MkDocs в `./build/site` (что запускает CI)|
|
||||
| `make docs-serve` |Предварительный просмотр документов в режиме реального времени на `http://127.0.0.1:8000`|
|
||||
|
||||
@@ -189,11 +189,11 @@ Alt-Svc: h3-29, h3-T051, h3-Q050 (HTTP/3 hints)
|
||||
|
||||
### VOD (vod.php)
|
||||
|
||||
Тот же процесс аутентификации, что и в live. Считывается из `VOD_PATH` вместо `STREAMS_PATH`.
|
||||
Тот же процесс аутентификации, что и в live. Считывается из `VOD_PATH` вместо `STREAMS_PATH`. Диапазоны байтов (поиск) разрешаются с помощью `Streaming\Delivery\HttpRange` (одиночные диапазоны RFC 7233, включая диапазоны суффиксов). Видеофильм с прямым подключением передается с помощью cURL, запрашивая у источника точно запрошенный диапазон.
|
||||
|
||||
### Временной сдвиг (timeshift.php)
|
||||
|
||||
Обслуживает архивированные сегменты (timeshift / catch-up) из пути к архиву.
|
||||
Обслуживает архивированные сегменты (timeshift / catch-up) из пути к архиву. Запрос TS передает в потоковом режиме несколько файлов подряд; им сопоставляется диапазон байт (поиск) — файлы перед началом пропускаются, первый вводится с правильным смещением, и доставка прекращается в конце диапазона.
|
||||
|
||||
### Доставка демона — `xc_fanout`
|
||||
|
||||
@@ -203,23 +203,93 @@ PHP-FPM работник, отвечающий за жизнедеятельно
|
||||
|
||||
- **Расходимся веером.** `xc_fanout` (встроенный демон Go) извлекает каждый источник **однажды** и
|
||||
предоставляет его каждому пользователю через сокет unix с помощью встроенного в оперативную память сегментатора HLS.
|
||||
PHP находится вне байтового пути для каждого зрителя: рабочий процесс чтения для каждого зрителя
|
||||
цикл обслуживания и путь `HLSGenerator::generateHLS()` для обслуживания клиентов не являются
|
||||
больше не используется для оперативной доставки (`generateHLS()` сохраняется в классе, но имеет
|
||||
абонентов нет). `AsyncFileOperations::awaitFileExists()` — это **нет** удалено - это
|
||||
по-прежнему используется для ожидания запуска потока и пути в байтах VOD/timeshift (см.
|
||||
Таблица показателей).
|
||||
PHP не соответствует байтовому пути для каждого зрителя: рабочий процесс чтения для каждого зрителя
|
||||
цикл обслуживания и путь к клиенту на диске `generateHLS()` исчезли.
|
||||
`AsyncFileOperations::awaitFileExists()` по-прежнему используется для запуска потока
|
||||
ожидания и путь в байтах VOD/timeshift (см. таблицу производительности).
|
||||
- **Кто кормит демона.** Поскольку демон является единственным путем к клиенту, каждый живой
|
||||
продюсер должен включить его, иначе канал нельзя будет смотреть:
|
||||
поток ffmpeg переходит в свой принимающий сокет (`buildLive()`; обратная петля
|
||||
включая дочерних), создатели супервизора-демона делают то же самое, PHP
|
||||
производители — сегментатор LLOD (`LlodCommand`) и ретранслятор с обратной связью
|
||||
(`LoopbackCommand`) — протолкнуть через `Streaming\Fanout\IngestFeeder`, и
|
||||
поток **отложенный** подается через `DelayCommand`, который перемещает каждый задержанный сегмент
|
||||
по мере того, как он публикует его, в зависимости от продолжительности сегмента (его выходные данные с кодировщика являются
|
||||
отложенный, поэтому тройник для него не используется). `IngestFeeder` буферизует то, что
|
||||
не удалось отправить неблокирующую запись (короткая запись больше не разрывает пакеты),
|
||||
выполняет повторную регистрацию и набор номера после перезапуска демона и содержит ключ HLS.
|
||||
- **Две розетки.** Клиентский сокет (ориентированный на nginx) обслуживает `/live/<id>` и
|
||||
`/hls/...`; управляющий сокет, предназначенный только для PHP, регистрирует источники
|
||||
(`PUT /streams/<id>` / `/ingest/<id>`), отвечает на вопросы о статусе выхода в эфир
|
||||
(`GET /streams/<id>`, `GET /probe/<id>`) и предоставляет доступ к телеметрии.
|
||||
- **Телеметрия / согласование данных.** `fanout_sync` опросы `GET /rates` (для каждого uuid
|
||||
КБИТ/с → `lines_divergence`) и `GET /connections` (согласовывает `lines_live`
|
||||
строк, поскольку PHP не может видеть разъединение в `X-Accel`).
|
||||
КБИТ/с → `lines_divergence`) и сверяет `GET /connections` с данными
|
||||
`lines_live` строк в обоих направлениях: строка, просмотрщик которой покинул демон, называется
|
||||
закрыто (PHP не удается увидеть отключение при `X-Accel`), и демон-просмотрщик, чей
|
||||
пропущенная строка — собранная, с истекшим сроком действия или запрещенная строка — удаляется по истечении 20 секунд
|
||||
(`DELETE /connections/<uuid>`).
|
||||
- **Удары и ограничения по подключению.** Строка TS viewer, обслуживаемая демоном, содержит `pid = 0`:
|
||||
здесь нет рабочего, которого можно было бы убить. `ConnectionLimiter` / `ConnectionTracker::closeConnection()`
|
||||
завершите его с помощью `ConnectionTracker::dropDaemonViewer()` — `FanoutClient::dropConnection()`
|
||||
на этом узле, или сигнал `drop_con` о том, что узел зрителя превращается в
|
||||
тот же вызов. Ограничитель никогда не отключает запрашивающее соединение сам по себе (это
|
||||
идентифицируется по uuid, поскольку каждая строка демона имеет общий pid 0).
|
||||
- **Вне эфира.** Если демон сообщает об отсутствии данных (`has_data=false` / устаревшие), PHP
|
||||
показывает страницу "не в эфире" вместо того, чтобы позволить зрителю зависнуть.
|
||||
- **Сохранено на диске HLS** только для timeshift / миниатюр / `.analyse` /
|
||||
`MonitorCommand` — не для доставки клиенту.
|
||||
дочерние элементы loopback / проверки запуска по требованию — не для доставки клиенту.
|
||||
|
||||
#### Управление потоковой передачей и встроенный ремультиплексор
|
||||
|
||||
При включенном **Контроль разветвленного энкодера** (`fanout_supervise`, миграция 018, по умолчанию включено),
|
||||
прямая трансляция не получает PHP watchdog. `StreamProcess::startMonitor()` строит свои команды и раздает
|
||||
их супервизору демона (`FanoutClient::supervise` → `PUT /monitor/<id>`), который запускает,
|
||||
отслеживает и перезапускает их — отработка отказа, приоритетное резервное копирование, принудительный источник, сбой вывода, потеря звука,
|
||||
включая снижение частоты кадров и перезапуск по расписанию. PHP продолжает создавать каждую команду и выполнять все
|
||||
запись в базу данных; демон выполняет то, что ему передают.
|
||||
|
||||
- **Передача** — `StreamProcess::superviseStream()` сначала запрашивает у демона
|
||||
(`GET /monitors/state`: доступно, `accepting`), создает спецификацию
|
||||
(`StreamProcess::buildSupervisorSpec()`: одна команда для каждого источника, политики и работоспособности, сопоставленных с
|
||||
соблюдены настройки `MonitorCommand`), записывает pid демона как `monitor_pid`, затем передает его
|
||||
over. Without a restart a running encoder is **adopted**, not replaced; `cron:streams` moves
|
||||
PHP-отслеживает потоки таким образом при следующем проходе.
|
||||
- **Команды** — прямая трансляция, доступная только для копирования, запускает собственный ремуксор демона, `xc_fanout remux`,
|
||||
построенный с помощью `StreamProcess::buildNativeLive()` рядом с `buildLive()`: он считывает исходный код изначально
|
||||
(MPEG-TS по протоколу http(s), HLS с сегментами TS, udp/rtp) и записывает то же самое на диск HLS и демон
|
||||
подача в виде строки ffmpeg `-f tee` без ffmpeg. Какие потоки соответствуют требованиям, это
|
||||
`StreamProcess::nativeRefusal()` / `isNativeSource()`; `fanout_source_backend` решает:
|
||||
`auto` = повторный мультиплексор с командой ffmpeg в виде `fallback_cmd` (используется при выходе из режима 3,
|
||||
"не удается обслуживать этот источник"), `native` = только для ремультиплексора, `ffmpeg` = только для ffmpeg. Только панель
|
||||
записывает команду ремультиплексора, когда демон узла объявляет об этом (`features` в
|
||||
`GET /monitors/state`, `FanoutClient::supportsRemux()`) — более старый двоичный файл неправильно разобрал бы его.
|
||||
- **Какой продюсер баллотировался и почему** — переданная команда записывается рядом с записью потока.
|
||||
файлы, подобные пути к самопроизвольному запуску `<id>_.ffmpeg`: `<id>_.fanout` для ремультиплексора,
|
||||
`<id>_.ffmpeg` для ffmpeg (в `auto` - оба). Когда включен собственный сервер и выполняется поток
|
||||
ffmpeg в любом случае, причина `StreamProcess::nativeRefusal()` добавляется к `<id>.errors`
|
||||
(`[panel] ffmpeg runs this stream: transcoding is enabled`), тот же файл, что и у производителя.
|
||||
stderr переходит в. Соответствующий тип `streams_types.type_key` = `live`; `gen_timestamps` и
|
||||
`read_native` намеренно не являются отказами (оба значения по умолчанию равны 1, поэтому они ничего не говорят о
|
||||
канал — смотрите программу запуска демона).
|
||||
- **Reconcile** — the daemon cannot write the database, so `StreamProcess::reconcileSupervised()`
|
||||
копирует его состояние в `streams_servers` (статус, pid, текущий источник, кодеки, разрешение,
|
||||
измеренный битрейт): каждый проход `cron:streams` и каждые 5 секунд от демона `signals`. A
|
||||
контролируемый поток, строка которого пропущена или помечена как остановленная, освобождается. Кодеки и размер изображения
|
||||
записываются в `stream_info` JSON, а также в плоские столбцы — этот JSON - это то, что
|
||||
отображает список потоков, из которого адаптивный мастер-плейлист берет `BANDWIDTH`/`RESOLUTION` и
|
||||
где `stream/auth.php` считывает видеокодек зрителя, и контролируемый поток никогда не запускается
|
||||
ffprobe чтобы заполнить его.
|
||||
- **Остановка** — `StreamProcess::stopStream()` освобождает первый (`DELETE /monitor/<id>`, который убивает
|
||||
продюсер); сначала супервизор перезапускает процесс, убивая продюсера.
|
||||
- **Возврат к PHP** — демон, который отключен или не принимает, и поток указывает, что он не принимает
|
||||
берем (задержка, созданные каналы, `yt-dlp` исходники платформы), запускаем `MonitorCommand`, как и раньше;
|
||||
`MonitorCommand` отключается для потока, который контролирует демон.
|
||||
- **"За этим следят?"** — для контролируемого потока `monitor_pid` - это pid демона, поэтому вызывающие абоненты используют
|
||||
`StreamProcess::isWatched()` (PHP монитор активен или находится под наблюдением), а не
|
||||
`ProcessManager::isMonitorAlive()` один.
|
||||
|
||||
Runbook на стороне демона - включение, проверка, откат кодов завершения работы ремультиплексора — это
|
||||
`docs/en/09-encoder-supervision.md` в репозитории `XC_VM_Fanout`.
|
||||
|
||||
#### Наложение отправленного сообщения
|
||||
|
||||
@@ -349,7 +419,11 @@ IP-блокировка на основе файлов. Файлы блоков
|
||||
|
||||
### 3. Ограничитель подключений (для каждого пользователя)
|
||||
|
||||
Применяется после проверки токена. Ограничивает одновременные потоки для каждого пользователя на основе `max_connections`.
|
||||
Применяется после проверки токена. Ограничивает одновременные потоки для каждого пользователя на основе `max_connections`, закрывая сначала самые старые соединения (более старые соединения самого запрашивающего устройства перед другими). Средства просмотра, обслуживаемые демонами, отключаются с помощью демона — см. [Daemon delivery](#daemon-delivery-xc_fanout).
|
||||
|
||||
### 4. Серверы, работающие только через прокси
|
||||
|
||||
Сервер с параметром `enable_proxy` принимает только запросы, поступающие через один из его прокси-серверов. `auth.php` проверяет одноранговый узел TCP nginx saw — `XC_PEER_ADDR`, значение которого равно `$realip_remote_addr` в расположении потока `nginx.conf`, а не заголовок запроса, которым управляет клиент.
|
||||
|
||||
---
|
||||
|
||||
@@ -357,12 +431,12 @@ IP-блокировка на основе файлов. Файлы блоков
|
||||
|
||||
Клиент HLS обслуживается демоном `xc_fanout` (см. [Доставка демоном](#daemon-delivery-xc_fanout)), поэтому происходит шифрование **сторона демона**:
|
||||
|
||||
1. `StreamProcess` записывает ключ AES-128 потока/IV в `content/streams/<id>_.key` / `_.iv`.
|
||||
2. At ingest registration (`FanoutClient::registerIngest`), when `encrypt_hls` is on, the key/IV are handed to the daemon, which encrypts the HLS segments it serves and emits a matching `#EXT-X-KEY`.
|
||||
3. `HLSGenerator::tokenizeDaemonPlaylist()` переписывает URL-адреса сегментов плейлиста демона в ссылки с авторизацией для каждого сегмента `/hls/<token>`, которые `segment.php` передаются через прокси-сервер демона.
|
||||
1. `StreamProcess` записывает ключ AES-128 потока/IV в `content/streams/<id>_.key` / `_.iv` — перед тем, как он создаст PHP производителя, который регистрируется демоном через несколько мгновений после запуска.
|
||||
2. При регистрации приема (`FanoutClient::registerIngest`), когда включено `encrypt_hls`, ключ/IV передается демону, который шифрует HLS сегмента, которые он обслуживает. Каждый производитель передает их — ffmpeg потоков (включая дочерние циклы), контролируемые потоки и PHP производителей через `IngestFeeder::forStream()` — потому что плейлист всегда объявляет ключ: демон, запущенный без него, подавал простые сегменты, которые ни один игрок не смог бы расшифровать.
|
||||
3. `HLSGenerator::tokenizeDaemonPlaylist()` переписывает URL-адреса сегментов плейлиста демона в ссылки с авторизацией для каждого сегмента `/hls/<token>`, которые `segment.php` проксируются от демона, и добавляет строку `#EXT-X-KEY`.
|
||||
4. Ключ AES доставляется игрокам с помощью `key.php` (`src/Public/stream/key.php`) с использованием того же механизма токенов.
|
||||
|
||||
> Устаревший `HLSGenerator::generateHLS()` (который создал и зашифровал плейлист на диске HLS для использования PHP) сохраняется в классе, но становится **больше не находится на пути к клиенту** после отключения демона.
|
||||
Значение `#EXT-X-MEDIA-SEQUENCE` в плейлисте live повторно привязывается к значению `HlsSequence`, поэтому он никогда не возвращается назад при переходе из прямого эфира в прямой эфир без изменения нумерации воспроизводимого потока (его состояние сохраняется в виде `tmp/signals/hlsseq_<id>`, поэтому оно сохраняется после перезапуска потока).
|
||||
|
||||
---
|
||||
|
||||
@@ -431,5 +505,7 @@ SIGNALS_PATH = /home/xc_vm/signals/
|
||||
| `src/Streaming/AsyncFileOperations.php` |неблокирующие утилиты для файловой системы|
|
||||
| `src/Streaming/Lifecycle/ShutdownHandler.php` |очистка соединения при выходе|
|
||||
| `src/Domain/Stream/ConnectionTracker.php` |состояние соединения в Redis/MySQL|
|
||||
| `src/Domain/Stream/StreamProcess.php` |формирование команды (`buildLive` / `buildNativeLive`), передача контроля и согласование|
|
||||
| `src/Streaming/Fanout/FanoutClient.php` |API управления демонами (прием, контроль, принудительный источник)|
|
||||
| `src/Core/Init/LegacyInitializer.php` |настройка глобальной переменной для потоковой передачи|
|
||||
| `tools/stream-check/stream_check.py` |проверка целостности очереди + пакет плейлистов + панель мониторинга живого буфера + графический редактор SVG|
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
| `xcvm_core` | `XcvmCoreCommand` |Установите/обновите расширение `xcvm_core` PHP из хранилища двоичных файлов|корень|
|
||||
| `ytdlp` | `YtDlpCommand` |Установите/обновите `yt-dlp` из своей предыдущей версии на GitHub|корень|
|
||||
| `startup` | `StartupCommand` |Инициализация системы: daemons.sh, crontab, кэш|корень|
|
||||
| `monitor` | `MonitorCommand` |Отслеживайте поток по идентификатору (запуск/перезапуск/отслеживание)|xc_vm|
|
||||
| `monitor` | `MonitorCommand` |Отслеживайте поток по идентификатору (start/restart/track). Только для потоков, которые не выполняет супервизор xc_fanout — он заменяет контролируемый поток|xc_vm|
|
||||
| `thumbnail` | `ThumbnailCommand` |Создание рамок миниатюр для потока|xc_vm|
|
||||
| `plex_item` | `PlexItemCommand` |Обработать один элемент Plex (фильм/сериал)|xc_vm|
|
||||
| `watch_item` | `WatchItemCommand` |Обработать один элемент наблюдения (поиск/обновление в базе данных TMDB)|xc_vm|
|
||||
@@ -127,7 +127,7 @@
|
||||
| `cron:plex` | `PlexCronJob` |сплетение|Обрабатывать обновления Plex|
|
||||
| `cron:watch` | `WatchCronJob` |часы|Обрабатывать обновления библиотеки отслеживания|
|
||||
|
||||
> "Необязательные" задания cron регистрируются **нет** условно — регистрируется каждый обнаруженный класс `CronJob`. "Необязательно" означает, что задание не выполняется, если не включена его функция/настройка (например, `cron:epg`, `cron:series`, `cron:update`), или если задание не удалено из сборки LB.
|
||||
> "Необязательные" задания cron регистрируются **нет** условно — регистрируется каждый обнаруженный `CronJob` класс. "Необязательно" означает, что задание не выполняется, если не включена его функция/настройка (например, `cron:epg`, `cron:series`, `cron:update`), или если задание не удалено из сборки LB.
|
||||
|
||||
---
|
||||
|
||||
@@ -138,12 +138,12 @@
|
||||
старая сборка, никогда не сходилась бы). `cron:root_signals` (root, каждую минуту) сохраняет
|
||||
они становятся текущими путем опроса их идемпотентных команд обновления для каждого двоичного файла на
|
||||
расписание с ограниченным использованием штампов - каждая загрузка выполняется только при несоответствии версии, проверяется
|
||||
контрольная сумма, запуск-тестирует новый двоичный файл, затем заменяет его атомарно (неработающая загрузка
|
||||
контрольная сумма, запуск-тестирует новый двоичный файл, затем атомарно заменяет его (неработающая загрузка
|
||||
никогда не заменяет рабочий). Выполняется на каждом узле (main **и** LB).
|
||||
|
||||
|Двоичный|Команда|Источник|Проверить|Опрос|
|
||||
| --- | --- | --- | --- | --- |
|
||||
|`xc_fanout` демон| `fanout_binary` |`XC_VM_Fanout` освободить актив| `SHA256SUMS` |~ежечасно|
|
||||
|`xc_fanout` демон| `fanout_binary` |`XC_VM_Fanout` высвободить актив| `SHA256SUMS` |~ежечасно|
|
||||
|`xcvm_core` расширение| `xcvm_core` |`XC_VM_Binaries` дерево репозиториев (`bin/xcvm_core/`)|`SHA256SUMS` + нагрузочный тест|~ежечасно|
|
||||
| `yt-dlp` | `ytdlp` |вышестоящий `yt-dlp/yt-dlp` релиз|`SHA2-256SUMS` + `--version`|ежедневный|
|
||||
|
||||
@@ -321,7 +321,7 @@ su - xc_vm -c '/home/xc_vm/console.php tools bouquets'
|
||||
|
||||
## Обновления / миграции баз данных
|
||||
|
||||
Файловая система обновления базы данных (создание шага `.sql`, таблицы `migrations`, потока выполнения `db:migrate`) теперь доступна на отдельной странице — см. [Обновления / миграции баз данных](database-migrations.md).
|
||||
Файловая система обновления базы данных (создание шага `.sql`, таблицы `migrations`, потока выполнения `db:migrate`) теперь размещена на отдельной странице - см. [Обновления / миграции баз данных](database-migrations.md).
|
||||
|
||||
---
|
||||
|
||||
@@ -333,7 +333,7 @@ su - xc_vm -c '/home/xc_vm/console.php tools bouquets'
|
||||
sudo /home/xc_vm/console.php status
|
||||
```
|
||||
|
||||
Проверяет, запущен ли XC_VM, подключается к базе данных, выполняет ожидающие обновления шаги, исправляет разрешения и проверяет конфигурацию nginx. Требуется после установки или восстановления.
|
||||
Проверяет, запущен ли параметр XC_VM, подключается к базе данных, выполняет ожидающие обновления шаги, исправляет разрешения и проверяет конфигурацию nginx. Требуется после установки или восстановления.
|
||||
|
||||
С аргументом `first-run` пропускает текущую проверку, используемую для начальной настройки:
|
||||
|
||||
@@ -373,7 +373,7 @@ sudo /home/xc_vm/console.php server:diagnose <server_id>
|
||||
sudo /home/xc_vm/console.php server:diagnose
|
||||
```
|
||||
|
||||
Обнаруживает **почему?** прокси—сервер/LB—узел, отображаемый в автономном режиме на панели: проверяет частоту сердечных сокращений, доступность (ICMP/TCP/HTTP `/api`), перекос часов, очередь сигналов и - локально на узле - выполняет ли узел брандмауэр на главном IP-адресе в своем собственном iptables, запущена ли служба `xc_vm`/nginx, запущен ли демон сердцебиения `watchdog` и находится ли `cron:servers` в crontab `xc_vm`. Доступно только для чтения; код выхода `0` = проблем не обнаружено, `2` = указаны вероятные причины. Более подробную информацию смотрите в [Руководстве по диагностике сервера](../administration/server-diagnostics.md).
|
||||
Обнаруживает **почему?** прокси—сервер/LB—узел, отображаемый в автономном режиме на панели: проверяет частоту сердечных сокращений, доступность (ICMP/TCP/HTTP `/api`), смещение тактовых импульсов, очередь сигналов и - локально на узле - выполняет ли узел брандмауэр на главном IP-адресе в своем собственном iptables, запущена ли служба `xc_vm`/nginx, запущен ли демон сердцебиения `watchdog` и находится ли `cron:servers` в crontab `xc_vm`. Доступно только для чтения; код завершения `0` = проблем не обнаружено, `2` = указаны вероятные причины. Подробности см. в [Руководстве по диагностике сервера](../administration/server-diagnostics.md).
|
||||
|
||||
### SSL-сертификат
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ define('DEV_MODE', false); // master development-mode flag
|
||||
| `recaptcha_enable` | `bool` |включите reCAPTCHA v2 при входе в систему|
|
||||
| `verify_host` | `bool` |принудительная проверка списка разрешений хоста|
|
||||
| `save_login_logs` | `bool` |постоянные попытки входа в систему в `login_logs`|
|
||||
| `fanout_supervise` | `bool` |передача прямых трансляций супервизору xc_fanout вместо монитора PHP (по умолчанию включен)|
|
||||
| `fanout_source_backend` |`auto` / `ffmpeg` / `native`|как преобразуются исходные тексты в MPEG-TS; под наблюдением, будут ли потоки, предназначенные только для копирования, запускать собственный ремиксер (`auto`: с резервным копированием ffmpeg)|
|
||||
|
||||
Эти значения загружаются из `CACHE_TMP_PATH/settings` защитниками запросов.
|
||||
|
||||
|
||||
@@ -36,8 +36,14 @@ ProcessManager::isStreamRunning(int $pid, int $streamId): bool
|
||||
```
|
||||
|
||||
- `ffmpeg`: проверяет шаблон вывода для конкретного потока в командной строке
|
||||
- `xc_fanout`: только собственный ремультиплексор (`xc_fanout remux … /<id>_.m3u8`) — демонический процесс
|
||||
сам по себе использует исполняемый файл, но не называет список воспроизведения потока
|
||||
- `php`: считается активным для контекста stream worker
|
||||
|
||||
Для запроса "есть ли что-нибудь **наблюдающий** в этом потоке" используйте `StreamProcess::isWatched($streamId, $monitorPid)`:
|
||||
`monitor_pid` контролируемого потока принадлежит демону xc_fanout, который `isMonitorAlive()` (an
|
||||
`XC_VM[<id>]` PHP процесс) справедливо отклоняется.
|
||||
|
||||
---
|
||||
|
||||
## Больше проверок и помощников
|
||||
@@ -61,6 +67,28 @@ ProcessManager::isAnyProcessRunning(array $terms): bool
|
||||
|
||||
---
|
||||
|
||||
## Процессор и память для каждого потока
|
||||
|
||||
```php
|
||||
ProcessManager::resourceSample($pid): ?array // ['ticks' => CPU ticks so far, 'rss' => bytes, 'at' => microtime]
|
||||
ProcessManager::cpuPercent(array $now, array $prev): ?float // percent of ONE core between two samples
|
||||
ProcessManager::producerKind($pid): ?string // 'fanout' (xc_fanout remux) | 'ffmpeg' | 'php'
|
||||
```
|
||||
|
||||
Считывается непосредственно из `/proc/PID/stat` (поля 14/15 для CPU, 24 для RSS; размер страницы является производным
|
||||
из собственного значения этого процесса `statm` против `status`, поскольку 64 КБ страниц являются нормальными для arm64). Процессор в `/proc`
|
||||
is cumulative, so a percentage needs **two** samples: `cpuPercent()` returns `null` when the pair
|
||||
ничего не говорит — ни о предыдущих показаниях, ни о двух показаниях за один и тот же момент, ни о счетчике, который сработал.
|
||||
в обратном направлении, потому что производитель перезапустился в том же потоке.
|
||||
|
||||
`cron:streams` производит выборку каждого запущенного потока один раз за проход и сводит результат к этому
|
||||
JSON-файл потока `progress_info` (`cpu`, `mem`, `producer`, плюс `cpu_t` / `cpu_at`, несущие
|
||||
чтение следующего прохода вычитается из). Только узел, на котором запущен поток, может считывать свой собственный `/proc`, поэтому
|
||||
выборка происходит там и перемещается на панель в строке, которую cron уже записывает; администратор
|
||||
список потоков отображает его в виде столбца **Ресурсы** (значок производителя, процент процессора, оперативная память).
|
||||
|
||||
---
|
||||
|
||||
## Завершение процесса
|
||||
|
||||
```php
|
||||
@@ -93,10 +121,10 @@ ProcessManager::acquireCronLock(string $pidFile, int $maxAge = 1800): bool
|
||||
|
||||
## `/proc` Проверить кэш
|
||||
|
||||
`isRunning()` использует короткий TTL-кэш для `/proc` проверок (1 секунда), чтобы уменьшить количество повторных операций ввода-вывода в узких циклах.
|
||||
`isRunning()` использует короткий TTL-кэш для `/proc` проверок (1 секунда), чтобы уменьшить количество повторяющихся операций ввода-вывода в узких циклах.
|
||||
|
||||
> **Ловушка.** Поскольку результат кэшируется в течение ~1 секунды, процесс, который завершается (или запускается) внутри этого
|
||||
> окно по—прежнему считывается в своем предыдущем состоянии - жесткий цикл может воздействовать на устаревшее "запущенное"/ "мертвое" окно.
|
||||
> "окно" по—прежнему считывается в своем предыдущем состоянии - жесткий цикл может воздействовать на устаревшее "запущенное"/ "мертвое" окно.
|
||||
> ответ. Вызовите `ProcessManager::clearCache()`, чтобы удалить кэш, когда вам понадобится новое чтение
|
||||
> (например, сразу после удаления pid и перед его повторной проверкой).
|
||||
|
||||
@@ -122,7 +150,7 @@ ProcessManager::acquireCronLock(string $pidFile, int $maxAge = 1800): bool
|
||||
|
||||
- `Thread` (`src/Core/Process/Thread.php`) — тонкая оболочка `proc_open` вокруг одного
|
||||
фоновая команда (запустите ее, опросите/дождитесь ее, прочитайте ее выходные данные).
|
||||
- `Multithread` (`src/Core/Process/Multithread.php`) — выполняет несколько команд оболочки.
|
||||
- `Multithread` (`src/Core/Process/Multithread.php`) — запускает несколько команд оболочки.
|
||||
одновременно и собирает выходные данные каждого из них; используйте его для разветвленной работы (например, для проверки многих
|
||||
исходники сразу), а не ручной цикл `proc_open`.
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ define('DEV_MODE', false);
|
||||
|
||||
// ── Version & Git Configuration ────────────────────────────────
|
||||
|
||||
define('XC_VM_VERSION', '2.5.0');
|
||||
define('XC_VM_VERSION', '2.5.1');
|
||||
|
||||
define('GIT_OWNER', 'Vateron-Media');
|
||||
define('GIT_REPO_MAIN', 'XC_VM');
|
||||
|
||||
Reference in New Issue
Block a user