Пользовательская документация

Планирование и протоколы передачи данных

Программа Perfect Streamer предназначена для передачи потоков формата MPEG-TS через публичную сеть Интернет с потерями пакетов и задержками на базе UDP.

Для каждого MPEG-TS потока (Stream) настраивается сервер перередатчик (Sender) и один или несколько приемников (Receiver), далее связка обозначается Peer.

Настройка передатчика и приемника сводится к вводу списка потоков (Stream) и настройки для каждого Stream списка input и output. Несколько input в списке обеспечивают резервирование источников. Несколько output в списке позволяют передавать потоки сразу по разным получателям.

Для передатчика input - это источники MPEG-TS потоков, output - передача потоков на приемники. Для приемников input - получение потоков от передатчиков. Доступны четыре Peer протокола для передачи потоков между передатчиком и приемником:

  • Протокол Perfect Stream (PS1).

  • SRT.

  • Pro-MPEG / RTP+FEC.

  • RIST.

Протокол PS1

Протокол PS1 работает по принципу Automatic Repeat reQuest (ARQ). Имеет низкую ресурсоемкость и позволяет передавать потоки с высоким битрейтом.

На передатчике - настраивается в output. Для одного стрима доступен только один экземпляр. Требуется прописать в Peer логины для приемников. Задается UDP listen port, должен быть уникальный для каждого стрима.

На приемнике - настраивается в input. Указывается host и port передатчика, также логин и пароль.

Доступно шифрование потоков (Crypto protection), используется AES-128. Для включения шифрования на обеих сторонах ввести Crypt Passphrase - общий ключ.

При работе приемник (клиент) передает передатчику (серверу) свои данные статистики. Это можно посмотреть в разделе Peers, выбрав клиента из списка.

Задержка потока и способность исправлять потери зависит от настроек получателя (клиента):

Round Trip Time - RTT, ms, default 300. Оценочная задерка (ping) в канале. После запуска потока реальный RTT можно увидеть в статистике (PS1 recovery delay).

Client Latency (RTT multiplexor) - множитель к RTT, по умолчанию 10, определяющий задержку потока на буфере отправителя. Т.е. по умолчанию задержка на буфере 3000 мс.

Со стороны отправителя есть настройка задержки (длины буфера) - Latency (ms). Она должна быть больше заданных у клиентов задержек.

Способность протокола компенсировать потери определяется количеством запросов на повторную передачу и зависит от Client Latency (RTT multiplexor). Большие потери приводят к дополнительному сетевому трафику. Для уменьшения задержки следует более тонко настроить эти параметры.

Корректность работы протокола см. статистику клиента. Счетчики PS1 recovery - при Not found увеличить буфер отправителя, Dublicates - увеличить RTT.

Так как инициирование соединения происходит со стороны приемника, то для передатчика требуется аутентификация, приемники прописываются в peer. Обязателен логин и пароль. Возможна авторизация по IP сервера, для этого у пира необходимо указать только IP приёмника.

Протокол SRT

Открытый протокол разработки Haivision. Базируется на протоколе UDT. Имеет широкое распространение и хорошие характеристики компенсации потерь пакетов данных.

Сценарии использования:

  • Peer между Perfect Streamer. На передатчике - настраивается в output, режим listen (по умолчанию). Для одного stream можно задать только один такой output. В этом режиме можно подключить несколько приемников. Для авторизации требуется прописать в Peer логины для приемников. На приемнике - настраивается в input. Указывается host и port передатчика, также логин и пароль. Для передачи логина и пароля в srt streamer использует streamid в формате «login|password»

  • Peer между Perfect Streamer и любыми сторонними srt стримерами. На передатчике можно настроить режим srt client, отключив listen, srt streamid, если надо, вводится в поле login. Для режима listen доступна авторизация по IP адресу - вводится в поле login Peer. На приемнике можно включить режим listen, в поле login задать srt streamid, а также можно задать хост, с которого разрешается прием.

Работа в режиме Listener: получение и передача потока телеканала в с указанием порта приёма.

Порты для listen режима должны быть уникальны.

Доступно шифрование потоков (Crypto protection), используется AES-128. Для включения шифрования на обеих сторонах ввести Crypt Passphrase - общий ключ.

Если на передатчике используется режим listen (по умолчанию), то инициирование соединения происходит со стороны приемника, и для передатчика требуется аутентификация, приемники прописываются в peer. Обязателен логин и пароль.

Опции протокола SRT соответствуют описанию - https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md

Reorder (SRTO_LOSSMAXTTL) - Значение, до которого может увеличиваться допуск на переупорядочивание. Допуск на переупорядочивание — это количество пакетов, которые должны следовать за обнаруженным «пробелом» в порядковых номерах входящих пакетов, чтобы был отправлен отчёт о потере (в надежде, что разрыв вызван переупорядочиванием пакетов, а не потерей). Значение допуска на переупорядочивание начинается с 0 и увеличивается при обнаружении переупорядочивания пакетов. Это происходит, когда получен «запоздалый» пакет с порядковым номером старше последнего полученного, но без флага повторной передачи. При таком обнаружении допуск на переупорядочивание устанавливается равным значению интервала между последним номером и порядковым номером данного пакета, но не более значения, заданного параметром SRTO_LOSSMAXTTL. По умолчанию это значение равно 0, что означает, что данный механизм отключён. https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#SRTO_LOSSMAXTTL

Overhead (SRTO_OHEADBW, %) - Накладные расходы на восстановление полосы пропускания сверх входной скорости (см. SRTO_INPUTBW), в процентах от входной скорости. Действует только если SRTO_MAXBW установлен в значение 0. Отправитель: настраивается пользователем, по умолчанию: 25%.

Рекомендации: Накладные расходы предназначены для обеспечения дополнительной полосы пропускания в случае, если пакет занял часть полосы пропускания, но затем был потерян и должен быть передан повторно. Поэтому эффективная максимальная полоса пропускания должна быть достаточно выше битрейта вашего потока, чтобы оставалось место для повторной передачи, но при этом ограничена, чтобы повторно переданные пакеты не приводили к резкому увеличению использования полосы пропускания при потере больших групп пакетов. Не устанавливайте слишком низкое значение и избегайте 0, если параметр SRTO_INPUTBW установлен в значение 0 (автоматически). В противном случае ваш поток будет быстро прерываться при любом увеличении потери пакетов. https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#SRTO_OHEADBW

Max Band (SRTO_MAXBW, bps) - Эта опция эффективна только при значении SRTO_MAXBW, равном 0 (относительное). Она управляет максимальной пропускной способностью совместно с параметром SRTO_OHEADBW по формуле: MAXBW = INPUTBW * (100 + OHEADBW) / 100. Если эта опция установлена в значение 0 (автоматически), фактическое значение INPUTBW будет оцениваться на основе скорости входного потока (случаев, когда приложение вызывает функцию srt_send*) во время передачи. Минимально допустимое значение оценки ограничено параметром SRTO_MININPUTBW, то есть INPUTBW = MAX(INPUTBW_ESTIMATE; MININPUTBW).

Рекомендации: установите для этого параметра ожидаемый битрейт вашей трансляции и оставьте значение по умолчанию 25% для SRTO_OHEADBW. https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#srto_inputbw

Timeout (SRTO_CONNTIMEO, ms) - Значение таймаута соединения в миллисекундах. Это время, в течение которого подключающийся объект будет пытаться подключиться и ожидать ответа от удалённой конечной точки, прежде чем прекратить соединение с кодом ошибки. https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#SRTO_CONNTIMEO

Протокол Pro-MPEG / RTP+FEC (COP3 / SMPTE 2022-1/2)

Это доставка MPEG-TS поверх RTP с упреждающей коррекцией ошибок (FEC, Forward Error Correction). Один и тот же протокол встречается в литературе и оборудовании под разными именами:

  • Pro-MPEG / Pro-MPEG COP3 — Code of Practice #3 форума Pro-MPEG, описан в стандарте IEEE (https://ieeexplore.ieee.org/document/6738329);

  • RTP + FEC — функциональное название (RTP-поток плюс FEC-каналы);

  • SMPTE 2022-1 — Column FEC (та же схема, опубликованная как стандарт SMPTE);

  • SMPTE 2022-2 — Row + Column FEC (двумерная матрица, реализована в PSS).

Достоинства — низкая задержка. Его недостаток — высокий дополнительный трафик (overhead), и он плохо работает при больших потерях пакетов (более 0.2%).

Этот протокол основан на RTP с добавлением 2-х каналов для FEC (кода коррекции ошибок). Два канала FEC используют порты port+2 и port+4, что надо учитывать при добавлении нескольких потоков на один хост или мультикаст группу.

На отправителе поток RTP пакетов группируется в матрицу с Cols колонок и Rows строк. Пример для cols=8 и row=4 (по умолчанию):

RTP01

RTP02

RTP03

RTP04

RTP05

RTP06

RTP07

RTP08

R1

RTP11

RTP12

RTP13

RTP14

RTP15

RTP16

RTP17

RTP18

R2

RTP21

RTP22

RTP23

RTP24

RTP25

RTP26

RTP27

RTP28

R3

RTP31

RTP32

RTP33

RTP34

RTP35

RTP36

RTP37

RTP38

R4

C1

C2

C3

C4

C5

C6

C7

C8

Пакеты Rx и Cx формируют данные для FEC по строкам и колонкам. Чем меньше размер матрицы, тем лучше способность исправлять потери, но больше дополнительный трафик. В данном примере на 32 RTP пакета потока приходится 12 FEC пакетов.

Доступно шифрование потоков (Crypto protection), используется AES-128, но это не включено в стандарт, поэтому не гарантируется совместимость со сторонним ПО или оборудованием.

Имеются нестандартные расширения протокола:

Multiplexing — мультиплексирование RTP каналов через один UDP порт. Может упростить настройку сети. Header XOR — обфускация RTP заголовка. Усложнит определение типа трафика в сети.

Протокол RIST

Новый открытый протокол. Базируется на протоколе RTP/RTCP. Работает по принципу Automatic Repeat reQuest (ARQ) без ACK, только NACK, что обеспечивает высокую эффективность.

Использует unicast и multicast.

Реализованы профили Simple и Main. Simple использует 2 udp порта подряд, задаваемый порт должен быть четным. Main использует только один RTP порт с мультиплексированием данных.

На передатчике - настраивается в output. Для unicast настраивается адрес и порт приемника. Для multicast требуется задать сетевой интерфейс, через который будет передача данных. Также для multicast можно задать авторизацию приемников через IP адрес если прописать логины в Peer.

На приемнике - настраивается в input. Для unicast настраивается порт приемника (listen) и обязательно сетевой интерфейс. Для multicast задается только мультикаст группа и порт.

RIST поддерживает несколько отдельных пиров (адресов). Можно задать вес (более 1), тогда включится режим балансировки нагрузки по пирам в зависимости от веса.

Если передатчик использует multicast, то приемников может быть много. В этом случае возможна аутентификация приемников по IP адресу. Для этого в настройках передатчика включите аутентификацию (по умолчанию отключена) и в список peer добавьте клиента, в поле логина пропишите IP адрес.

Другие протоколы

Кроме peer протоколов для получения и передачи потоков доступны другие:

Protocol

Input

Output

UDP

Yes

Yes

RTP

Yes

Yes

TCP

Yes

No

HLS

Yes

Yes

UDP (Unicast или Multicast) - прием и передача MPEG-TS в UDP пакете, до 7-ми TS пакетов на один UDP пакет.

RTP (Unicast или Multicast) - стандартный RFC-based протокол. Поддерживается восстановление reordered пакетов.

TCP - прием MPEG-TS в TCP соединении, режим TCP клиент.

HLS - прием и передача MPEG-TS over http или стандартный HLS протокол от Apple. На приёме для адаптивного плейлиста выбирается поток с большим битрейтом.

Работа потоков с файлами и устройствами

Для input и output доступен протокол file/device для работы с файлами и устройствами.

output file/device - запись в файл или вывод в устройство. Запись в файл может потребоваться для записи в ts-файл и последующей диагностики другими анализаторами. Вывод в устройство - любое устройство (в том числе SDI) которое прописывается в /dev.

input file/device - цикличное воспроизведение видео из ts-файла.

При работе с файлами указывается полный путь до файла в поле File Path:

/catalog/stream.ts.

При работе с устройствами дополнительно активируется признак Is Device.

Список разрешённых потоков и ограничение Peer

Для возможности ограничения доступа к потокам телеканалов со стороны клиента (Peer) в режиме SRT Listen, PS1, HLS и HTTP в программе реализован функционал списка разрешённых потоков. В настройках Peer на передатчике задаётся список доступных телеканалов. Для этого необходимо в поле Stream Access добавить из общего списка каналов на сервере только те каналы, которые предполагаются к выдаче этому Peer. По умолчанию при пустом списке доступны все каналы.

Для Peer доступны ограничения работы по времени и количеству соединений по транспортным протоколам.

Anonymous peer

По умолчанию логин пира имеет значение anonymous. Анонимный пир позволяет раздавать потоки без привязки к IP или логину и паролю. Действуют ограничения на количество выдаваемых потоков по транспортным протоколам, по дате ограничения и по списку разрешённых потоков.

Возможно создать индивидуальный peer по логину(имени) и паролю.

Для авторизации peer по ip следует активировать опцию «Login Is IP».

Варианты авторизации:

  • По единичному IP

  • По диапазону IP, для примера: «192.168.1.10-192.168.1.20»

  • Комбинированный вариант, синтаксис IP списков: ip[-ip2][,…]

Подключение сторонних приложений

Для поддержки других протоколов, которые не поддерживаются встроенными средствами, имеется возможность получения и передачи потока через сторонние консольные приложения. Для этого для input и output имеется отдельный протокол std. Поток MPEG-TS принимается и передается через поток ввода/вывода операционной системы.

В настройке указывается консольное приложение (путь абсолютный), командная строка. Также можно задать переменные окружения.

Для input при настройке внешнего приложения надо исключить появление сообщений в стандартном выводе, только в stderr.

Для output можно задать пакетирование до 7-ми MPEG-TS пакетов.

Требования к входному потоку

Соответствие iso13818-1, Single Program (SPTS) или Multi Program Transport Stream (MPTS). Особенности MPTS описаны ниже, далее настройки указаны для Single Program.

Требуется хотя бы одна звуковая дорожка.

Поддерживаются потоки без видео, включается режимом Radio.

Поддерживаются закодированные потоки, для них надо включить Scrambled Stream.

Для синхронизации в потоке должны быть валидные PCR отметки.

Настройки Stream

Задать уникальное имя стрима. Использовать латиницу, цифры, знаки «_», «-». Дополнительно можно задать отображаемое имя потока, поддерживается русский и другие языки.

Stream Timeout - общий таймаут стрима. Если в течение этого времени нет валидного входного потока, то производится полный рестарт.

Pause - перевод stream, а также всех input и output в неактивное состояние. По умолчанию при добавлении нового stream, а также input и output они будут в паузе и неактивны.

В программе производится проверка входного потока с input на его валидность. Если поток проверку не прошел, то input считается аварийным.

Check Interval - Интервал повторной проверки потока.

Настройки фильтрации MPEG-TS:

Remove All Unnecessary Data - Удаление всех ненужных данных кроме PAT/PMT, видео и звука за исключанием заданных в отдельных фильтрах (см. ниже)

