Описание

Видеопоток захватывается с RTSP-источника, отдающего аудио и видео в поддерживаемых кодеках. Далее видеопоток трансформируется на стороне сервера для воспроизведения в браузерах и мобильных устройствах.

RTSP-источники

Поддерживаемые кодеки

Поддерживаемые платформы и браузеры


Chrome

Firefox

Safari 11

Internet Explorer

Edge

Windows

+

+


+

+

Mac OS

+

+

+



Android

+

+




iOS

-

-

+



Схема работы


  1. Браузер соединяется с сервером по протоколу Websocket и отправляет команду play.
  2. Сервер соединяется с RTSP-источником и отправляет команду play.
  3. RTSP-источник передает на сервер RTSP-поток.
  4. Сервер трансформирует поток в WebRTC и отдает поток браузеру.

Настройка

В некоторых случаях, например, если подключение к IP-камере для захвата потока по RTSP производится через VPN, RTSP-клиент должен быть привязан к определенному адресу. Адрес указывается при помощи опции rtsp_client_address в файле настроек flashphoner.properties, например

rtsp_client_address=172.16.0.3

Краткое руководство по тестированию

Захват видеопотока с IP-камеры и трансляция в браузер

1. Для теста используем:

2. Откройте веб-приложение Player, укажите в поле "Stream" URL веб-камеры:


3. Нажмите кнопку "Start". Начнется трансляция захваченного потока.


4. Графики WebRTC internals:

Управление захватом видеопотока с IP-камеры при помощи REST API

Как правило, для захвата потока с IP-камеры достаточно указать URL-камеры в качестве имени потока при его создании. Однако, при необходимости, возможно управлять захватом RTSP-потока при помощи REST API.

Тестирование

1. Для теста используем:

2. Откройте REST-клиент. Отправьте запрос /rtsp/startup, указав в параметрах URL веб-камеры:


3. Убедитесь, что поток захвачен сервером. Для этого отправьте запрос /rtsp/find_all:


4. Откройте веб-приложение Player, укажите в поле "Stream" URL веб-камеры и нажмите Start. Начнется воспроизведение потока в браузере:


5. Отправьте запрос /rtsp/terminate, указав в параметрах URL веб-камеры:


6. Воспроизведение потока прервется с ошибкой:

REST-вызовы

REST-запрос должен быть HTTP/HTTPS POST запросом в таком виде:

Здесь:

REST-методы и статусы ответа

REST-метод

Пример тела REST-запроса

Пример тела REST-ответа

Статусы ответа

Описание

/rtsp/startup

{
 "uri":"rtsp://myserver.com/live/myStream"
}

409 - Conflict

500 - Internal error


Извлечь RTMP-поток по указанному URL


/rtsp/find_all


{
"uri": "rtsp://myserver.com/live/myStream",
"status": "PLAYING"
}

200 – потоки найдены

404 – потоки не найдены

Найти все извлеченные RTMP-потоки

/rtsp/terminate

{
"uri":"rtsp://myserver.com/live/myStream"
}

200 - поток завершен

404 - поток не найден

Завершить извлеченный RTMP-поток

Параметры

Имя параметра

Описание

Пример

uri

URL RTSP-потока

rtsp://myserver.com/live/myStream

status

Текущий статус потока

PLAYING

Последовательность выполнения операций (Call Flow)

Ниже описана последовательность вызовов при использовании примера Player

player.html

player.js

1. Установка соединения с сервером.

Flashphoner.createSession(); code

    Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
        setStatus(session.status());
        //session connected, start playback
        playStream(session);
    }).on(SESSION_STATUS.DISCONNECTED, function(){
        setStatus(SESSION_STATUS.DISCONNECTED);
        onStopped();
    }).on(SESSION_STATUS.FAILED, function(){
        setStatus(SESSION_STATUS.FAILED);
        onStopped();
    });

2. Получение от сервера события, подтверждающего успешное соединение.

ConnectionStatusEvent ESTABLISHED code

    Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
        setStatus(session.status());
        //session connected, start playback
        playStream(session);
    }).on(SESSION_STATUS.DISCONNECTED, function(){
        ...
    }).on(SESSION_STATUS.FAILED, function(){
        ...
    });

3. Запрос на воспроизведение потока.

session.createStream(), stream.play(); code

URL IP-камеры передается в метод createStream() как имя потока

