HLS формат с разными разрешениями

Din

New Member
Добрый день,
Есть rtsp-камера. Назовем ее RTSP://camera1
Есть соответсвенно url для получения видео с камеры в HLS-формате: https://host/RTSP://camera1/RTSP://camera1.m3u8
Для смены разрешения всех видео стримов у Flashphoner есть настройка hls_player_height, hls_player_width

Подскажите, пожалуйста, как нам настроить Flashphoner или что необходимо сделать, чтоб получать видео с одной и той же камеры в нескольких разрешениях в формате HLS?
Например, чтоб
ссылка https://host/RTSP://camera1/RTSP://camera1.m3u8 - давала видео с разрешением камеры
например https://host/RTSP://camera1_4K/RTSP%3A%2F%2Fcamera1_4K.m3u8 - давала видео с разрешением 4K
_2K/RTSP%3A%2F%2Fcamera1_2K.m3u8 - давала видео с разрешением 2K
и так далее.

Спасибо.
 

Max

Administrator
Staff member
Добрый день.
Уточните, пожалуйста: может ли камера для каждого разрешения отдавать свой поток по уникальному URL, например
Code:
rtsp://camera:554/?channel=1&resolution=240p
rtsp://camera:554/?channel=1&resolution=480p
rtsp://camera:554/?channel=1&resolution=720p
Если да, то каждый из этих потоков может быть захвачен на WCS по своему URL и проигран по полному имени по WEbRTC или HLS.
Если камера отдает только одно разрешение (максимальное), необходимо транскодировать поток на сервере к меньшим разрешениям. Для этого нужно создать транскодер по REST API
Code:
POST /rest-api/transcoder/startup HTTP/1.1
HOST: wcs:8081
content-type: application/json
 
{
    "uri": "transcoder://tcode1",
    "remoteStreamName": "rtsp://camera:554/?channel=1",
    "localStreamName": "camera720p",
    "encoder": {
        "width": 1280,
        "height": 720
    }
}
и забирать с сервера транскодированный поток по WebRTC или HLS по имени camera720p
Отметим, что транскодирование требует от сервера значительных ресурсов (1 физическое ядро CPU на 2 потока, кодируемых в 720p).
 

Din

New Member
Какова продолжительность жизни транскодера?
Если у нас требуется, например, воспроизвести HLS видеопоток на 2ух разных устройствах, то перед тем, как обратиться к УРЛ camera720p, необходимо на обоих устройства обратиться к REST API и запустить транскодер?
Или же запуск транскодера требуется сделать единожды без привязки к устройству, на которому будет воспроизведение? Тогда вопрос номер 1.
 

ildarei

New Member
Добрый день.
Уточните, пожалуйста: может ли камера для каждого разрешения отдавать свой поток по уникальному URL, например
Code:
rtsp://camera:554/?channel=1&resolution=240p
rtsp://camera:554/?channel=1&resolution=480p
rtsp://camera:554/?channel=1&resolution=720p
Если да, то каждый из этих потоков может быть захвачен на WCS по своему URL и проигран по полному имени по WEbRTC или HLS.
Если камера отдает только одно разрешение (максимальное), необходимо транскодировать поток на сервере к меньшим разрешениям. Для этого нужно создать транскодер по REST API
Code:
POST /rest-api/transcoder/startup HTTP/1.1
HOST: wcs:8081
content-type: application/json

{
    "uri": "transcoder://tcode1",
    "remoteStreamName": "rtsp://camera:554/?channel=1",
    "localStreamName": "camera720p",
    "encoder": {
        "width": 1280,
        "height": 720
    }
}
и забирать с сервера транскодированный поток по WebRTC или HLS по имени camera720p
Отметим, что транскодирование требует от сервера значительных ресурсов (1 физическое ядро CPU на 2 потока, кодируемых в 720p).
На большинстве камер можно получать максимальное разрешение на основном потоке, а на второстепенном не более 704х576.
Соответственно если у нас задача получать 3 потока в разрешениях 4к 2к и 1к, то вариант у нас один - транскодить на сервере.
Подтвердите, пожалуйста, верно ли я все понимаю.
 

Max

Administrator
Staff member
Какова продолжительность жизни транскодера?
Если у нас требуется, например, воспроизвести HLS видеопоток на 2ух разных устройствах, то перед тем, как обратиться к УРЛ camera720p, необходимо на обоих устройства обратиться к REST API и запустить транскодер?
Или же запуск транскодера требуется сделать единожды без привязки к устройству, на которому будет воспроизведение? Тогда вопрос номер 1.
Для транскодирования одного потока в одно разрешение достаточно запустить один транскодер. После этого подписчики, желающие играть поток в этом разрешении, забирают с сервера выходной поток этого транскодера.
То есть REST API достаточно дернуть при подключении первого подписчика на это разрешение.
По умолчанию, транскодер, у которого нет подписчиков, завершается через 60 секунд. Этот интервал регулируется настройкой сервера
Code:
transcoder_agent_activity_timer_timeout=60000
На большинстве камер можно получать максимальное разрешение на основном потоке, а на второстепенном не более 704х576.
Соответственно если у нас задача получать 3 потока в разрешениях 4к 2к и 1к, то вариант у нас один - транскодить на сервере.
Да, в этом случае верно.
Но нужно иметь в виду, что транскодинг, а именно кодирование выходного потока, требует значительных ресурсов. Например, если Вам необходимо транскодировать 4K поток в 1080p, на один такой поток потребуется два ядра CPU. Для транскодирования в 2K мы, к сожалению, не проводили нагрузочных тестов, предполагаем, что минимум три ядра на один выходной поток.
Также транскодинг требует значительного объема памяти. Рекомендуем не менее 128 Гб, из них 64 Гб выделить на Java heap, оставшиеся 64 Гб будут использоваться для промежуточного хранения декодированных картинок (кодирование производится не Java кодом, а нативным, для ускорения).
 