Remove SDT - Удаление SDT даннных (имя канала, провайдер и др).

Remove EIT/EPG - Удаление EPG данных.

Remove Teletext - Удаление телетекста.

Remove Subtitles - Удаление субтитров.

Управление bitrate потока:

Bitrate mode - режим управления bitrate.

  1. Origin (default) - поток передается без изменений.

  2. VBR - удалает NULL пакеты что минимизирует bitrate. Включить если потоки используются только для OTT вещания.

  3. CBR auto - включает выравнивание bitrate вставкой NULL пакетов (Stuffing). Результирующий bitrate будет настроен по максимальному bitrate входного потока.

  4. CBR set stuffing bitrate - явно задать нужный bitrate. Если задать меньше входного потока то он будет выравнен как в режиме CBR Auto.

При включенном CBR режиме PCR Accuracy будет соответствовать TR 101 290. PCR interval будет как в оригинальном потоке.

Исправление потоков:

Fix PAT/PMT interval - Исправляет интервал на соответствие TR 101 290, вставляя дополнительные PAT/PMT.

Резервирование источников

Может быть задано списком несколько input, но активен только один. Если input встал на аварию, то делается попытка использвать следующий по списку, и так по кругу.

Если у stream включить Fallback Check, то при работе резервного input (не первого в списке) будет производиться перепроверка выше по списку с интервалом Check Interval. Если при перепроверке поток валидный, то stream переключается на него.

Так как порядок input имеет значение, то его можно менять. Если input поставить в паузу, то он при работе учитываться не будет.

Фильтрация и модификация MPEG-TS

По умолчанию MPEG-TS поток передается как есть.

Для каждого input доступны следующие опции фильтрации MPEG-TS потока:

PID Accept - список разрешенных pid. Если пустой, то разрешено все, кроме PID Reject.

PID Reject - список запрещенных pid. Имеет приоритет над PID Accept.

Имеется возможность поменять pid. Для этого вводятся списки PID Old и PID New.

Mapping PID and Languages - переназначение языка звуковых дорожек.

Default Language - назначить язык по умолчанию, если для звуковой дорожки нет языка.

Для stream можно назначить новые MPEG-TS данные (SDT table):

  • MPEG-TS Network ID

  • Service Name

  • Provider Name

  • Language

MPTS потоки

MPTS поток - MPRG-TS поток с несколькими потоками (сервисами), каждый сервис имеет унникальный номер (PNR). Используется для DVB вещания.

Для MPTS потоков опции фильтрации недоступны. Потоки передаются как есть.

Функция мозаики по умолчанию отключена. Не рекомендуется ее включать на слабых CPU, это может добавить джиттер.

В диагностике потока отображаются данные по всем программам отдельно, а также суммарная статистика.

Демультиплексор

Выделяет из MTPS потока отдельные потоки. Для этого в SPTS стриме добавить input типа demux, выбрать источник и сервис по PNR. Если исходный MPTS активен, то при выборе PNR будет доступен список, иначе надо задать PNR вручную.

Мультиплексор

Собирает MPTS поток из отдельных потоков SPTS. Для настройки такого потока:

  • Создать MPTS stream.

  • Добавить input типа muxer. Задать bitrate для выравнивания CBR потока (stuffing, TR 101 290 и T-STD compliance).

    Если задать 0 (по умолчанию) то выравнивания не будет, bitrate будет соответствовать входным потокам. Там же можно ввести некоторые параметры MPEG-TS потока, для большинства применений подойдут параметры по умолчанию.

  • В Stream источника добавить output типа muxer. Ввести имя сервиса и, если надо, имя провайдера. Если используется не латиница, то в настройках MPEG-TS стрима выбрать язык.

  • Повторить для всех источников.

Мультиплексор генерирует для потока SDT, NIT и TDT/TOT (метки времени). EIT (EPG) берется из потоков источников. PID назначаются новые.

Тестовые потоки

Генератор Test Stream — тестовый сигнал (испытательная таблица). Позволяет создавать сгенерированные видеопотоки в качестве заглушек для эфира или авариях на основных потоках. Есть возможность задать тип изображения, звука, наложить текст и время.

Настраивается включением соответствующего типа input у стрима. Есть возможность установить тип видео-формата, разрешения, битрейта, громкость и частоту звука и др.

Перечень доступных Test Stream в виде списка доступен в левом боковом меню программы.

OTT сервис

Выдает потоки по протоколам на базе HTTP - HLS, MPEG-DASH (с версии 1.12) и MPEG-TS over HTTP. Поддерживается HTTPS (SSL). Выдача включается на вкладке OTT настроек Stream.

URL для подключения имеют формат:

host и port - задаются в настройках http server.

stream - ID стрима. Не путать с порядковым номером в списке стримов. ID отображается вверху страницы статистики стрима и в колонке ID списка стримов, ID задается при создании стрима и никогда не меняется.

Аналогично для HLS и DASH:

На странице статистики стрима отображаются URL подключенных протоколов (в виде шаблона) и текущий статус их работы. Неавторизированный доступ запрещен, клиенты должны быть прописаны в Peers.

Для HLS и HLS в URL доступны дополнительные параметры (опционально):

[URL]?a=1&s=40&m=40&v=5

  • a: 1 - абсолютный путь в плейлисте (по умолчанию), 0 - относительный путь.

  • s: продолжительность динамического плейлиста (сек), по умолчанию 40 сек.

  • m: минимальная продолжительность динамического плейлиста (сек), по умолчанию 40 сек. Максимальный размер динамического плейлиста 60 сек. Если текущий размер буфера чанков менее минимального размера указанного в запросе, то будет выдана ошибка 404. Это сделано для того, чтобы HLS стартовал с заполненного буфера чанков на сервере.

  • v: версия HLS протокола, выдаваемого в плейлисте. По умолчанию 5. Смена версии может потребоваться для некоторых HLS клиентов.

Для совместимости с некоторыми HLS клиентами в URL может быть добавлено имя файла index.m3u8, например http://host:port/hls/stream/login/password/index.m3u8.

Имеется 2 режима работы HLS сервера - Peer mode и OTT mode.

Peer mode - режим с простой разбивкой сегментов (чанков). Рекомендуется для пиринга (дистрибьюции) потоками.

OTT mode - режим с для OTT вещания оптимизированной разбивкой сегментов для быстрого старта проигрывателей. В этом режиме нагрузка на CPU больше, рекомендуется для вещания.

Для HTTP сервера может быть включен SSL (HTTPS), это делается в настройках сервера.

Chunk Min Interval и Chunk Max Interval

В режиме OTT делается анализ потока на PAT/PMT/SPS/PPS/IFrame и чанки нарезаются по критерию быстрого старта проигрывателей. Анализ начинается с min interval и если по какой-то причине данные не найдены, то чанк принудительно нарезается по max interval.

HLS Adaptive Multistream

С версии 1.10 добавлена поддержка HLS Adaptive Multistream и с версии 1.12 DASH Adaptive Multistream

Для адаптивных потоков настраивается отдельный HLS плейлист. Для этого надо:

  • У стримов, которые будут включены в адаптивный плейлист, включить HLS с OTT Mode.

  • В главном меню появится раздел адаптивных потоков. В нем надо добавить поток, где прописать все потоки, которые должны быть добавлены в этот плейлист.

  • У потоков может быть задан параметр битрейт. По умочанию он 0, что означает что битрейт берется от измеренного значения. Иначе его можно задать явно.

Для адаптивных плейлистов будет другой URL:

У пиров (клиентов) может быть назначено ограничение доступа к адаптивным потокам, также как к обычным. Разрешение для адаптивного потока включает разрешение ко всем потокам, которые входят в него.

Модель кеширования OTT HLS и DASH.

Сервер формирует ответы трёх категорий, различающихся сроком жизни содержимого и пригодностью для кеширования промежуточными узлами (reverse proxy, CDN, клиентский кеш).

1. Модель кеширования

1.1. Ресурсы и HTTP-заголовки

Ресурс

URL

Content-Type

Cache-Control

TS-сегмент

/h<sess>/<keyID>.ts, /h<sess>/<subID>/<keyID>.ts

video/mp2t

public, max-age=60, immutable

DASH MPD

/h<sess>/index.mpd

application/dash+xml; charset=utf-8

public, max-age=1

HLS master

/hls/<stream>/<login>/<pass>/index.m3u8

application/vnd.apple.mpegurl

public, max-age=1

HLS media

/h<sess>/index.m3u8, /h<sess>/<subID>/index.m3u8

application/vnd.apple.mpegurl

public, max-age=1

302 Redirect

/dash/<stream>/<login>/<pass>/index.mpd

no-cache, no-store

Raw TS

/http/<stream>/<login>/<pass>

video/mp2t

не задан; не кешируется

1.2. Характеристики TS-сегментов

Идентификатор keyID формируется как CRC64(startTime || streamID) и глобально уникален. URL сегмента адресует неизменное содержимое — при повторных запросах того же URL возвращается идентичный байтовый поток (пока сегмент остаётся в пределах скользящего окна).

Директива immutable подавляет условную ревалидацию клиентом (If-None-Match, If-Modified-Since). Значение max-age=60 обеспечивает совместимость с типичным timeShiftBufferDepth=40s.

1.3. Характеристики манифестов

max-age=1 ограничивает верхнюю границу устаревания содержимого в кеше одной секундой. При совместном использовании с proxy_cache_lock on (nginx) всплески запросов к манифесту коалесцируются в один запрос на origin в секунду.

1.4. Вариативность содержимого

При absPath=0 (значение по умолчанию, URL параметра «a» нет) манифесты HLS media и DASH MPD не содержат идентификатора сессии в теле. Содержимое манифеста идентично между сессиями, принадлежащими одной (stream, param)-комбинации. Это позволяет reverse-proxy кешу переиспользовать запись между сессиями при нормализации ключа кеша.

При absPath=1 (URL параметр «a=1») в теле манифеста присутствуют абсолютные URL, включающие схему, хост и идентификатор сессии. Содержимое становится специфичным для сессии, возможность кросс-сессионного переиспользования кеша отсутствует.

2. Поведение клиентов

Клиент

URL обновления манифеста

Воздействие на количество сессий

VLC 3.x HLS

/h<sess>/index.m3u8

Одна сессия на сеанс воспроизведения

VLC 3.x DASH

/dash/<stream>/.../index.mpd

Обрабатывается session reuse (см. 3.3)

ffmpeg 5.x HLS

/h<sess>/index.m3u8

Одна сессия на сеанс воспроизведения

ffmpeg 5.x DASH

/dash/<stream>/.../index.mpd (цикл повтора)

Обрабатывается session reuse (см. 3.3)

dash.js, hls.js

/h<sess>/... через <Location> / session URL

Одна сессия на сеанс воспроизведения

3. Специальные механизмы

3.1. HTTP 302 Redirect для DASH

Запрос вида /dash/<stream>/<login>/<pass>/index.mpd возвращает ответ 302 Found с заголовком Location: /h<sess>/index.mpd. Тело ответа пустое. Авторизация и выделение сессии выполняются на этапе обработки редиректа.

Клиенты, поддерживающие кеширование редиректа, обращаются к session URL напрямую в последующих запросах. Клиенты, не поддерживающие, повторяют запрос редиректа. Стоимость повторной обработки редиректа ограничена проверкой аутентификации и операциями session reuse.

3.2. Session reuse для DASH

При обработке запроса /dash/.../index.mpd, выполняемого под login-id L для stream-id S и флага adaptive=A, при наличии в _ottClientList существующей DASH-сессии с теми же (L, S, A) возвращается её sessID. Новая сессия не создаётся, слот maxConn не расходуется.

Применяется только к DASH. Для HLS отдельный механизм reuse не требуется: HLS-клиенты обновляют media playlist через session URL и не инициируют applyNewOTTSess на каждом refresh.

3.3. Переиспользование сегментов между сессиями

Путь /h<sess>/<keyID>.ts не зависит от sess при разрешении keyID в содержимое: keyID однозначно идентифицирует сегмент в рамках зарегистрированных ChunkList (см. _ottStreamList). Nginx с нормализованным cache key (обрезающим префикс /h<sess>/) обслуживает все запросы одного keyID из единственной записи кеша.

4. Параметры запроса

Параметр

Значение по умолчанию

Влияние

a

0

1 — абсолютные URL в манифестах; 0 — относительные

s

40

timeShiftBufferDepth в секундах

m

40

Минимальная длина окна для выдачи манифеста

v

3

#EXT-X-VERSION в HLS (игнорируется DASH)

Изменение параметра через query string обновляет сохранённые в сессии значения при следующем applyNewOTTSess-вызове.

5. Нагрузочные характеристики

Нагрузка на origin масштабируется с числом одновременно наблюдаемых различных стримов. Увеличение числа клиентов, наблюдающих один и тот же стрим, не увеличивает количество запросов к origin при наличии reverse-proxy кеша и нормализованного cache key.

Сценарий

Частота origin-запросов (реф.)

1 клиент на стрим X

MPD: 0.4 req/s, segment: 0.2 req/s

N клиентов на один стрим X (кеш включён)

MPD: 1 req/s, segment: 0.2 req/s

N ffmpeg-клиентов в режиме повтора на одном стриме

MPD: 1 req/s (с proxy_cache_lock)

N клиентов на N различных стримов

MPD: 0.4·N req/s, segment: 0.2·N req/s

6. Nginx как кеширующий reverse proxy

6.1. Базовая конфигурация

proxy_cache_path /var/cache/nginx/pss_segments
    levels=1:2 keys_zone=pss_segments:100m
    max_size=20g inactive=30m use_temp_path=off;

proxy_cache_path /var/cache/nginx/pss_manifests
    levels=1:2 keys_zone=pss_manifests:10m
    max_size=256m inactive=5m use_temp_path=off;

upstream pss_backend {
    server 127.0.0.1:41972;
    keepalive 64;
}

map $uri $pss_cache_key {
    ~^/h[0-9a-f]{16}(?<tail>/.+\.(ts|m3u8))$  "stream:$tail";
    default                                     $uri;
}

server {
    listen 80;
    server_name stream.example.com;

    location ~* "^/h[0-9a-f]{16}(/[0-9]+)?/[0-9a-f]+\.ts$" {
        proxy_cache               pss_segments;
        proxy_cache_key           $pss_cache_key;
        proxy_cache_valid         200 60s;
        proxy_cache_valid         404 403 0s;
        proxy_cache_lock          on;
        proxy_cache_use_stale     updating error timeout;
        proxy_cache_revalidate    on;
        add_header                X-Cache-Status $upstream_cache_status;

        proxy_pass                http://pss_backend;
        proxy_http_version        1.1;
        proxy_set_header          Connection "";
        proxy_buffering           on;
    }

    location ~* "(^/h[0-9a-f]{16}(/[0-9]+)?/index\.(m3u8|mpd)$|^/(hls|dash)/.*\.(m3u8|mpd)$)" {
        proxy_cache               pss_manifests;
        proxy_cache_key           $pss_cache_key;
        proxy_cache_valid         200 1s;
        proxy_cache_valid         404 403 0s;
        proxy_cache_lock          on;
        proxy_cache_lock_timeout  2s;
        proxy_cache_use_stale     updating;
        add_header                X-Cache-Status $upstream_cache_status;

        proxy_pass                http://pss_backend;
        proxy_http_version        1.1;
        proxy_set_header          Connection "";
    }

    location / {
        proxy_pass                http://pss_backend;
        proxy_http_version        1.1;
        proxy_set_header          Connection "";
        proxy_set_header          X-Forwarded-Proto $scheme;
        proxy_set_header          X-Forwarded-Host  $host;
        proxy_buffering           off;
        proxy_read_timeout        3600s;
    }
}