function playStream(session) {
    var streamName = $('#streamName').val();
    var options = {
        name: streamName,
        display: remoteVideo,
        flashShowFullScreenButton: true
    };
    ...    
    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
        ...
    });
    stream.play();
}

4. Запрос от WCS к RTSP-источнику на трансляцию потока.

5. Трансляция RTSP-потока

6. Получение от сервера события, подтверждающего успешный захват и проигрывание потока.

StreamStatusEvent, статус PLAYING code

    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
        ...
    }).on(STREAM_STATUS.PLAYING, function(stream) {
        $("#preloader").show();
        setStatus(stream.status());
        onStarted(stream);
        ...
    });
    stream.play();

7. Отправка аудио-видео потока по WebRTC

8. Остановка воспроизведения потока.

stream.stop(); code

function onStarted(stream) {
    $("#playBtn").text("Stop").off('click').click(function(){
        $(this).prop('disabled', true);
        stream.stop();
    }).prop('disabled', false);
    $("#fullScreenBtn").off('click').click(function(){
       stream.fullScreen();
    }).prop('disabled', false);
    $("#volumeControl").slider("enable");
    stream.setVolume(currentVolumeValue);
}

9. Получение от сервера события, подтверждающего остановку воспроизведения потока.

StreamStatusEvent, статус STOPPED code

    stream = session.createStream(options).on(STREAM_STATUS.PENDING, function(stream) {
        ...
    }).on(STREAM_STATUS.PLAYING, function(stream) {
        ...
    }).on(STREAM_STATUS.STOPPED, function() {
        setStatus(STREAM_STATUS.STOPPED);
        onStopped();
    }).on(STREAM_STATUS.FAILED, function(stream) {
        ...
    }).on(STREAM_STATUS.NOT_ENOUGH_BANDWIDTH, function(stream){
        ...
    });
    stream.play();

Повторное использование подключения к камере

Если к потоку, захваченному с RTSP IP-камеры, присоединяются другие подписчики, будет использовано ранее установленное подключение к камере, при условии, что все подписчики указали одинаковый адрес камеры. Например, запросы к одной и той же камере

rtsp://host:554/live.sdp

и

rtsp://host:554/live.sdp?p=1

отличаются, поэтому будет создано два RTSP-подключения, если запросить оба этих потока.

Аутентификация при захвате потока

WCS поддерживает аутентификацию по имени и паролю при захвате RTSP-потока. данные пользователя должны быть указаны в URL потока, например

rtsp://user:password@hostname/stream

Если в имени или пароле есть какие-либо спецсимволы, они должны быть экранированы. например

rtsp://user:p%40ssword@hostname/stream

Здесь

user - имя пользователя

p@ssword - пароль, символ '@' экранирован при указании URL.

Известные проблемы

1. Поток, содержащий B-фреймы, не воспроизводится либо воспроизводится с артефактами (задержки, подергивания)

Симптомы: 
а) поток, передаваемый IP камерой по RTSP, не проигрывается, дает задержки видео или подергивания
б) предупреждения в клиентском логе:

09:32:31,238 WARN 4BitstreamNormalizer - RTMP-pool-10-thread-5 It is B-frame!

Решение: при возможности запрашивать с камеры поток более низкого разрешения, с более низким качеством таким образом, чтобы исключить использование B-фреймов, либо траскодировать данный поток.

2. Соединение с IP-камерой разрывается при ошибке в любом из треков (аудио или видео)

Симптомы: соединение с IP-камерой разрывается, если один из треков вернул ошибку 4**.
Решение: данное поведение включено по умолчанию. Однако, если единичные ошибки не являются критичными и не требуют прекращения трансляции, в файле flashphoner.properties необходимо указать

rtsp_fail_on_error_track=false
rtp_force_synchronization=true

3. AAC фреймы типа 0 не поддерживаются декодером и будут игнорироваться при воспроизведении захваченного потока

При этом в клиентском логе будут выведены предупреждения:

10:13:06,815 WARN AAC - AudioProcessor-c6c22de8-a129-43b2-bf67-1f433a814ba9 Dropping AAC frame that starts with 0, 119056e500

4. Символы в имени потока, недопустимые в URI, должны быть экранированы

Симптомы: RTSP-поток не воспроизводится с признаком ошибки 'Bad URI'
Решение: любые символы, недопустимые при указании URI, должны быть экранированы в имени потока, например

rtsp://hostname/c@@lstream/channel1

должен быть записан как

rtsp://hostname/c%40%40lstream/channel1