Skip to content

Сессии просмотра

media.play.sessions

Сессия просмотра — состояние, которое Sapsan ведёт для обращения зрителя к стриму. Она связывает запросы плеера с авторизацией и учитывает активность, переданные байты и использование архива. Это позволяет наблюдать просмотр целиком, хотя доставка может состоять из множества отдельных HTTP-запросов.

Например, HLS-плеер запрашивает мастер-плейлист, варианты качеств и последовательность сегментов. Адаптация качества и новые HTTP-соединения сами по себе не должны превращать один просмотр в сотни зрителей. Sapsan находит существующую сессию и относит последующие запросы к ней.

Как объединяются HTTP-запросы

Для обычного HTTP-проигрывания идентичность складывается из следующих данных:

  • Имя стрима — какой медиаресурс запрошен.
  • Вид обращения — просмотр отделён от публикации.
  • IP-адрес клиента — с учётом настроенных доверенных прокси.
  • Токен доступа — для проверенного JWT-билета используется идентификатор его выдачи jti.

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

Идентификатор сессии назначает сервер. Обычному HTTP-клиенту не требуется придумывать собственный UUID сессии или сохранять специальную cookie. User-Agent записывается в статистику, но не входит в перечисленный ключ объединения.

Токен должен доходить до связанных запросов. В HTTP-проигрывании параметр ?token= имеет приоритет перед Authorization: Bearer …. Передача и выдача JWT описаны в токенах доступа.

Такой учёт зависит от выбранной идентичности, а не от физического устройства. Несколько плееров с одним IP, одним токеном и одним стримом могут попасть в общую сессию. Смена IP или идентификатора токена может создать новую. Для раздельного учёта выдавайте отдельные билеты и правильно настройте доверенные прокси.

Жизненный цикл и статистика

Запросы и выдаваемые данные поддерживают активность сессии. Если активности нет 60 секунд, сессия истекает; очистка выполняется периодически, поэтому закрытие не обязано совпадать с моментом закрытия вкладки браузера.

Открытая запись сессии и активный зритель — разные показатели. Текущая реализация переводит сессию в активные после выдачи 10 КиБ данных. Один запрос небольшого плейлиста поэтому не обязательно увеличит число активных зрителей. Порог измеряет доставленные байты и не подтверждает, что человек посмотрел изображение. В журнал закрытых сессий попадают сессии, достигшие активности.

Учитываются следующие сведения:

  • Время — открытие, последняя активность, длительность и закрытие.
  • Доставка — протокол и количество переданных байтов.
  • Клиент — IP, User-Agent и идентификатор пользователя, если он предоставлен авторизацией.
  • Архив — признак обращения к DVR. После перемотки он остаётся установленным и при возвращении к прямому эфиру.

Переход live → архив → live сам по себе не создаёт три просмотра. Аналогично, число запросов сегментов и число сетевых соединений не следует складывать как число зрителей.

Качество доставки SRT

Сессия, открытая по SRT, несёт протокольный срез доставки — актуальные счётчики соединения в ответе активных сессий:

Поле Что означает
rtt_ms, rtt_max_ms текущий RTT и максимум за жизнь сессии
send_buffer_packets пакеты в буфере отправки — ранний признак затора у зрителя
packets_sent отправленные пакеты — знаменатель доли потерь
lost_packets потери: разрывы исходящей последовательности пакетов
drop_too_late_packets из потерь — пакеты, пропущенные по истечении срока доставки: латентности не хватило на восстановление
drop_requests из потерь — пакеты, сброшенные по команде получателя: зритель сообщил, что диапазон ему уже не нужен
retransmitted_packets повторно отправленные пакеты — ответы на NAK-отчёты зрителя
naks_received NAK-отчёты зрителя: сколько раз он сообщал о потерях
health вердикт здоровья соединения: ok, degraded или bad

Значения активной сессии обновляются: узел периодически фиксирует счётчики в запись сессии. На закрытии в нодную запись попадают финальные тоталы и вердикт последнего окна.

Вердикт health описывает окно доставки — последнюю минуту соединения, а не всю его жизнь: доля потерь и текущий RTT против удвоенной латентности выдачи. Прошлые провалы остаются в прошлом: окно стало чистым — вердикт возвращается к ok, а «когда сыпало» читается историей среза (см. минутную историю). Обрыв соединения вердикт не портит: чистая сессия, закрытая замолчавшим зрителем, остаётся с вердиктом последнего окна, а сам уход описывает причина закрытия.

Сессии остальных протоколов секции srt не имеют вовсе — отсутствие поля не означает нулевых потерь.

Минутная история сессии

Сессии с владельцем user_id — из карты клиентов выдачи или тега владельца — пишутся в стор метрик central минутными точками: график сессии строится тем же механизмом, что и графики входа стрима. Каждая серия несёт метки name (стрим), user_id и session:

Серия Что показывает
stream_play_srt_session_rtt_seconds, ..._rtt_max_seconds RTT — текущий и максимум
stream_play_srt_session_send_buffer_packets буфер отправки, пакеты
stream_play_srt_session_packets_sent_total, ..._bytes_total отправленные пакеты и байты
stream_play_srt_session_lost_packets_total потери
stream_play_srt_session_drop_too_late_packets_total, ..._drop_requests_total потери по причинам: с истёкшим сроком доставки и сброшенные получателем
stream_play_srt_session_retransmitted_packets_total, ..._naks_received_total ретрансмиты и NAK-отчёты

Серии читаются во встроенном Prometheus-сервере central тем же range-запросом, что и серии стрима. Глубина детализации — окно стора, по умолчанию шесть часов; рестарт плоскости метрик обнуляет историю. Глубже окна доступны общие итоги закрытой записи — байты, длительность, причина закрытия. Анонимные сессии серий не создают: без владельца графиков нет, а не нули.

Авторизация сессии

Основной рекомендуемый способ допуска — JWT-билет. Стример проверяет его локально, а состояние сессии связывает запросы и их трафик. Наличие уже открытой сессии не отменяет проверки JWT в следующем HTTP-запросе.

Для старых интеграций с внешним auth-бэкендом разрешение сохраняется на определённое время. В течение этого окна последующие запросы используют принятое решение; после истечения окна требуется новая авторизация. auth_duration, по умолчанию 180 секунд, относится к сроку решения авторизации, а не к 60-секундному таймауту бездействия.

Проверка следующих HTTP-запросов и прекращение уже открытого непрерывного ответа — разные операции. Нельзя считать, что изменение решения авторизации мгновенно обрывает любую уже идущую выдачу MPEG-TS только благодаря наличию сессии.

Чем отличается проверка ссылки на nginx-эдже

Проверка подписанной ссылки отвечает, допустим ли конкретный запрос. Например, модуль secure_link nginx проверяет подлинность ссылки и её срок действия. Учёт просмотра требует состояния, связывающего отдельные обращения плеера.

Задача Только проверка ссылки Учёт сессии Sapsan
Допустить запрос к сегменту Проверяет предъявленную ссылку Проверяет доступ и связывает запрос с просмотром.
Посчитать просмотр Отдельные запросы сами по себе не задают границы просмотра Ведёт активность и жизненный цикл сессии.
Учесть трафик Доступны данные каждого запроса Байты накапливаются в сессии.
Разобрать перемотку и протокол Требуется дополнительная агрегация Эти сведения входят в запись сессии.
Собрать данные нескольких эджей Требуется общий механизм учёта Central собирает сведения стримеров и предоставляет кластерную историю.

Nginx можно интегрировать с внешним состоянием и аналитикой. Сравнение относится к схеме, где на эдже выполняется только проверка ссылки: сама такая проверка ещё не является учётом сессий просмотра.

Кластерная сессия и переход между эджами

При балансировке зритель может начать просмотр на эдже A и продолжить на эдже B. Чтобы анализировать такой просмотр, central собирает сведения с серверов, хранит закрытые сессии в общем журнале и формирует историю с этапом объединения записей.

В кластерной истории записи одной распознанной идентичности объединяются, если их интервалы пересекаются или разделены не более чем 30 минутами. Переданные байты суммируются, время охватывает объединённый интервал, а nodes перечисляет участвовавшие серверы. Это даёт модель логического просмотра поверх отдельных серверных записей.

В текущей реализации есть ограничение: чтение истории фактически опирается на совпадающий полный id. При открытии просмотра на другом эдже этот ID может измениться, поскольку включает время открытия. Поэтому объединение всех миграций между эджами пока не гарантируется. Идентификатор JWT-билета сам по себе не устраняет это ограничение текущей выдачи истории.

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

Просмотр через API

Текущие сессии стрима в central:

curl -fsS -u "$ADMIN_USER:$ADMIN_PASSWORD" \
  'http://central:8080/central/api-v4/play-sessions/active?stream=cam1&limit=100'

История с объединением записей:

curl -fsS -u "$ADMIN_USER:$ADMIN_PASSWORD" \
  'http://central:8080/central/api-v4/play-sessions/closed?stream=cam1&limit=100'

Ответ содержит массив sessions. Поля id, bytes, duration и dvr описывают просмотр; node и nodes — участие стримеров. uncovered_nodes показывает серверы, по которым сбор данных неполон. Непокрытый сервер нельзя считать сервером с нулём зрителей.

Для локальной диагностики доступны соответствующие пути /streamer/api-v4/play-sessions/active и /streamer/api-v4/play-sessions/closed на стримере. Сбор истории в central происходит асинхронно: локальное закрытие сессии не означает её мгновенного появления в общем журнале.