6.2. Назначение директив

Директива

Назначение

proxy_cache_lock on

Сериализует выполнение upstream-запросов при одновременных cache miss по одному ключу

proxy_cache_use_stale updating

Возвращает устаревшую копию параллельным запросам в период обновления кеша

proxy_cache_revalidate on

Использует If-Modified-Since при cache miss с сохранённой копией

proxy_cache_valid 404 403 0s

Запрещает кеширование ошибок авторизации и 404

keepalive 64 в upstream

Поддерживает пул persistent-соединений к origin

proxy_buffering on

Для сегментов; включает буферизацию ответа в nginx

proxy_buffering off

Для раздела /; отключает буферизацию (raw streaming)

6.3. Расчёт max_size кеша сегментов

Ориентировочное значение: bitrate × timeShiftBufferDepth × distinct_streams × 2

Пример: 10 стримов × 8 Mbps × 40s × 2 ≈ 800 MB. Рекомендуется задать запас 10x для учёта вариативности битрейта.

6.4. TLS-терминация

Сервер Perfect Streamer принимает соединения на портах HTTP и HTTPS. При TLS-терминации на nginx upstream использует порт HTTP. Пересылка заголовков X-Forwarded-Proto и X-Forwarded-Host обязательна для корректного формирования абсолютных URL при absPath=1.

server {
    listen 443 ssl http2;
    server_name stream.example.com;

    ssl_certificate           /etc/letsencrypt/live/stream.example.com/fullchain.pem;
    ssl_certificate_key       /etc/letsencrypt/live/stream.example.com/privkey.pem;
    ssl_protocols             TLSv1.2 TLSv1.3;
    ssl_session_cache         shared:SSL:10m;
    ssl_session_timeout       1d;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location ... {
        proxy_pass                http://pss_backend;
        proxy_set_header          X-Forwarded-Proto https;
        proxy_set_header          X-Forwarded-Host  $host;
        proxy_set_header          Host              $host;
        # + директивы кеширования из 6.1
    }
}

server {
    listen 80;
    server_name stream.example.com;
    return 301 https://$host$request_uri;
}

При HTTPS между nginx и origin применяются директивы proxy_ssl_verify, proxy_ssl_trusted_certificate. Для loopback-соединений шифрование избыточно.

6.5. Мультихост

При обслуживании нескольких server_name из одного nginx-процесса $host добавляется в cache key для изоляции контента:

map $uri $pss_cache_key {
    ~^/h[0-9a-f]{16}(?<tail>/.+\.(ts|m3u8))$  "$host:stream:$tail";
    default                                     "$host:$uri";
}

Размер keys_zone рассчитывается как 8000 ключей/MB. Для мультихост-инсталляций с тысячами стримов рекомендуется keys_zone=...:300m или выше.

7. Клиентское кеширование

Cache-Control: immutable обрабатывается браузерами Chrome/Firefox/Safari. Клиентский кеш возвращает сегмент без условного запроса при повторном обращении (в том числе при обратном seek в пределах буфера плеера).

Service Workers могут применять стратегию cache-first на основании содержимого Cache-Control. DASH-плееры (dash.js, Shaka) используют MSE через SourceBuffer; сегмент, помещённый в буфер, остаётся доступен без повторного HTTP-запроса до выхода за границу скольжения.

Для кросс-доменных запросов заголовок Access-Control-Allow-Origin: * позволяет кеширование в shared caches без Vary: Origin. При смене значения ACAO на конкретный Origin требуется Vary: Origin, что снижает эффективность shared cache.

8. Размещение через CDN

Perfect Streamer совместим с CDN в режиме pull-from-origin (Cloudflare, Akamai, Fastly, BunnyCDN, Amazon CloudFront).

Origin shield. Рекомендуется размещение одного или нескольких shield-узлов между CDN edge и origin для снижения частоты запросов на origin при глобальном распределении клиентов.

Purge. Content-addressed сегменты не требуют purge. При изменении метаданных стрима (кодек, разрешение) manifest’ы обновляются в течение max-age=1 без явного purge.

Cache warming. При ожидаемом росте нагрузки на конкретный стрим допустим прогрев CDN с нескольких географических точек до начала трансляции.

Геораспределение. Сегменты (max-age=60) хорошо подходят для географически распределённого кеширования. Манифесты (max-age=1) допускают задержку доставки до одной секунды — приемлемо для non-low-latency live.

9. Мониторинг

9.1. X-Cache-Status

Добавление add_header X-Cache-Status $upstream_cache_status; в каждый location с кешированием. Значения:

Значение

Описание

HIT

Ответ из кеша

MISS

В кеше отсутствовал, получен от origin и сохранён

EXPIRED

Просрочен, обновлён

UPDATING

Отдана stale-копия параллельному запросу во время обновления

STALE

use_stale вернул просроченную копию (origin недоступен)

REVALIDATED

Origin вернул 304 Not Modified

BYPASS

Сработал proxy_cache_bypass

9.2. Формат access-log

log_format pss_cache '$remote_addr $status $request_method "$request" '
                     '$body_bytes_sent rt=$request_time ut=$upstream_response_time '
                     'cache=$upstream_cache_status key=$pss_cache_key';

server {
    access_log /var/log/nginx/pss.log pss_cache;
}

9.3. Метрики

Модуль nginx-vts экспортирует метрики per-zone в формате Prometheus:

GET /status/format/prometheus

Рекомендуемые пороги для алертов:

Метрика

Порог

Возможная причина

Segment HIT rate

< 90% за 5 минут

Нарушена нормализация cache key; малый max_size

Manifest MISS rate

> 50% за 1 минуту

proxy_cache_lock не сериализует запросы

Upstream response time p95

> 500 мс за 1 минуту

Перегрузка origin

Cache zone fill

> 90% за 10 минут

Приближение к max_size, планируется LRU-eviction

10. Диагностика

Симптом

Вероятная причина

Решение

Segment HIT rate низкий

Vary: Origin с высокой вариативностью Origin; нарушение normalisation в map

Проверить заголовки и regex в директиве map

404 на сегментах после выхода из окна

Закешированный 404 при сегменте, выпавшем из sliding window

Добавить proxy_cache_valid 404 0s в location segments

Задержка playback start 2-5 с

proxy_cache_lock_timeout превышает target latency

Снизить до 1-2 с; включить proxy_cache_use_stale updating

Manifest не обновляется

proxy_cache_valid переопределяет max-age

Явно указать proxy_cache_valid 200 1s

Рост TIME_WAIT на upstream

Отсутствует keepalive в upstream-блоке

Добавить keepalive 64, proxy_http_version 1.1, proxy_set_header Connection ""

403 на /dash/.../<segment>.ts от ffmpeg

Клиент резолвит относительные URL от pre-redirect URL

Сервер эмитит <BaseURL>/h<sess>/</BaseURL> (absolute path); совместимо в текущем билде

11. Безопасность

11.1. Session URL

URL формата /h<sess>/... выполняет функцию сессионного токена — не требует повторной аутентификации. Срок жизни ограничен idle timeout (значение 30 с). При отсутствии активности сессия удаляется cleaner-задачей.

Требования:

  • HTTPS для всех OTT-путей (/hls/, /dash/, /h<sess>/) в production

  • Session ID в Location заголовке 302 не кешируется (no-cache, no-store)

11.2. Rate limiting

limit_req_zone $binary_remote_addr zone=dash_top:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=hls_top:10m  rate=5r/s;

server {
    location /dash/ {
        limit_req zone=dash_top burst=20 nodelay;
        proxy_pass http://pss_backend;
    }
    location /hls/ {
        limit_req zone=hls_top burst=20 nodelay;
        proxy_pass http://pss_backend;
    }
}

Session URL (/h<sess>/) не требует rate limiting — обработка дешёвая, ответы кешируются.

11.3. Кеширование ответов с ошибками

proxy_cache_valid 200 60s;
proxy_cache_valid 301 302 0s;
proxy_cache_valid 404 403 0s;
proxy_cache_valid any 1s;

Запрещает кеширование редиректов (уникальный sess в Location) и ответов с ошибками авторизации или отсутствия ресурса.

11.4. Ограничение сетевого доступа к origin

Порт 41972 (41982 для HTTPS) должен быть закрыт для внешнего трафика. Допустимые конфигурации:

  1. Bind Perfect Streamer на 127.0.0.1 (при локальном nginx)

  2. Firewall-правило:

iptables -A INPUT -p tcp --dport 41972 ! -s 10.0.0.0/8 -j DROP

12. Интеграция с middleware

12.1. Модель prefix-login

Perfect Streamer поддерживает делегирование идентификации пользователя middleware/биллинг-системе через механизм prefix-login. Внешний коннектор к биллинг-системе не включён в текущий релиз.

Конфигурация embedded-пользователя:

{
  "id": 9,
  "login": "sub",
  "password": "xxx",
  "is-prefix": true,
  "max-conn-http-hls": 1,
  "accept-stream": [ ... ]
}

При is-prefix: true сервер принимает URL с логином вида <prefix><billing_user_id>:

/dash/test1/sub42/xxx/index.mpd
/hls/test1/sub43/xxx/index.m3u8

12.2. Формат статистики

<clients>
  <client login-id="-1974387287" login="sub" match-login="sub42"
          sess-id="11331..." ott-type="dash" stream-id="10000" .../>
  <client login-id="-2147031294" login="sub" match-login="sub43"
          sess-id="11132..." ott-type="dash" stream-id="10000" .../>
</clients>

Поле login-id содержит хеш URL-логина. Поле login — конфигурационное значение. Поле match-login — URL-логин, использованный клиентом.

12.3. Ограничения prefix-login

  • Общий пароль. Все subscribers prefix-пула используют одно значение password. Компрометация пароля предоставляет доступ к любому <prefix><string>.

  • Гранулярность ACL. accept-stream применяется ко всему prefix-пулу. Per-subscriber ACL недоступен без внешнего биллинга.

  • Ротация пароля. Изменение password отключает всех активных subscribers. Для постепенной замены требуется временное использование двух prefix-логинов.

13. WebVTT субтитры

Источник субтитров — DVB Teletext / DVB Subtitling из входного MPEG-TS. В разделах Media Information или Original Media Information должны присутствовать дорожки Teletext subtitles. Также в разделе Analyzer можно убедиться, что пакеты соответствующих PID активны.

Для OTT HLS/DASH должен быть включён режим OTT (в Peer mode WebVTT субтитры недоступны). В разделе Output # OTT должен появиться ненулевой счётчик чанков OTT WebVTT buffer chunk count.

Для диагностики субтитров включить у стрима Analyze и Trace. При старте потока в логе стрима должно появиться:

Start Teletext subtitle decoder
[ttxsubdec] ttx: pid=331 magazine=8 page=0x88 lang=***

Далее в лог пишется декодированный текст субтитров.

13.1. URL VTT-сегментов

Схема

URL

Содержимое

HLS master

/hls/.../index.m3u8

#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",...,URI="/h<sess>/sub/<pid>/index.m3u8"

HLS subtitle playlist

/h<sess>/sub/<pid>/index.m3u8

список <keyHex>.vtt с #EXTINF

HLS VTT-сегмент

/h<sess>/sub/<pid>/<keyHex>.vtt

VTT с HLS-flavored X-TIMESTAMP-MAP

DASH MPD AdaptationSet

в index.mpd

contentType="text" mimeType="text/vtt" + <SegmentTemplate media="$Number$.vtt">

DASH VTT-сегмент

/h<sess>/sub/<pid>/<seq>.vtt

VTT с DASH-flavored X-TIMESTAMP-MAP

<keyHex> — 16-символьный hex от CRC64(startTime, streamID, pid). <seq> — десятичный номер чанка subtitle storage’а (separate counter от video storage).

DVR / Архив

С версии 1.13 в Perfect Streamer доступен встроенный DVR — постоянный архив стрима на диске, который работает параллельно с обычной OTT-выдачей (HLS / DASH). Архив пишется автоматически, без отдельного процесса, и воспроизводится через те же URL OTT, что и live-вещание — отличие только в query-параметре.

Возможности:

  • Запись каждого OTT-стрима в архив на выбранном хранилище.

  • HLS и DASH воспроизведение архива (VOD) на тех же URL, что и live.

  • Поддержка субтитров (WebVTT) — пишутся вместе с TS-чанками.

  • Несколько хранилищ — стрим привязывается к одному, разные стримы могут писать на разные диски.

  • Автоматическая очистка по времени удержания и по заполнению диска.

  • EPG-aligned VOD — выдача архива по указанию EPG-события.

  • Адаптивный VOD — поддерживается для адаптивных групп.

DVR не требует отдельной лицензии. Включается на уровне стрима добавлением привязки к хранилищу.

DVR не заменяет live-вещание. Если у стрима есть архив — клиент получает live-плейлист с тем же поведением, что и без DVR. Архив начинает играть только тогда, когда клиент явно запросил VOD-режим через query-параметр URL (см. ниже).

Конфигурация хранилища

Хранилище — это запись в разделе Configuration / DVR Storage. Каждая запись описывает одну директорию на диске, в которую PSS пишет файлы архива. Стрим использует одно хранилище.

При добавлении хранилища настраиваются:

Name — отображаемое имя.

Dir Path — путь к директории на диске. После создания записи путь изменить нельзя — чтобы перенести архив на другой диск, нужно удалить запись и добавить новую с новым путём. Существующие файлы при удалении записи на диске не трогаются.

Max Usage, % — порог заполнения диска (по умолчанию 90 %). При превышении начинает работать size-based очистка (см. ниже). Минимум 1 %, максимум 100 %.

Cleanup Interval, сек — период работы задачи очистки (по умолчанию 10 сек). На каждом тике сначала срезается всё старше глубины хранения стрима, затем — при превышении Max Usage — старые чанки.

Disk Pressure Grace, сек — сколько секунд Used % должен непрерывно превышать Max Usage, прежде чем начнётся Size-based cleanup (по умолчанию 60 сек). Фильтрует короткие пики.

Disk Pressure Cut, сек — верхний предел для одного тика очистки: сколько секунд видео на один стрим может быть удалено за раз (по умолчанию 300 сек). Остальное переносится на следующий тик.

Disk Emergency Bytes — порог свободного места, ниже которого хранилище переходит в состояние Error и запись останавливается (по умолчанию 2 ГиБ). Автоматическое восстановление — при свободном месте ≥ 2 × этого значения.

Alarm Disk-Full Hysteresis, % — ширина зоны гистерезиса при выходе из состояния DiskFullDegraded (по умолчанию 2 %).

Большинство значений по умолчанию подходят для типовых установок; коррекция требуется обычно только для Max Usage и Dir Path.

На один диск имеет смысл создавать одно хранилище. Если на одном диске указать несколько записей с разными подкаталогами, они будут конкурировать за свободное место — statvfs даёт общую картину, а очистка отдельная.