Din

New Member
Продолжаем мучать HLS
Транскодировать видеопоток с 4К камеры в другое разрешение удалось, благодаря вызову REST API /rest-api/transcoder/startup
Но мы столкнулись с другой проблемой.
Если с камеры нет активных подключенных стримов, то REST API /rest-api/transcoder/startup ее не видит, и возвращает NotFound.
Т.е. для того, чтобы с камеры получить перекодированное видео в произвольном разрешении необходимо сделать три действия:
1. Запросить стрим с камеры по умолчанию
2. Запустить транскодер
3. Запросить стрим с кастомным разрешением

Первый пункт явно лишний.
Что мы делаем не так? Нельзя ли объединить первые 2 пункта?
 

Max

Administrator
Staff member
Т.е. для того, чтобы с камеры получить перекодированное видео в произвольном разрешении необходимо сделать три действия:
1. Запросить стрим с камеры по умолчанию
2. Запустить транскодер
3. Запросить стрим с кастомным разрешением
Да, все верно. Если потока нет на сервере, его необходимо захватить с камеры на сервер. Это можно проверить запросом /rtsp/find.
Что мы делаем не так? Нельзя ли объединить первые 2 пункта?
Нельзя, т.к. это две разные операции. Сначала необходимо опубликовать поток на сервере, это делается в момент захвата потока с камеры, затем уже можно создать для него транскодер.
Есть вариант отказаться от REST API и отдать управление на клиента. В этом случае клиент запрашивает проигрывание потока с камеры с указанием разрешения:
Code:
session.createStream({
    name: "rtsp://camera:554/?channel=1",
    constraints: {
          audio:true,
          video: {
               width:1920,
               height:1080
          }
    }
    ...
}).play();
В этом случае:
- если потока с камеры еще нет на сервере, он будет захвачен с камеры
- затем поток будет играть этому клиенту с транскодированием
- если поток уже есть и транскодируется, клиент просто подпишется на него
Но это работает только для WebRTC подписчиков. Для HLS нужно создавать транскодеры по REST API.
 

Din

New Member
Нельзя, т.к. это две разные операции. Сначала необходимо опубликовать поток на сервере, это делается в момент захвата потока с камеры, затем уже можно создать для него транскодер.
Есть вариант отказаться от REST API и отдать управление на клиента. В этом случае клиент запрашивает проигрывание потока с камеры с указанием разрешения:
Я конечно не знаю всех тонкостей внутренней работы сервера Флешфонер, но странно: Почему WebRTC'у можно одной операцией сделать все (и поток захватить, и транспонировать сразу и прочее), а HLS нельзя :)
Но все равно спасибо.

Надеюсь последний вопрос:
8081 - порт для REST API по HTTP
Какой порт для HTTPS?
 

Max

Administrator
Staff member
Почему WebRTC'у можно одной операцией сделать все (и поток захватить, и транспонировать сразу и прочее), а HLS нельзя :)
Потому что подписаться можно только на опубликованный поток. А когда запрашивается транскодинг через констрейнты, отдельный PUBLISH экземпляр потока не создается, поэтому другими протоколами (HLS, RTMP, RTSP) на него не подписаться.
Для WebRTC это все работает, потому что сервер заточен в первую очередь на WebRTC.
 

Din

New Member
Добрый день.
...
Для этого нужно создать транскодер по REST API
Code:
POST /rest-api/transcoder/startup HTTP/1.1
HOST: wcs:8081
content-type: application/json

{
    "uri": "transcoder://tcode1",
    "remoteStreamName": "rtsp://camera:554/?channel=1",
    "localStreamName": "camera720p",
    "encoder": {
        "width": 1280,
        "height": 720
    }
}
и забирать с сервера транскодированный поток по WebRTC или HLS по имени camera720p
Отметим, что транскодирование требует от сервера значительных ресурсов (1 физическое ядро CPU на 2 потока, кодируемых в 720p).
Добрый день.
Скажите, пожалуйста, за что отвечает параметр uri?
 

Max

Administrator
Staff member
Скажите, пожалуйста, за что отвечает параметр uri?
Это обязательный параметр, который идентифицирует данный транскодер на сервере. Имя после префикса transcoder:// должно быть уникальным, в противном случае запрос на создание вернет 409 Conflict, а любой другой запрос вернет 404 Not found
 
Top