Привязка стрима к хранилищу

В настройках Stream / OTT появляется секция DVR:

Storage — выпадающий список доступных хранилищ; 0 означает «архив выключен для этого стрима».

Storage Hours — глубина архива для этого стрима в часах. Чанки старше этого значения удаляются на каждом тике задачи очистки. 0 отключает Rolling cleanup (срабатывает только Size-based cleanup по Max Usage).

Storage Min Hour — нижний порог защиты (часы). Задача очистки никогда не удаляет чанки моложе этого значения, даже под давлением Max Usage. Используйте, если бизнес-логика требует гарантированной свежей записи, например «последние 2 часа всегда есть».

Изменение Storage на лету:

  • выставление 0 — отключает архив; чанки на диске сохраняются, новые не пишутся. VOD-сессии по этому стриму начинают отвечать 404;

  • выбор другого хранилища — стрим отвязывается от старого и начинает писать в новое. Файлы со старого диска не переносятся.

Изменение Storage Hours и Storage Min Hour применяется мгновенно — на следующем тике задача очистки увидит новое значение.

После настройки стрим начинает писать архив автоматически, как только перейдёт в состояние Running.

VOD: воспроизведение архива

Архив воспроизводится через те же URL, что и live-вещание HLS / DASH (см. раздел OTT сервис) — отличается только query-параметр.

URL и параметры

URL для HLS и DASH:

Без query-параметров — обычный live с скользящим окном. При наличии параметра t — VOD режим.

Параметр

Назначение

t=<epoch>

Время начала VOD (Unix epoch, сек). t=0 — от начала архива. Наличие t (даже t=0) включает VOD-режим.

d=<sec>

Длительность VOD-окна, сек. d=0 или параметр отсутствует — «до текущего момента». Имеет смысл только вместе с t.

epg=<epoch>

EPG-aligned VOD: сервер сам находит EPG-событие, активное в указанный момент, и берёт его start и duration как границы окна. Несовместим с t и d (server-side замена). См. ниже.

a, s, m, v

Стандартные параметры live (см. OTT сервис); s и m в VOD-режиме игнорируются.

Поведение по t и d:

t

d

Окно

Условие 404

нет

live (скользящее окно)

0

нет / 0

[начало архива, сейчас]

DVR не привязан

0

> 0

[начало архива, +d]

DVR не привязан

> 0

нет / 0

[t, сейчас]

DVR не привязан

> 0

> 0

[t, t+d]

DVR не привязан

Нормализация границ:

  • t раньше начала архива — start автоматически подтягивается к первому доступному чанку (cleanup мог уже срезать). Это не 404, просто покажем то, что осталось.

  • t в будущем или окно полностью раньше архива — пустой, но валидный плейлист (HLS: только header + EXT-X-ENDLIST; DASH: @type="static", mediaPresentationDuration="PT0S").

  • Чанки выбираются строго по startTime ∈ [t, t+d) — частичных сегментов нет.

VOD на стриме без архива (или у которого хранилище в Error) — 404 сразу на master playlist / MPD. Сессия не создаётся.

Текст ошибок в теле 404 (видны в логах сервера и в HTTP body):

  • VOD: stream not running — стрим есть в конфиге, но не в Running.

  • VOD: no DVR archive — у стрима не задано хранилище или хранилище в Error.

  • VOD: DVR detached — стрим был отвязан от хранилища между запросами.

  • VOD: EPG event not found — для ?epg= событие не найдено.

VOD HLS плейлист — закрытый (плеер видит длительность и может перематывать):

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:5.000,
...
#EXT-X-ENDLIST

В live-плейлисте этих маркеров нет — это и есть единственное отличие.

VOD DASH MPD — статический: @type="static", фиксированный mediaPresentationDuration, явные <SegmentURL>. Live-DASH остаётся @type="dynamic".

Если в выбранном интервале есть разрывы в архиве (например, был перезапуск записи или cleanup срезал часть посередине), DASH MPD автоматически разбивается на несколько <Period> — по одному на каждую сплошную дорожку. Плееры (VLC, dashjs, Shaka) перематывают через границу периода без специальных настроек.

EPG-aligned VOD

Если стрим связан с EPG-источником (поля EPG Source и EPG Channel в настройках стрима), клиент может запросить архив по моменту времени, попадающему в EPG-событие:

Сервер находит EPG-событие, активное в указанный epoch, и сам подставляет его start и duration как границы VOD-окна. Это удобно для каталога передач: UI знает время события, но не обязан вычислять точные сек./мс. границы.

Если стрим к EPG не привязан или в этот момент нет события — 404 ``VOD: EPG event not found``. Параметры t и d при наличии epg игнорируются.

Адаптивные потоки

Адаптивные группы (см. HLS Adaptive Multistream) поддерживают те же VOD-параметры:

В master playlist (HLS) попадают только те варианты, у которых задано хранилище DVR. Варианты без DVR пропускаются (в логе появляется VOD: variant N has no DVR), сборка из оставшихся вариантов работает.

В DASH-варианте каждое качество становится отдельным <Representation> внутри общих <Period>; плеер может переключаться между качествами без переоткрытия манифеста.

Поведение проигрывателя

VOD HLS / DASH с архива играют стандартные плееры: VLC, hls.js, dashjs, Shaka, ffmpeg. Перемотка по таймлайну работает.

Если плеер запросил сегмент, который к этому моменту уже удалил cleanup, сервер вернёт 404 на этот сегмент (не 500). VLC, hls.js, dashjs пропускают такой сегмент и продолжают воспроизведение со следующего.

Дополнительные возможности:

  • Защита активных сессий: пока VOD-сессия открыта, cleanup не удаляет чанки в её окне (см. ниже).

  • Live-edge bridge: если клиент в VOD-сессии запросил сегмент за пределами vodEnd — например, при достижении конца архива пошёл вперёд по таймлайну — сервер автоматически отдаёт сегмент из live-памяти. Никаких переадресаций и повторной авторизации.

  • Кеш плейлиста: на повторные запросы того же VOD index.m3u8 / index.mpd сервер отдаёт байт в байт идентичный ответ — без повторного построения. Подходит для CDN перед PSS.

Субтитры в архиве

Если у стрима в потоке есть субтитры (DVB Subtitling, Teletext или WebVTT) и включена опция OTT WebVTT в настройках стрима, субтитры архивируются параллельно с TS-чанками — в файлы .vtt рядом с .ts.

В live-режиме master playlist содержит EXT-X-MEDIA:TYPE=SUBTITLES; в VOD-режиме сервер отдаёт VOD-плейлист субтитровENDLIST) и .vtt сегменты на тех же URL.

Особенности:

  • HLS: сохраняется заголовок X-TIMESTAMP-MAP в начале каждого .vtt (обязательно по спецификации HLS).

  • DASH: заголовок X-TIMESTAMP-MAP удаляется на лету (он привязан к абсолютному PCR и конфликтует с DASH-якорем; иначе VLC показывает пустые субтитры).

  • В адаптивной группе: если активный sub-stream не пишет субтитры — VTT-сегменты вернут 404. На следующем варианте плеер может снова получить субтитры.

Отключить субтитры можно либо опцией OTT WebVTT в стриме, либо вообще не включая HLS в OTT mode.

Очистка и retention

PSS использует две стратегии очистки, работающие на каждом тике задачи очистки (по умолчанию каждые 10 сек):

  1. Rolling cleanup (per-stream): для каждого стрима удаляются чанки старше Storage Hours. Работает всегда, даже если диск полупустой.

  2. Size-based cleanup (общий по хранилищу): когда Used % на диске непрерывно превышает Max Usage в течение Disk Pressure Grace секунд, начинают срезаться самые старые чанки пропорционально по всем стримам, привязанным к хранилищу. Очистка идёт порциями по Disk Pressure Cut сек видео на стрим за тик. Никогда не удаляет чанки моложе Storage Min Hour.

  3. Emergency disk-full cut: когда свободное место упало ниже Disk Emergency Bytes, очистка работает агрессивно, может удалять даже защищённые сессией чанки. Запись останавливается до тех пор, пока свободное место не восстановится с гистерезисом × 2.

  4. Orphan scan (раз в час): на диске могут остаться файлы, не учтённые в индексе (после внезапного остановления PSS). Раз в час scanner проходит по подкаталогам стримов и удаляет такие «забытые» файлы. Защита от race с writer’ом — пропускаются файлы моложе 60 сек.

Замечание. Задачи очистки запускаются в фоне; пользователю обычно не нужно ничего делать. Если архив растёт быстрее, чем срезается — снижайте Storage Hours на стримах или повышайте Disk Pressure Cut.

Защита активных VOD-сессий

Когда клиент открывает VOD-сессию, на каждом хранилище, участвующем в её окне, регистрируется «защитный слот» с моментом начала окна. Rolling и size-based очистка не трогают чанки в окне открытой сессии. Слот снимается автоматически, когда сессия закрывается (FIN, таймаут).

Это значит:

  • Если клиент держит VOD-сессию долго, он гарантированно может перемотать на любой момент внутри своего окна — чанки не «исчезнут под ним».

  • Очистка по Max Usage может временно не доводить Used % до желаемого порога, пока сессия активна; как только клиент уйдёт — очистка догонит.

  • Emergency disk-full cut и Storage Min Hour обходят защиту: если диск близок к нулю свободного места, чанки удаляются, и клиент получит 404 на затронутые сегменты (плеер пропустит).

  • После перезапуска PSS защитные слоты исчезают — очистка возобновляется сразу.

Несколько хранилищ

Можно создать любое количество записей DVR Storage — каждая для своей директории / своего диска. Стримы привязываются к разным хранилищам независимо. Очистка и пороги (Max Usage, Disk Pressure) работают per-storage.

Сценарии применения:

  • Разделение по уровням ценности: хранилище на быстрой SSD для премиум-каналов с большой глубиной, хранилище на ёмком HDD для остальных.

  • Отдельный диск под архив: чтобы запись DVR не конкурировала с системным диском или с временными файлами.

  • Разделение проектов: один диск под комплект каналов №1, другой под №2 — упрощает миграцию и аудит.

Изменение привязки стрима (поле Storage в Stream / OTT) переключает запись на лету. Старые файлы остаются на прежнем диске нетронутыми — их можно либо удалить вручную, либо снова подключить запись, переставив стрим обратно.

Состояние хранилища и мониторинг

В разделе Data / DVR Storage List (а также через API GET /data/dvr-storage-list) отображаются по каждому хранилищу:

  • StateReady / DiskFullDegraded / Error.

  • Total / Free / Used Bytes — статистика диска (statvfs).

  • Used % — текущий процент заполнения.

  • Archived Bytes — суммарный размер чанков, учтённых в индексе всех привязанных стримов (без orphan-файлов).

  • Attached Streams — сколько стримов привязаны к этому хранилищу.

  • Pressure Since Sec — момент (epoch), когда Used % впервые превысил Max Usage в текущем эпизоде давления; 0 означает «давления нет сейчас».

Состояния:

  • Ready — нормальная работа.

  • DiskFullDegraded — свободного места < (Disk Emergency Bytes × 2); запись пока продолжается, но в любой момент может перейти в Error.

  • Error — свободного места < Disk Emergency Bytes; запись остановлена; restart по гистерезису.

Если хранилище ушло в Error, проверьте свободное место на диске; PSS сам не вытаскивает из этого состояния, пока физически не появится больше места.

Защита от случайных потерь данных

Несколько операций админ-интерфейса приводят к потере записанного архива или к прекращению выдачи VOD. Перед их выполнением админский UI показывает модальное подтверждение:

  • Удаление DVR Storage — все привязанные стримы теряют доступ к VOD; файлы на диске остаются, но без записи о хранилище они недостижимы через PSS.

  • Переключение стрима на другое хранилище — VOD по старому архиву перестаёт работать.

  • Отвязка стрима от хранилища (Storage = 0) — то же самое.

  • Уменьшение Max Usage — может спровоцировать size-based очистку и удалить старые чанки.

  • Уменьшение Storage Hours / Storage Min Hour — может вывести часть архива за rolling-окно.

Это сознательное решение продукта: операция выполнима, но требует подтверждения, и удалённые файлы остаются на диске (их можно вернуть из бэкапа). Размещение архива на отдельном файловом сервере / RAID существенно снижает риск необратимой потери.

Ограничения текущей версии

  • VOD-сессия, открытая клиентом, не следит за live edge — если за время сессии в архив добавились новые чанки, клиент должен перезапросить плейлист (стандартное поведение всех HLS / DASH плееров).

  • На один диск имеет смысл назначать одно хранилище — несколько записей с разными подкаталогами на одном диске будут конкурировать за свободное место.

  • Сегменты адресуются хешем (HLS) или $Number$.ts шаблоном (live DASH) / явными <SegmentURL> (VOD DASH). Изменение размеров чанка между live и VOD не требует переоткрытия URL.

  • Orphan-scanner запускается раз в час; чтобы ускорить — достаточно перезапустить PSS.

Операции с потоками

Удаление. Для удаления потока зайдите в настройки потока и нажмите кнопку Delete stream.

Клонирование. Для клонирования потока зайдите в настройки исходного потока и нажмите кнопку Clone stream.

Сортировка. Для настройки сортировки потоков нажмите кнопку Sort в окне списка потоков. После этого укажите нужный порядок путём перетаскивания потоков вверх и вниз по списку. Для сохранения указанного порядка сортировки нажмите кнопку Save order или Cancel для отмены изменений.

Фильтрация списка. Чтобы отфильтровать список потоков нажмите на кнопку с иконкой поиска и введите строку фильтра. Для отмены фильтра нажмите кнопку стрелки назад.

Групповые операции. В режиме фильтрации списка потоков возможно выбрать несколько потоков путём включения галочек в левом столбце. Если выбраны какие-то потоки, становятся доступны кнопки Удалить и Клонировать для выбранных потоков.

Экспорт и импорт потоков с помощью скрипта на python

Экспорт и импорт конфигурации реализован через .m3u плейлист, делается через скрипт на Python.

Требуется наличие Python версии 3 по пути /usr/bin/python3.

Экспорт и импорт потоков через web-интерфейс

В списке потоков при нажатии на кнопку Playlist открывается диалог экспорта потоков в плейлист формата m3u8. Экспортирутся только те потоки, которые в данный момент отображаются с учётом применённых фильтров списка.

Настройки:

  • Host / IP - указывается имя сервера или адрес, который будет использоваться для формирования URL потоков.

  • Protocols - указываются типы протоколов для экспорта.

  • Login - выбирается аккаунт, который будет использован для формирования URL потоков.

  • Use Display Names - использовать Display name потока вместо Stream name в m3u8-файле.

Плейлист скачивается в виде m3u8-файла при нажатии на кнопку Download.

При нажатии на кнопку Import Playlist происходит переключение диалога в режим импорта потоков из плейлиста формата m3u8. При импорте потоков существующие потоки не удаляются. У всех импортированных потоков в поле Note прописывается время импорта.

Настройки:

  • Playlist - выбор файла плейлиста для импорта.

  • Create Outputs - выбор протокола для автоматической генерации выходов для импортированных потоков.

  • Output Ports From - начальный номер порта для генерации выходов.

  • Output IP - выбор интерфейса, к которому привязываются выходные потоки.

  • Tags - тэги, которыми будут помечены импортированные потоки. Полезны для групповых операций. Например, для удаления всех импортированных потоков.

Если в поле Playlist указан файл для импорта, то кнопка Load Playlist становится активна. При нажатии на кнопку Load Playlist происходит предварительная загрузка плейлиста, результат парсинга плейлиста отображается в таблице. После парсинга плейлиста становится активна кнопка Import Streams, при нажатии на которую происходит импорт потоков и генерация выходов для них.

Отчеты и диагностика

В разделе Streams отображаются данные о всех stream в виде таблицы. Пауза - доступно ролям admin и restricted admin.

Для каждого stream доступна подробная статистика и отчеты.

Peers - список активных получателей (клиентов). Для каждого доступна отдельная статистика.

Анализ потоков

Анализатор потоков стримера производит измерение и анализ различных параметров потока MPEG-TS, что позволяет оценить качество.

Input speed - скорость (битрейт) потока в kbps. Изменяется после фильтрации по меткам PCR. Выводится в виде графика, где также отображается выходной битрейт после синхронизатора.

Raw data speed - скорость приема данных по заданному протоколу. Overhead - дополнение в % на издежки протокола.

CC errors - пропуск пакетов (CC, discontinuity). Отображаются счетчики за периоды и накопительный счетчик за stream uptime. Также отображается история ввиде графика.

Scrambled - счетчики закодированных MPEGTS ES пакетов. Если не 0, то имеются сбои в декодировании закрытых каналов.

Sync by - Источник синхронизации, по умолчанию PCR. При некорректном PCR для синхронизации может использоваться PTS/DTS видео (см. соот настройку у input Force Sync by PTS).

PCR interval - интервал между PCR отметками. Рекомендуется не более 50 мс.

PCR jitter - характеризует точность синхронизации выходного потока. Измеряется как разница между PCR и реальным временем.

Analyze PCR PMT Gap - включается отдельной настройкой. Анализируется разброс между PCR и PTS/DTS для кажного ES. История отображается ввиде графика. Слишком большой разброс может вызвать проблемы у проигрывателе с малым размером буфера синхронизации. Анализ включается настройкой Analyze PAT/PMT/KF.

PAT interval и PMT interval - изменяется интервал между PAT (PMT) таблицами. Рекомендуется не более 500 мс. Анализ включается настройкой Analyze PAT/PMT/KF.

Key Frame interval - изменяется интервал между ключевыми кадрами (KF). Для проигрывателей с рандомным подключением к потоку рекомендуется не более 1 сек. Анализ включается настройкой Analyze PAT/PMT/KF.

PAT/KF interval - измеряет средний интервал между началом и концом последовательности PAT/PMT/SPS/PPS/KF. От этого зависит скорость старта воспроизведения проигрывателей с рандомным подключением к потоку. Измеряется по началу KF в потоке, поэтому реальное время старта проигрывателя будет больше. Анализ включается настройкой Analyze PAT/PMT/KF.

Включение Analyze PAT/PMT/KF включает анализатор потока в постоянном режиме, что приводит к увеличению нагрузки на CPU.

Управление джиттером

Для управления джиттером существует несколько настроек в стриме:

  • Jitter Compensation Delay (ms) - функция компенсации сетевого Jitter, устанавливается размер буфера. Расширенное описание функции: https://forum.pstreamer.tv/viewtopic.php?t=25

  • Jitter Auto sync - активирует значение 2000 мс для протоколов на базе TCP(HTTP, HLS), для UDP-протоколов значение остаётся прежним - 500 мс.

  • Limit PCR gap (ms) - проверка насколько PCR может прыгнуть, если больше, то будет пересинхронизация.

При появлении ошибок PCR Accuracy после транскодера необходимо задать ровный битрейт с помощью stuffing у энкодируемого потока по следующему пути: «input - transcoder - Align Total Bitrate». Скорость надо задать гарантировано больше битрейта видео и звука.

System Monitor

Контроль основных параметров операционной системы.

Mosaic

Функция снятия скриншота с входного потока. Включается отдельно для каждого stream.

Если не требуется, то с целью экономии ресурсов может быть полностью отключена в разделе Settings/Server Settings.

Администрирование

В разделе Configuration/Administration/Administrators List добавляются пользователи для доступа к веб интерфейсу - встроенный HTTP сервер.

У пользователей назначаются роли:

admin - полный доступ.

restricted admin - настройки недоступны, есть возможность изменять значение pause.

viewer - доступ только в режиме просмотра.

Резервное копирование настроек

Для того, чтобы сделать резервную копию настроек, необходимо сохранить содержимое папки /opt/pss/config.

Для восстановления настроек остановите сервис и замените содержимое папки /opt/pss/config.

Подключение внешних систем мониторинга

pss-metrics — универсальный экспортёр метрик для Perfect Streamer

Один CLI-скрипт на Python 3, который забирает статистику из HTTP API веб-сервера PSS и формирует вывод для самых распространённых систем мониторинга:

  • Zabbix (UserParameter, Low-Level Discovery, zabbix_sender trapper)

  • Prometheus (текстовый формат экспозиции для textfile collector)

  • InfluxDB / Telegraf (line protocol либо JSON для exec input)

  • Универсальный JSON для произвольных скриптов и Nagios-style проверок состояния

Экспортёр — единый самодостаточный файл без сторонних зависимостей, использует только стандартную библиотеку Python 3.6+ (urllib, xml.etree, json, argparse).

Файлы

pss-metrics.py                    основной CLI (исполняемый)
userparameter_pss.conf.example    шаблон UserParameter для Zabbix

Установка

Экспортёр поставляется в /opt/pss/monitoring/pss-metrics.py. Убедитесь, что установлен Python 3.6 или новее:

# RHEL / Rocky / AlmaLinux
yum install -y python3

# Debian / Ubuntu
apt-get install -y python3

Дополнительные пакеты не требуются.

Конфигурация

По умолчанию pss-metrics подключается к http://127.0.0.1:43971 и автоматически определяет порт из /opt/pss/config/pss.json (либо /opt/pss/config/pss_default.json). Параметры можно переопределить через переменные окружения, файл /etc/pss-metrics.conf (формат ключ=значение) или флаги командной строки. Приоритет: CLI > env > файл > значения по умолчанию.

Поддерживаемые переменные:

PSS_URL          полный URL, например http://10.0.0.1:43971  (по умолчанию авто)
PSS_USER         логин веб-сервера (если включена авторизация)
PSS_PASS         пароль веб-сервера
PSS_TIMEOUT      таймаут HTTP, в секундах                    (по умолчанию 5)
PSS_CACHE_DIR    каталог кеша                                (по умолчанию /run/pss-metrics)
PSS_CACHE_TTL    время жизни кеша, в секундах                (по умолчанию 10)
PSS_CA_BUNDLE    путь к CA bundle для HTTPS
PSS_INSECURE     1 — отключить проверку TLS-сертификата
PSS_VERBOSE      1 — логировать запросы в stderr

Кеш: каждый запуск делает не более одного HTTP GET на endpoint в окне TTL. При TTL=10 с даже сотни проверок UserParameter в минуту дают ~6 HTTP-запросов в минуту к PSS.

Быстрый старт

Проверка состояния (Nagios-style exit codes):

pss-metrics.py health
# OK: total=42 running=15 stopped=27 unhealthy=0 version=1.12.2.430d

Zabbix LLD-обнаружение:

pss-metrics.py discover streams
pss-metrics.py discover inputs --running-only
pss-metrics.py discover outputs

Получение одной метрики (использовать в Zabbix UserParameter):

pss-metrics.py get summary.running
pss-metrics.py get stream.10031.bitrate
pss-metrics.py get input.10031.1.speed1
pss-metrics.py get output.10031.1.speed
pss-metrics.py get sysmon.cpu.self-usage
pss-metrics.py get server.server-version

Полный экспорт:

pss-metrics.py dump --format=json
pss-metrics.py dump --format=prometheus
pss-metrics.py dump --format=influx
pss-metrics.py dump --format=zabbix-trapper --zabbix-host=streamer-01

Пути метрик

pss-metrics get принимает путь, разделённый точками. Пустой вывод означает «значение отсутствует» (например, метрика существует только для запущенных потоков).

server.<attr>                например server.server-version, server.uptime
summary.<key>                total | running | stopped | unhealthy |
                             input_bitrate_kbps | output_bitrate_kbps
sysmon.cpu.<attr>            self-usage | total-usage | cores
sysmon.memory.<attr>         self-usage-kb | available-kb | total-kb
sysmon.netbw.<iface>.<attr>  rx-bw | tx-bw  (имя интерфейса как в XML)
stream.<id>.<attr>           любой атрибут <stream>
input.<sid>.<iid>.<attr>     любой атрибут <input>
output.<sid>.<oid>.<attr>    любой атрибут <output>

Полезные атрибуты по потокам (из /data/stream/detail):

stream:  state, state-str, bitrate, thread-usage, mpts
input:   speed1, recv-bytes, recv-packets, recv-err,
         stat-disc, stat-disc1, stat-scrambled, stat-scrambled1,
         health-state-good, health-status, check-status
output:  speed, sent-bytes, sent-packets, sent-err, uri, type

Интеграция с Zabbix

Поддерживаются два сценария — выберите подходящий вашему окружению.

  1. Статический UserParameter + LLD (Zabbix agent v1 / v2)

    Скопируйте userparameter_pss.conf.example в /etc/zabbix/zabbix_agentd.d/pss.conf, перезапустите zabbix-agent, импортируйте на сервере шаблон с LLD-прототипами, использующими ключи pss.discover. Пример привязок:

    UserParameter=pss.discover[*],/opt/pss/monitoring/pss-metrics.py discover $1
    UserParameter=pss.get[*],/opt/pss/monitoring/pss-metrics.py get $1
    UserParameter=pss.health,/opt/pss/monitoring/pss-metrics.py health
    

    В Zabbix-сервере:

    Ключ правила обнаружения:  pss.discover[streams]
    Ключи прототипов элементов: pss.get[input.{#STREAM_ID}.1.speed1]
                                pss.get[stream.{#STREAM_ID}.bitrate]
                                pss.get[summary.unhealthy]
    
  2. Trapper (push) через zabbix_sender

    Запускайте по таймеру (cron / systemd) и направляйте вывод в pipe:

    /opt/pss/monitoring/pss-metrics.py dump --format=zabbix-trapper \
        --zabbix-host="$(hostname)" \
      | zabbix_sender -z zabbix.example.com -i -
    

Интеграция с Prometheus

Два варианта.

  1. Textfile collector (рекомендуется для one-shot окружений).

    Запускайте периодический экспорт через systemd-timer или cron:

    */1 * * * * /opt/pss/monitoring/pss-metrics.py dump --format=prometheus \
        > /var/lib/node_exporter/textfile_collector/pss.prom.$$ \
        && mv /var/lib/node_exporter/textfile_collector/pss.prom.$$ \
              /var/lib/node_exporter/textfile_collector/pss.prom
    

    node_exporter отдаст файл через –collector.textfile.directory.

  2. Прямой scrape через маленькую обёртку (например socat + pss-metrics dump) либо любой сторонний HTTP-прокси на ваш выбор.

Интеграция с Telegraf / InfluxDB

Telegraf inputs.exec:

[[inputs.exec]]
  commands = ["/opt/pss/monitoring/pss-metrics.py dump --format=influx"]
  interval = "10s"
  timeout  = "5s"
  data_format = "influx"

Для JSON-парсера используйте –format=json и настройте data_format = «json» с указанием путей к полям.

HTTPS и аутентификация

Если веб-сервер PSS работает за HTTPS или защищён паролем:

PSS_URL=https://streamer.example.com:8443 \
PSS_USER=monitor PSS_PASS=secret \
pss-metrics.py health

Самоподписанные сертификаты: установите PSS_INSECURE=1 (не рекомендуется) либо укажите PSS_CA_BUNDLE=/path/to/ca.pem.

Коды возврата

pss-metrics следует Nagios-конвенции:

0  OK
1  WARNING       (например, у запущенных потоков unhealthy)
2  CRITICAL      (PSS недоступен)
3  UNKNOWN       (неверные аргументы / внутренняя ошибка)

get и dump выводят пустую строку и завершаются с кодом 0, если запрошенная сущность отсутствует — это соответствует ожиданию Zabbix, что пустое значение трактуется как «NOT_SUPPORTED», а не как сбой агента.

Диагностика

pss-metrics.py -v health        # логировать каждый HTTP-запрос в stderr
pss-metrics.py --cache-ttl=0   # обойти кеш при отладке
rm -rf /run/pss-metrics         # очистить кеш

Let’s Encrypt и certbot для HTTPS

Начиная с версии 1.9.2.340 Perfect Streamer поддерживает автоматическое обновление сертификатов Let’s Encrypt для работы HTTPS в Web Server, HTTP Server, EPG Server.

Настройка certbot для RHEL.

Ограничение:

  • Должен быть свободен tcp/80 порт и назначен белый IP адрес с публичным доменным именем.

  • Для всех https серверов используется одинаковое имя хоста. (web server, http server, epg server).

Установка certbot (https://certbot.eff.org/instructions?ws=other&os=snap) :

sudo yum install snapd
sudo systemctl enable --now snapd.socket
sudo ln -s /var/lib/snapd/snap /snap
sudo snap install certbot --classic

Настройка certbot:

sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot certonly --standalone

Проверка certbot:

sudo certbot renew --dry-run

Проверка таймера certbot:

systemctl list-timers | grep certbot

В админке Perfect Streamer включить HTTPS на серверах (Web Server, HTTP Server, EPG Server).

Создать hook скрипт (https://pstreamer.tv/distrib/scripts/cert_update.zip). И разместить его по пути:

/opt/pss/scripts/cert_update.sh

В нем, если надо, прописать доменное имя хоста, по умолчанию берется из /etc/hostname.

Сделать файл исполняемым.

chmod +x /opt/pss/scripts/cert_update.sh

Проверить запуск скрипта, не должно быть ошибок:

/opt/conf/scripts/cert_update.sh

Настройки HTTPS должны применится, изменение статуса отобразится в логах.

Добавить hook файл в certbot:

certbot renew --deploy-hook "/opt/conf/scripts/cert_update.sh"

Еще раз проверить certbot:

sudo certbot renew --dry-run

Настройка certbot для Debian/Ubuntu.

Настройка для Debian аналогична RHEL, краткое описание установки на примере Ubuntu 24.04.2 LTS.

Установка certbot:

apt install certbot
certbot certonly

Делаем скрипт исполняемым:

chmod +x /opt/pss/scripts/cert_update.sh

Запускаем скрипт:

/opt/pss/scripts/cert_update.sh

Выдаёт:

Select domain name (your domain name)

Проверяем обновились ли сертификаты:

ls -lat /opt/pss/config/cert/
total 44
-rw------- 1 root root  241 May 26 07:52 epgserver.key
-rw------- 1 root root  241 May 26 07:52 httpserver.key
-rw------- 1 root root  241 May 26 07:52 webserver.key
-rw-r--r-- 1 root root 1338 May 26 07:52 epgserver.crt
-rw-r--r-- 1 root root 1338 May 26 07:52 httpserver.crt
-rw-r--r-- 1 root root 1338 May 26 07:52 webserver.crt

Дата должна быть актуальной.

DVB-адаптеры

Perfect Streamer поддерживает работу с любыми DVB-адаптерами, установленными в системе. Осуществляется поддержка стандартов DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, ATSC. Дополнительно реализована декапсуляция T2-MI (ETSI TS 102 773) и дескремблирование BISS-1 / BISS-E.

Основное условие — корректно установленный и работающий драйвер адаптера в системе.

Раздел DVB появится только если в системе есть валидные DVB адаптеры. Переконфигурирование влет не поддерживается, требуется рестарт стримера.

Подключение адаптера

Для добавления нового DVB-адаптера необходимо перейти в соответствующий раздел и добавить адаптер:

  • Задать имя адаптера.

  • Выбрать адаптер из списка доступных в системе.

  • Выбрать режим Stream.

  • Указать тип delivery system: DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C.

  • Указать параметры настройки приёма: Частота несущей, Поляризация, Символьная частота, FEC, Модуляция, ID DVB-потока, Частота гетеродина, Гетеродин верхнего диапазона, Граница верхнего диапазона, Режим DiSEqC 1.0 и прочие параметры в зависимости от типа.

Опционально может быть включена запись EIT в БД EPG (Записывать EIT в БД EPG).

Повторить добавление для каждого адаптера, присутствующего в системе.

Сканирование DVB

Чтобы не вводить параметры приёма (частоту, поляризацию, символьную скорость, FEC, модуляцию) вручную, в Perfect Streamer встроен сканер транспондеров. Сканер обходит транспондеры выбранного спутника (DVB-S/S2) или регионального диапазона (DVB-C, DVB-T/T2), выполняет тюнинг и захват каждого, собирает таблицы PSI/SI (PAT, PMT, SDT) и формирует итоговый список мультиплексов с программами. Любой найденный мультиплекс одной кнопкой добавляется в список DVB-адаптеров.

Сканер задействует физический адаптер целиком — для запуска нужен адаптер, не используемый ни ядром операционной системы, ни одной активной записью DVB-адаптера в Perfect Streamer.

Свободные адаптеры

При открытии экрана сканирования в админке отображается список физических DVB-адаптеров системы с признаком занятости:

  • free — адаптер доступен для сканирования.

  • kernel — устройство держит другой процесс операционной системы.

  • pss-id-N — адаптер уже используется записью DVB-адаптера в Perfect Streamer с указанным идентификатором. Сканер на нём запустить нельзя, пока эта запись активна. Чтобы временно освободить адаптер, существующую запись DVB-адаптера следует приостановить (флаг Pause в её настройках).

Справочники транспондеров

Сканер ориентируется на справочники в формате Enigma2: списки спутников satellites.xml и регионов cables.xml / terrestrial.xml. Каждый файл содержит набор транспондеров для известной орбитальной позиции или регионального DVB-T/C диапазона (подробнее — на сайте проекта oe-alliance-tuxbox-common).

Файлы размещаются в каталоге sat/ относительно pss.json (стандартно — /etc/pss/sat/). Они входят в дистрибутив Perfect Streamer и загружаются при открытии экрана сканирования. При необходимости их можно обновить заменой соответствующего XML-файла.

В админке справочники представлены тремя списками:

  • Спутник — орбитальные позиции (например, Hot Bird 13.0°E, Astra 19.2°E).

  • Кабельный регион — страна или провайдер DVB-C.

  • Эфирный регион — регион DVB-T/T2.

Если нужного спутника или региона в справочнике нет, можно обновить XML или воспользоваться слепым сканированием (см. ниже).

Запуск

В диалоге сканирования последовательно задаются:

  • Свободный физический адаптер.

  • Тип delivery system: DVB-S, DVB-S2, DVB-T, DVB-T2 или DVB-C.

  • Источник:

    • для DVB-S/S2 — орбитальная позиция из списка спутников и LNB-параметры (частоты гетеродина LO1 и LO2, граница верхнего диапазона, DiSEqC-порт);

    • для DVB-C — кабельный регион;

    • для DVB-T/T2 — эфирный регион.

После нажатия Старт скан выполняется в фоне. Прогресс отображается в админке:

  • процент выполнения по числу обработанных транспондеров;

  • текущая частота и поляризация;

  • счётчики Найдено мультиплексов и Найдено программ;

  • дерево уже найденных мультиплексов с раскрытием программ.

Сканер — общий ресурс на весь стример: одновременно выполняется не более одного скана. Если запустить новый скан во время уже идущего, предыдущий автоматически отменяется. Кнопка Отмена прерывает скан и очищает накопленный список.

Длительность скана зависит от количества транспондеров в выбранном справочнике (типично — до 5 секунд на транспондер: до 2 секунд на захват сигнала и до 5 секунд на сбор PSI). Типичные значения:

  • DVB-S Hot Bird 13.0°E — около 2 минут (44 транспондера).

  • DVB-S Astra 19.2°E — около 1.5 минуты.

  • DVB-T регион Европы — менее минуты.

Результат

Результат скана отображается деревом мультиплекс → программы.

Параметры мультиплекса:

  • частота, поляризация, символьная скорость;

  • FEC, модуляция, delivery system;

  • идентификатор транспортного потока (TSID);

  • показания фронтэнда на момент окончания сбора PSI — SNR, Signal, BER;

  • счётчики pmt-total / pmt-recv — сколько PMT-таблиц объявил PAT и сколько фактически собрано за тайм-аут.

Параметры программы:

  • PNR (program_number) — идентификатор сервиса в мультиплексе;

  • Имя и Провайдер — из таблицы SDT, в UTF-8;

  • scrambled — признак скремблирования. Источник определяется в следующем порядке: бит free_CA_mode из SDT (декларация broadcaster’а) → флаги транспортного скремблирования из PMT. Если ни SDT, ни PMT за тайм-аут не пришли, значение по умолчанию — 0 («не кодирован»); реальное состояние выясняется при попытке приёма;

  • video-pid, audio-pid, pcr-pid — основные элементарные потоки сервиса.

Применение результата

Выбранный в дереве мультиплекс одной кнопкой добавляется в список DVB-адаптеров. Создаётся новая запись с параметрами из результата скана (частота, поляризация, символьная скорость, FEC, модуляция, delivery system) плюс LNB-параметры и пара adapter/device, заданные на старте скана. Имя адаптера задаётся пользователем; дополнительные параметры (BISS-ключи для скремблированных каналов, T2-MI, общий LNB и т.п.) заполняются после создания записи в её настройках.

Программы из найденных мультиплексов применяются отдельно — через создание потока (Stream) с входным demuxer-источником по PNR (см. раздел Подключение SPTS-потока к сервису DVB-мультиплекса).

Слепое сканирование

Слепой режим используется, когда:

  • нужного спутника нет в справочнике (нестандартная орбитальная позиция, локальный uplink);

  • регионального справочника DVB-T/C недостаточно или он устарел для конкретной локации;

  • нужно перепроверить участок диапазона безотносительно списка известных транспондеров.

В этом режиме сканер не обращается к справочнику, а синтезирует список транспондеров из частотной сетки. По умолчанию используются типовые диапазоны:

  • DVB-S/S2 Ku — 10700..12750 МГц, шаг 4 МГц, обе поляризации (H и V), типовые символьные скорости 22000 / 27500 / 30000 ксим/с.

  • DVB-C — 47000..862000 кГц, шаг 8000 кГц, QAM-64 и QAM-256, типовые символьные скорости 6875 / 6900 / 6952 ксим/с.

  • DVB-T/T2 — 174000..862000 кГц, шаг 8000 кГц.

Полный слепой проход Ku-диапазона занимает порядка 100 минут (несколько тысяч точек тюнинга). На практике в админке диапазон сужают вручную — минимальная/максимальная частота и шаг сетки. Например, прогон 11700..11800 МГц с шагом 4 МГц для одного LNB-band — около 5 минут.

Формат результата слепого скана идентичен обычному. Особенности:

  • поля FEC и Модуляция найденных мультиплексов фиксируются в значении AUTO — сканер не определяет их точное значение;

  • delivery system равна запрошенной (DVB-S, DVB-S2, …). Для смешанных сетей рекомендуется выполнить два прохода — отдельно DVB-S и отдельно DVB-S2.

Применение мультиплекса из слепого скана выполняется так же, как и из обычного — через кнопку добавления в список DVB-адаптеров. Поля FEC и Модуляция обычно оставляют в AUTO и при необходимости уточняют после стабильного захвата сигнала на конкретном транспондере.

Размер kernel-буфера приёма

Параметр buffer-size (целое, по умолчанию 512) задаёт размер кольцевого буфера kernel DVB demux в блоках по 65536 байт.

  • 512 (32 МБ) — рекомендованное значение по умолчанию. Покрывает полнотранспондерные сценарии DVB-S/S2 (>= 33 Мбит/с) с одним или несколькими MPTS-потребителями. Подобран по результатам тестирования на стенде с TBS-адаптером при полной загрузке транспондера.

  • 8...64 (512 КБ … 4 МБ) — допустимо для embedded-систем с ограниченной RAM или для адаптеров в режимах Scanner / Femon, где трафик невелик.

  • 0 — оставить значение по умолчанию драйвера (как правило, 8…32 КБ). Подходит только для очень слабонагруженных сценариев. На потоках более 10 Мбит/с будут потери.

При появлении в логе сообщения вида:

DVB adapter X/Y dvr buffer overflow (NN so far, KK pids);
raise 'buffer-size' or reduce pid filter

следует увеличить buffer-size или сократить число PID, проходящих через фильтр (например, отказаться от MPTS-выхода, если он не нужен).

Расход памяти: значение N даёт N × 64 КБ на адаптер kernel-памяти. При большом числе адаптеров (8 и более) это стоит учитывать (8 × 32 МБ = 256 МБ).

Подключение SPTS-потока к сервису DVB-мультиплекса

При добавлении нового SPTS телеканала в input у стрима выбираются:

  • Тип demuxer.

  • Источник DVB-адаптер.

  • Мультиплекс, созданный у DVB-адаптера, по имени адаптера.

  • PNR — выбирается из всплывающего списка выявленных в мультиплексе сервисов или вводится вручную.

Права доступа на устройства DVB

Если DVB-адаптеры в Perfect Streamer не отображаются, выполнить следующие действия:

sudo nano /etc/udev/rules.d/99-dvb-permissions.rules
SUBSYSTEM=="dvb", GROUP="video", MODE="0660"

sudo usermod -aG video pss
sudo chown -R root:video /dev/dvb/*
sudo reboot

Декапсуляция T2-MI

T2-MI (T2-Modulator Interface, ETSI TS 102 773) — формат транспортировки потоков DVB-T2 по DVB-S2 multistream. Внешний транспондер DVB-S/S2 переносит один или несколько T2-MI carrier-PID, каждый из которых инкапсулирует BBFRAME с одним или несколькими PLP (Physical Layer Pipe). После декапсуляции из BBFRAME извлекается внутренний MPEG-TS, содержащий программы и таблицы PSI/SI.

Реализация Perfect Streamer работает в multi-carrier режиме: один физический адаптер одновременно отдаёт внешний DVB-S/S2 мультиплекс и все декапсулированные T2-MI carrier (по одному на каждый carrier-PID, найденный в PMT внешнего потока).

Параметры конфигурации

t2mi-mode (Int, 0..2, по умолчанию 0) — режим декапсуляции:

  • 0 — отключено. Внешний MPEG-TS передаётся без обработки. При обнаружении дескриптора T2-MI (tag 0x51) в PMT в лог выводится одноразовая подсказка.

  • 1 — ручной режим. Декапсуляция включена постоянно. Если t2mi-pid не равен 0, на старте предсоздаётся carrier на этом PID. Дополнительные carrier продолжают обнаруживаться по PMT автоматически.

  • 2 — автоматический режим. Carrier обнаруживаются автоматически из PMT внешнего мультиплекса по всем ES, выглядящим как T2-MI (дескриптор 0x51 либо единственный ES с stream_type=0x06 на сервисе без других A/V ES). Если carrier не найдены, адаптер работает как обычный DVB-мультиплекс.

t2mi-pid (Int, 0..8191, по умолчанию 0) — PID для предсоздания carrier на старте, до прихода PMT:

  • 0 — без предсоздания. Carrier обнаруживаются по PMT (рекомендовано для автоматического режима 2).

  • 1..8191 — предсоздать carrier на этом PID. Дополнительные T2-MI ES, найденные в PMT, всё равно получают свои carrier.

В multi-carrier режиме параметр t2mi-pid не является селектором единственного carrier — каждый обнаруженный T2-MI ES получает собственный carrier с собственным декапсулятором. Параметр обеспечивает раннюю инициализацию для известного PID.

t2mi-plp (Int, 0..255, по умолчанию 0) — идентификатор PLP, извлекаемого из каждого T2-MI carrier на адаптере. Применяется ко всем carrier — индивидуальное переопределение на carrier в текущей версии не поддерживается. Если в эксплуатации разные carrier несут разные PLP, следует:

  • указать PLP, общий для всех carrier, либо

  • настроить отдельные адаптеры на разные PLP с помощью lnb-sharing.

Это идентификатор поля plp_id BBFRAME, не ISI multistream DVB-S2 (он задаётся параметром dvb-stream-id). Это разные идентификаторы на разных уровнях.

Диагностика выбора PLP:

  • Через 5 секунд после старта carrier, если для заданного PLP не получено ни одного BBFrame, но другие PLP видны — в лог пишется предупреждение со списком наблюдаемых plp_id.

t2mi-tsid (Int, -1..255, по умолчанию -1) — зарезервировано на будущее. Селектор идентификатора T2-MI потока, когда несколько T2-MI потоков делят один carrier-PID. В текущей версии игнорируется.

Композитный PNR — подключение SPTS из T2-MI

Один адаптер может предоставлять несколько логических мультиплексов:

  • carrier-id = 0 — внешний DVB-S/S2 мультиплекс (обычные A/V сервисы).

  • carrier-id = 1..N — декапсулированные T2-MI carrier (по одному на внешний T2-MI ES).

Дескремблирование BISS

Поддерживается дескремблирование зашифрованных потоков DVB по BISS-1 (режим E1) и BISS-E (режим E2). Применимо к системам передачи DVB-S, DVB-S2, DVB-T, DVB-T2.

Реализация позволяет одновременно поддерживать активными несколько дескремблеров на одном адаптере:

  • По PNR во внешнем мультиплексе (обычный сервис).

  • По plp_id для дешифрования carrier-PID T2-MI до декапсуляции (требуется для зашифрованных multistream-потоков — без этого декапсулятор отбрасывает каждый зашифрованный пакет, см. счётчик <t2mi scrambledDropped>).

EPG

Импорт EPG/XMLTV

EPG данные собираются в EPG Database из разных источников:

  • EIT из принимаемых потоков (SPTS и MPTS). Включается настройкой Stream: Extract EIT to EPG Database.

  • Импорт в формате XMLTV из разных внешних источников. Задаются в настройках Configuration/EPG/EPG Sources. Поддерживаются источники EPG в виде ссылки на web-ресурс и локально из файла, с указанием полного пути.

Время хранения событий EPG задается параметром EPG storage period (days).

Auto-clean database - Удаляются программы, для которых нет событий.

В разделе EPG отображаются источники EPG и связанные с ними данные. Для каждого канала (EPG Channels List) можно задать:

  • Channel Name - имя, которое будет использовано в экспорте на сервере XMLTV.

  • Time Zone - можно скорректировать временную зону, если она при импорте не была привязана к UTC.

  • EPG Channel Sets - привязать канал к Channel Set (см. ниже).

  • Icon - URL иконки канала (http://example.com/mychannel/myicon.png).

Генератор EIT

EIT данные из EPG Database могут быть сгенерированы в SPTS Stream. Для этого в настройке Stream надо задать EPG Source ID и выбрать EPG Channel ID. При этом будет обязательно генерироваться SDT, даже если ее нет в источнике. Задайте корректно SDT Data.

Если этот Stream используется в мультиплексоре, то Service Name можно переопределить отдельно в настройке output/muxer.

EPG-сервер (XMLTV)

Отдельный встроенный HTTP-сервер Perfect Streamer выдаёт полный XMLTV для заданного набора каналов. Эндпоинт предназначен для middleware и плееров, которые хранят программу передач локально и обновляют её редко, файлом целиком — обычно один-два раза в сутки.

Сервер и его клиенты настраиваются в разделе Configuration/EPG/EPG Server.

URL и аутентификация

Сервис обслуживается отдельным HTTP-сервером epg-server (не тем, что /data/*). По умолчанию он слушает порты 10444 (HTTP) и 10445 (HTTPS); порты и SSL настраиваются в разделе /config/epg-server.

Маршруты:

URL

Content-Type

Поведение

GET /xmltv

text/xml

При Accept-Encoding: gzip ответ сжимается на лету (Content-Encoding: gzip), иначе отдаётся как обычный XML.

GET /xmltv.gz

application/octet-stream

Всегда возвращает gzip-поток с Content-Disposition: inline; filename="xmltv.xml.gz" — удобно сохранять как файл.

Поддерживаются три способа аутентификации:

  • HTTP Digest (предпочтительно) — учётка из /config/epg-server/login.

  • Параметры в URL?l=<login>&p=<password> (синонимы: login=…, password=…).

  • Loopback — запрос с 127.0.0.1 обрабатывается анонимно. Удобно для скриптов, развёрнутых на той же машине.

Предупреждение

Логин и пароль в URL попадают в access-логи reverse-proxy и в историю браузера. Для публичной раздачи XMLTV используйте HTTP Digest либо принимайте запросы только с приватных адресов.

Доступ по channel-set

Каждая учётка epg-server/login привязана к одному channel-set из /config/epg-channel-set. EPG в ответе содержит только те каналы, которые входят в указанный набор. Это позволяет одной инсталляции PSS выдавать разный XMLTV разным операторам/middleware’ам.

Базовая настройка в UI:

  1. В Configuration/EPG/EPG Channel Sets создайте группу каналов и назначьте в неё нужные каналы у источников EPG.

  2. В Configuration/EPG/EPG Server Clients заведите учётную запись и привяжите к ней созданную группу. Без привязки channel-set клиенту отдаётся пустой XMLTV.

Дополнительные ограничения для login:

  • ip-addr — если задан и не wildcard, запрос с другого IP получит 403 Forbidden.

  • limit-day — Unix epoch-сек, после которого учётка перестаёт обслуживаться (403 Forbidden). Удобно для абонементной модели.

  • pause — временно отключить login без удаления.

Формат ответа

Тело ответа — XMLTV-документ с корнем <tv>. Структура соответствует общепринятой схеме XMLTV DTD:

<?xml version="1.0" encoding="utf-8"?>
<tv source-info-name="..." source-info-url="...">
  <channel id="ru.first">
    <display-name lang="ru">Первый</display-name>
    <icon src="https://.../first.png"/>
  </channel>
  ...
  <programme start="20260504060000 +0300"
             stop ="20260504070000 +0300"
             channel="ru.first">
    <title lang="ru">Утренние новости</title>
    <desc  lang="ru">Обзор событий за сутки</desc>
    <rating system="RU"><value>12+</value></rating>
  </programme>
  ...
</tv>

Заметки по полям:

  • Атрибуты source-info-name и source-info-url корня <tv> заполняются из полей EPG Source Name и EPG Source URL в Configuration/EPG/EPG Server.

  • Атрибуты start и stop оформлены в формате YYYYMMDDhhmmss ±zone (часовой пояс берётся из поля time_zone канала).

  • В <programme> могут быть несколько <title>/<desc> для разных языков. Атрибут lang пустой, если в исходных данных EPG идентификатор языка не сопоставился со словарём (запись всё равно попадёт в выдачу).

  • Каналы с конфликтующим channel_id (если один и тот же id пришёл из разных источников) показываются один раз, остальные источники пропускаются с предупреждением в логе сервера.

  • В выдачу попадают только события с stop_time >= now.

HTTP-заголовки

Сервер всегда отправляет:

Cache-Control: no-cache, no-store, must-revalidate
Pragma:        no-cache
Expires:       0
Connection:    close

Для /xmltv дополнительно — Content-Encoding: gzip при Accept-Encoding: gzip в запросе. Для /xmltv.gzContent-Disposition: inline; filename="xmltv.xml.gz".

Запрет клиентского кеша сделан намеренно: XMLTV меняется при каждом импорте EIT либо обновлении внешних XMLTV-источников, и плеер не должен держать устаревшие данные у себя бессрочно. Edge-кеш (nginx) при этом вполне допустим — см. раздел про производительность ниже.

Серверный кеш и его сброс

Готовый XMLTV кешируется в памяти процесса PSS:

  • По одной записи на каждый channel-set; внутри хранятся обе версии тела (raw и gzip) — повторные запросы с Accept-Encoding: gzip или /xmltv.gz не пересжимают данные.

  • Запись помечается счётчиком update-time. Любое обновление EPG (импорт EIT, обновление XMLTV-источника) увеличивает счётчик, и при следующем запросе кеш перестраивается.

Принудительный сброс кеша:

POST /xmltv/reset-cache

Маршрут обслуживается на admin-сервере (порт 43971/43981), не на epg-server. Тело — пустое; ответ — 200 OK с JSON-конвертом.

HTTP-коды ответа

Код

Условие

200 OK

Запрос обработан. Тело — XMLTV-документ (возможно, пустой <tv></tv> при временном сбое БД).

401 Unauthorized

Ни Digest, ни параметры l/p не прошли проверку (для не loopback-запросов).

403 Forbidden

Login существует, но запрос не с разрешённого IP, либо истёк limit-day.

404 Not Found

Любой URL, кроме /xmltv и /xmltv.gz.

405 Method Not Allowed

Метод не GET.

Тело ошибки — JSON-конверт фиксированного формата:

{"status": 401, "message": "Unauthorized"}

Производительность и масштабирование

Серверный кеш

Серверный кеш обслуживает повторные обращения к одному channel-set без обращения к SQLite — копированием готового тела.

Построение XMLTV «с нуля» (cache miss) дороже: для каждого канала делается отдельный SELECT по channel_name, для каждого события — по event_text и event_rating. Время построения ориентировочно:

Размер выдачи

Cache hit

Cache miss (build)

100 каналов / сутки

десятки мс

~0.5–1 с

500 каналов / сутки

~50 мс

2–5 с

1000+ каналов / неделя

~100–300 мс

5–15 с

Для большинства middleware приемлемо запрашивать XMLTV раз в несколько часов или раз в сутки.

Когда нужен внешний reverse-proxy (nginx)

В отличие от /data/epg/channel (короткие JSON-ответы), XMLTV — это один большой документ на channel-set, идеально подходящий для edge-кеша:

  • Десятки и сотни клиентов на один channel-set — внутреннего кеша PSS обычно достаточно, если они опрашивают XMLTV раз в час–сутки.

  • Тысячи клиентов одновременно — рекомендуется reverse-proxy с кешем. Выдача XMLTV-файла на сотни/тысячи запросов — это в первую очередь сетевая нагрузка (сотни КБ — единицы МБ на ответ), которую стоит снимать с PSS.

  • Географически распределённая раздача — без CDN/edge-кеша не обойтись независимо от числа клиентов.

PSS отдаёт Cache-Control: no-cache, поэтому в nginx нужно явно сказать игнорировать заголовок upstream’а и держать собственный TTL.

Пример конфигурации nginx

# /etc/nginx/conf.d/pss-xmltv.conf

proxy_cache_path /var/cache/nginx/pss-xmltv
                 levels=1:2
                 keys_zone=pss_xmltv:8m
                 max_size=4g
                 inactive=2h
                 use_temp_path=off;

upstream pss_epg {
    server 127.0.0.1:10444;
    keepalive 16;
}

server {
    listen 80;
    # listen 443 ssl http2;     # SSL termination разумно держать здесь
    server_name epg-files.example.com;

    # Не включаем gzip on: /xmltv.gz уже сжат, /xmltv получит
    # gzip-encoding от PSS, повторное сжатие бесполезно.

    location ~ ^/xmltv(\.gz)?$ {
        proxy_pass http://pss_epg;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # PSS отдаёт no-cache; кешируем на edge принудительно.
        proxy_ignore_headers Cache-Control Expires Set-Cookie;
        proxy_hide_header   Cache-Control;
        proxy_hide_header   Pragma;
        proxy_hide_header   Expires;

        # Ключ кеша = весь URL включая query (login/password в /xmltv?l=...&p=...)
        # дают разные ключи для разных учёток с разным channel-set.
        proxy_cache_key     "$scheme$host$request_uri";

        proxy_cache         pss_xmltv;
        proxy_cache_valid   200      30m;       # XMLTV меняется не часто
        proxy_cache_valid   401 403  1m;
        proxy_cache_lock           on;          # коалесцируем cache miss
        proxy_cache_lock_timeout   60s;         # build XMLTV может занимать секунды
        proxy_cache_use_stale      error timeout updating
                                   http_500 http_502 http_503;

        # Большой буфер: XMLTV для крупного channel-set может
        # достигать нескольких мегабайт.
        proxy_buffering      on;
        proxy_buffers        16 256k;
        proxy_buffer_size    256k;
        proxy_busy_buffers_size 1m;

        # Клиенту разрешим закешировать на короткий срок.
        add_header Cache-Control "public, max-age=600";
        add_header X-Cache-Status $upstream_cache_status always;
    }
}

Пояснения и рекомендации

  • TTL ``proxy_cache_valid 200 30m`` — XMLTV редко меняется чаще получаса. Если синхронизация с источниками идёт раз в час и больше, можно поднимать до 1 часа и более; если важна свежесть после POST /xmltv/reset-cache — снижайте.

  • ``proxy_cache_lock_timeout 60s`` — увеличен по сравнению с /data/epg/channel (где обычно 5 секунд), потому что построение XMLTV для большого channel-set занимает дольше.

  • Отдельный ``keys_zone`` — даже на крупной инсталляции уникальных ключей XMLTV единицы (по числу учёток × channel-set), 8 МБ хватит с запасом. max_size выбирается по объёму XMLTV, а не по числу ключей.

  • gzip на стороне nginx не нужен: для /xmltv.gz ответ уже сжат, для /xmltv PSS сам ответит gzip-encoded при наличии Accept-Encoding: gzip.

  • HTTPS-терминация на nginx даёт лучшую производительность при многих одновременных TLS-рукопожатиях.

Связанные эндпоинты

  • POST /xmltv/reset-cache — принудительный сброс серверного кеша XMLTV (на admin-сервере 43971/43981).

  • POST /data/epg/update?s=<src_id> — принудительное обновление внешнего XMLTV-источника; после успешного обновления серверный кеш XMLTV сбрасывается автоматически.

  • GET /data/epg/channel?… — выдача EPG за сутки по одному каналу в JSON; см. отдельный раздел.

Полный перечень и подробное описание HTTP API приведены в manual/http_data_api.txt.

EPG для OTT middleware

Сервер выдаёт данные программы передач (EPG) за выбранные сутки по одному каналу в формате JSON. Эндпоинт предназначен для бэкенда OTT middleware, которое агрегирует расписание из Perfect Streamer для построения программы передач у конечного клиента.

URL и аутентификация

Эндпоинт обслуживается встроенным admin-сервером. По умолчанию он доступен по портам 43971 (HTTP) и 43981 (HTTPS); порты настраиваются в разделе Settings/Server Settings.

GET /data/epg/channel?src=<src_id>&ch=<channel_id>&lang=<lang>&t=<time>

Аутентификация — HTTP Digest, как у остальных /data/*. Для middleware достаточно учётной записи с ролью viewer (только чтение).

Примечание

Запросы с loopback-адреса (127.0.0.1) выполняются без проверки HTTP Digest — сервер считает их анонимными. Это удобно для локальных скриптов и health-check’ов middleware, развёрнутого на той же машине, что и Perfect Streamer; для удалённых обращений учётные данные обязательны.

Параметры запроса

Параметр

Тип

Обязат.

По умолчанию

Описание

src

целое без знака

нет

0

Источник EPG. 0 — данные, импортированные из MPEG-TS EIT входных потоков. 1, 2, — идентификатор записи из /config/epg/epg-source (внешний XMLTV-источник).

ch

строка

да

Идентификатор канала из базы EPG: значение поля channel_id таблицы channel. Список доступных идентификаторов можно получить SQL-запросом через POST /data/epg/sql.

lang

целое или ISO 639

нет

системный язык по умолчанию

0 — системный язык по умолчанию; целое > 0 — внутренний идентификатор языка (см. GET /schema/lang); строка — двух- или трёхбуквенный код ISO 639, например eng, rus, fra.

t

целое без знака (Unix epoch, сек)

нет

текущее время сервера

Любая точка внутри интересующих суток. Сервер выдаёт события за UTC-сутки, которым принадлежит t: интервал [t / 86400 · 86400, (t / 86400 + 1) · 86400). Для получения данных за «следующие сутки» достаточно прибавить 86400 к текущему времени.

Примечание

Сутки берутся в UTC, а не в локальном часовом поясе. Если middleware формирует расписание по локальному календарному дню, граница UTC-суток может не совпадать с локальной полночью; в таком случае нужно сделать два запроса (за смежные UTC-сутки) и склеить результаты по полю start.

Формат ответа

  • Content-Type: application/json.

  • HTTP-заголовки запрещают кеширование на стороне клиента и промежуточных прокси:

    Cache-Control: no-cache, no-store, must-revalidate
    Pragma: no-cache
    Expires: 0
    
  • Тело ответа — JSON со списком событий за сутки:

{
  "event": [
    {"start": 1715000000, "end": 1715003400, "title": "Утренние новости", "desc": "Обзор событий за сутки"},
    {"start": 1715003400, "end": 1715007000, "title": "Прогноз погоды",   "desc": ""}
  ]
}

Поля события:

  • start, end — моменты начала и окончания передачи в Unix epoch (сек), UTC.

  • title — заголовок передачи на выбранном языке. Если для события на запрошенном языке заголовка нет, сервер берёт запись на системном языке по умолчанию, затем — на любом другом доступном.

  • desc — расширенное описание. Может быть пустой строкой, если в базе для события не было отдельного описания.

Особенности выдачи:

  • В выдачу не попадают события с пустым заголовком и без описания, а также события с некорректными метками времени.

  • Дубликаты по start отсекаются: для одного и того же момента начала возвращается одна запись с лучшим приоритетом языка (запрошенный → системный default → остальные).

  • Порядок событий в массиве не гарантируется — при необходимости middleware сортирует список по полю start самостоятельно.

  • Если канал не найден, источник не существует или за выбранные сутки нет событий, сервер возвращает 200 OK с пустым массивом {"event":[]} либо с пустым телом (в редком случае отсутствия источника). Middleware должен корректно обрабатывать оба варианта.

Кеширование на сервере

Готовый JSON кешируется сервером по ключу (channel_id, дата UTC, язык), поэтому повторные запросы за те же сутки одного канала обрабатываются без обращения к базе данных. От middleware никаких действий по управлению кешем не требуется.

Сброс кеша выполняется автоматически:

  • при поступлении новых событий из MPEG-TS EIT входных потоков (src=0);

  • при успешном обновлении внешнего XMLTV-источника (src > 0 — плановое обновление либо принудительное через POST /data/epg/update?s=<src_id>);

  • при выходе суток за окно хранения EPG.

Принудительный сброс кеша отдельным эндпоинтом не предусмотрен и не требуется.

HTTP-коды ответа

Код

Условие

200 OK

Запрос обработан. Тело — JSON со списком событий (возможно, пустым).

400 Bad Request

Параметр ch не указан или пуст; либо src, t не разбираются как беззнаковое целое; либо числовой lang указывает на несуществующий идентификатор языка.

401 Unauthorized

Отсутствует либо некорректна HTTP Digest аутентификация (для запросов не с loopback-адреса).

Прочие ситуации (неизвестный src, отсутствие канала, отсутствие событий за сутки) не приводят к 4xx — middleware получает 200 OK с пустым массивом {"event":[]}.

Тело ответа при ошибке — JSON-конверт фиксированного формата:

{"status": 400, "message": "Bad Request"}

Поле status дублирует HTTP-код, поле message содержит уточнённую причину ошибки на английском (либо стандартный текст HTTP-статуса, если дополнительной информации нет). Content-Type ответа об ошибке — application/json.

Пример

curl -u middleware:secret --digest \
  'http://pss.example.com:43971/data/epg/channel?src=0&ch=12.0.1&lang=rus&t=1715000000'

Пример ответа:

{
  "event": [
    {"start": 1715000000, "end": 1715003400, "title": "Утренние новости", "desc": "Обзор событий за сутки"},
    {"start": 1715003400, "end": 1715007000, "title": "Прогноз погоды",   "desc": ""}
  ]
}

Производительность и масштабирование

Серверный кеш Perfect Streamer

Внутри процесса PSS реализован in-memory LRU-кеш ответов с ключом (channel_id, дата UTC, язык) и хард-капом 1024 записи на источник EPG. При типовой нагрузке (десятки–сотни каналов × 1–3 языка × keep-day дней) все актуальные записи помещаются в кеш целиком; ответы на повторные запросы обрабатываются без обращения к SQLite.

Порядок величин (debug-сборка, локальный loopback, без HTTPS):

Сценарий

Задержка (одиночный запрос)

Пропускная способность (P=8)

Cache hit

~0.3 мс

~1100 запросов/с

Cache miss (SQL + JSON)

~1.0–1.5 мс

~1000 запросов/с

В release-сборке и без отладочного логирования цифры примерно в 2–3 раза лучше. Bandwidth — около 14 КБ на ответ для типового канала за сутки.

Когда нужен внешний reverse-proxy (nginx)

Серверный кеш ускоряет повторные обращения к одному и тому же (channel, день, язык), но каждый запрос всё равно проходит через встроенный HTTP-сервер PSS и тратит поток из его пула. На большом числе клиентов имеет смысл вынести кеширование на edge:

  • до ~1 000 онлайн-клиентов — внутреннего кеша обычно достаточно, reverse-proxy не обязателен.

  • десятки тысяч и больше — рекомендуется reverse-proxy с кешем (например, nginx). Edge-кеш отрабатывает 99 % запросов без участия PSS, амортизирует пики (старт middleware, массовое обновление плеера) и даёт возможность поставить SSL-терминацию на отдельный узел.

  • географически распределённая раздача — внешний CDN/прокси нужен ещё до подсчёта числа клиентов.

PSS отдаёт собственный заголовок Cache-Control: no-cache, no-store, must-revalidate, чтобы конечные клиенты не закешировали EPG надолго. Reverse-proxy при этом может (и должен) кешировать ответ самостоятельно — ниже показано, как явно сказать nginx игнорировать Cache-Control upstream-а и держать собственный TTL.

Пример конфигурации nginx

Минимальный конфиг для edge-кеша EPG, рассчитанный на десятки тысяч клиентов с интервалом опроса 1–5 минут:

# /etc/nginx/conf.d/pss-epg.conf

proxy_cache_path /var/cache/nginx/pss-epg
                 levels=1:2
                 keys_zone=pss_epg:32m
                 max_size=2g
                 inactive=30m
                 use_temp_path=off;

upstream pss_admin {
    server 127.0.0.1:43971;
    keepalive 64;
}

server {
    listen 80;
    # listen 443 ssl http2;  # рекомендовано: SSL termination здесь
    server_name epg.example.com;

    # gzip помогает: типовой EPG-JSON жмётся ~5–8x.
    gzip on;
    gzip_types application/json;
    gzip_min_length 512;
    gzip_proxied any;

    location = /data/epg/channel {
        proxy_pass http://pss_admin;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # PSS отдаёт no-cache; кешируем на edge принудительно.
        proxy_ignore_headers Cache-Control Expires Set-Cookie;
        proxy_hide_header   Cache-Control;
        proxy_hide_header   Pragma;
        proxy_hide_header   Expires;

        # Ключ кеша = весь URL с query string. Параметры src/ch/lang/t
        # уже определяют уникальность ответа.
        proxy_cache_key     "$scheme$host$request_uri";

        proxy_cache         pss_epg;
        proxy_cache_valid   200 60s;          # время устаревания
        proxy_cache_valid   400 404 10s;
        proxy_cache_lock           on;        # коалесцируем cache miss
        proxy_cache_lock_timeout   5s;
        proxy_cache_use_stale      error timeout updating
                                   http_500 http_502 http_503;

        # Отдадим клиенту результат в JSON, но с собственным TTL
        # (плеер пересмотрит EPG не раньше этого срока).
        add_header Cache-Control "public, max-age=60";
        add_header X-Cache-Status $upstream_cache_status always;
    }
}

Пояснения и рекомендации

  • TTL ``proxy_cache_valid 200 60s`` — компромисс между свежестью EPG и нагрузкой на upstream. Программа передач не меняется в реальном времени, поэтому 30–300 секунд выглядят разумно. После импорта новых событий PSS сбрасывает свой кеш мгновенно, а edge-кеш догонит за следующий TTL.

  • ``proxy_cache_lock on`` обязательно для большого числа клиентов: при cache miss он коалесцирует параллельные запросы к одному ключу в один upstream-запрос, защищая SQLite от пиковых BUSY под нагрузкой.

  • ``keys_zone`` и ``max_size`` подбираются по числу (канал × сутки × язык): 32 МБ keys_zone хватит на сотни тысяч ключей; 2 ГБ max_size — на месяц истории по сотням каналов с запасом.

  • gzip существенно режет трафик: ответы хорошо сжимаются (повторяющиеся ключи JSON, кириллица в UTF-8).

  • ``X-Cache-Status`` в ответе позволяет на стороне middleware видеть HIT/MISS/EXPIRED и оценить эффективность кеша.

  • Если nginx и PSS живут на одной машине — admin-сервер не требует HTTP Digest для loopback, поэтому upstream-блок можно оставить без proxy_set_header Authorization . Для разнесения по сетям заведите отдельную учётку viewer и добавьте Digest-аутентификацию в proxy_pass.

  • HTTPS разумно терминировать на nginx: PSS поддерживает HTTPS напрямую, но edge-сервер обычно эффективнее в обработке TLS-handshakes при тысячах одновременных клиентов.

Связанные эндпоинты

  • POST /data/epg/sql?s=<src_id> — произвольный SQL-запрос к базе EPG (в частности, для получения списка channel_id).

  • POST /data/epg/update?s=<src_id> — принудительное обновление внешнего XMLTV-источника.

Полный перечень и подробное описание HTTP API приведены в manual/http_data_api.txt.

Оптимизация работы программы

Если при большом количестве stream возникли проблемы с большой нагрузкой CPU или нехватка памяти, то можно провести оптимизацию настроек.

Отключить функции MPEG-TS фильтрации и обработки, если в этом нет необходимости. По умолчанию у stream включена функция Clean All Unnecessary Data, отключить если в потоке нет нежелательных данных. При полном отключении этих функций в Report пропадет раздел Original Media Information.

Полностью отключить и изменить настройки Mosaic. Полностью отключить можно в настройках сервера. Можно отключить индивидуально для каждого stream, или изменить интервал обновления настройкой Check Interval.

Ошибки queue overload для базы данных DBStat и DBEPG

Возникают при недостатке быстродействия баз данных - используется медленный диск или система слишком перегружена.

Место баз данных задается параметром data-dir файла конфигурации pss.properties

Возможные решения проблемы:

  1. Перенос файлов баз данных в /tmp. Будет использована память системы, требует оценки свободной памяти и настройки времени хранения статистики (см настройки сервера). При рестарте системы данные будут потеряны.

  2. Уменьшить детализацию статистики - см параметр dbstat-detail. По умолчанию 5 секунд. Можно увеличить до 20.

  3. Разместить базу данных EPG в памяти - задать параметр dbepg-memory=true.

Транскодеры

Транскодеры реализованы как отдельные исполняемые бинарные файлы, которые запускаются из pstreamer как отдельные процессы.

Поддерживаются конфигурации типа 1toN, т.е. с одного decoder можно получить несколько потоков с разными настройками encoder.

В исходном потоке необходимо наличие видео и аудио, варианты без видео или без звука не поддерживаются.

Реализованы кодеки:

  • Video SW decoder: mpeg2, h.264, hevc (h.265)

  • Video NW decoder: mpeg2, h.264, hevc (h.265)

  • Video SW encoder: mpeg2, h.264, hevc (h.265)

  • Video NW encoder: h.264, hevc (h.265)

Поддерживается interlaced stream на входе и выходе.

Для H.264 и HEVC decoder поддерживается формат interlace alternate (два отдельных поля в потоке). Он преобразуется в interlace interleaved.

Для HEVC decoder поддерживается профиль Main10 с bt.709 (SDR) и bt.2020 (HDR). Encoder для HEVC всегда использует профиль Main с bt.709.

Для H.264 и HEVC decoder поддерживается формат VFR (Variable Frame Rate), он преобразуется в постоянный frame rate.

  • Audio decoder - mpeg (layer 1,2,3), aac, ac3

  • Audio encoder - mpeg (layer 2), aac

Есть режим транскодирования Video Passthrough - без транскодирования видео, транскодируется только звук. Используется транскодер SW.

Примечание

Для транскодирования необходимо сконфигурировать два или более стрима, с output (decoder) и с input (encoder).

Для настройки инстанса транскодера необходимо:

  • Источник - добавить в stream output transcoder (decoder). В настройках выбрать тип - SW, NV или Video Passthrough.

  • Выходной поток - добавить в stream input transcoder (encoder). В настройках выбрать источник-decoder.

  • Повторить, если надо несколько выходных потоков на один decoder.

Настройки output transcoder (decoder)

  • Convert colors to BT.709 - конвертация форматов SD BT.470-2 (PAL) и SMPTE 170M (NTSC) в BT.709

  • Trace - включить для диагностики подробный лог транскодера.

Для корректной работы транскодера требуется, чтобы исходный поток соответствовал определенным требованиям и в некоторых случаях это можно исправить. Эти настройки не конвертируют поток, они работают как подсказки для корректной работы транскодера.

Для коррекции данных входного потока имеются настройки:

  • Fix PAR - исправить Pixel Aspect Ratio. Задается как дробное число в формате N/D. Например, для Wide SD это 16/9.

  • Fix Framerate - явно указать framerate. В некоторых потоках framerate в SPS может отсутствовать и в логе транскодера будет соотв. ошибка. В этих случаях надо явно указать framerate. Задается как дробное число в формате N/D.

Примеры значений framerate:

  • PAL - 25/1

  • NTSC - 30/1 или 30000/1001

  • Cinema - 24/1 или 24000/1001

Настройки input transcoder (encoder)

  • Encoder Type - кодек видео.

  • Align Total Bitrate - битрейт стаффинга потока (заполнение null пакетами). Важно это задать, если поток будет использоваться для DVB вещания. Битрейт должен быть гарантированно больше битрейта видео и всех звуковых дорожек.

  • Video Profile - для H.264 можно выбрать профиль кодирования.

  • Video Bitrate - битрейт видео потока в kbps. Кодирование всегда использует режим CBR. Суммарный битрейт будет больше из-за звуковых дорожек.

  • Speed Preset - предустановки опций кодирования, значения от 1 до 7. Значение меньше - больше качество и больше требуемых ресурсов. По умолчанию 4.

  • GOP Interval - интервал в фреймах для GOP (этот параметр соотв. Key Frame Interval). По умолчанию 25 (1 секунда для 25p), рекомендуемое значение, если проигрыватели начинают воспроизведение с произвольной точки потока.

  • BFrame - включить для повышения качества. Рекомендуемое значение 3.

  • Lookahead - включить для повышения качества. Рекомендуемое значение 20–50 фреймов.

  • Resize - изменение размера картинки.

  • Deinterlace - преобразует interlace в progressive.

Вставка crop (пустые поля по краям картинки) не поддерживается. Задание произвольного размера картинки не поддерживается, так как это может привести к искажению пропорций.

Для resize доступны опции:

  • Пропорционально уменьшить размер на 2 и 4.

  • Сделать формат Wide SD 16:9, будет задан нужный Aspect Ratio.

  • Upscale SD->HD. Применяется для источника формата SD PAL/NTSC. Interlace не поддерживается, применяется deinterlace при необходимости.

  • Задать ширину. Высота будет пропорционально пересчитана.

  • Задать высоту. Ширина будет пропорционально пересчитана.

Некоторые параметры могут оказаться несовместимыми с заданным транскодером. Ошибки можно увидеть в логах транскодера.

Обработка звука

По умолчанию все звуковые дорожки передаются со входа на выход без обработки. Ненужные дорожки можно убрать настройкой PID-фильтров в stream.

Если надо транскодировать звук, то это можно настроить правилами отдельно для каждого звукового кодека. Опция skip - убрать звуковую дорожку с этим кодеком.

Если в выходном потоке не окажется звуковых дорожек, то будет ошибка, см. логи транскодера.

Формирование PCR и TR 101 290

MPEG-TS мультиплексор формирует новый PCR. Если правильно задать Align Total Bitrate (более чем сумма битрейтов видео и звука), то PCR должен пройти проверку по стандарту TR 101 290.

Статус работы транскодеров

При наличии проблем в работе транскодера (нет потока с encoder) надо смотреть логи в разделе Transcoders, тут отображается список инстансов (каждая строка - отдельный инстанс, decoder + N encoders) и, при клике на нужный инстанс, открывается диалог статуса логов. Отображается текущий лог и лог от предыдущего запуска. Для подробного лога надо включить trace в настройках output (decoder).