В этой статье покажем 7 технологически разных способов отображения видеопотока с IP-камеры с поддержкой RTSP на web-странице браузера.

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

Способ 1 — RTMP

RTMP протокол браузеры не поддерживают, но его поддерживает старый добрый Flash Player, который работает неплохо, хоть и не во всех браузерах, и может отобразить видеопоток.

Flash player

Код плеера в этом случае будет построен на Action Script 3 и выглядеть примерно так:

var nc:NetConnection = nc.connect("rtmp://192.168.88.59/live",obj);
var subscribeStream:NetStream = new NetStream(nc);
subscribeStream.play("rtsp://192.168.88.5/live.sdp");

В этом примере:

rtmp://192.168.88.59/live — это адрес промежуточного сервера, который заберет RTSP видеопоток с камеры и конвертирует его в RTMP
rtsp://192.168.88.5/live.sdp — это RTSP адрес самой камеры.

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

Выглядит это так:

Flash streaming

Способ 2 — RTMP с оберткой HTML5

Желающих кодить на Action Script 3 все меньше. Специально для этого придуман способ с HTML5 оберткой, которая позволяет управлять RTMP-плеером из JavaScript. В этом случае флэшка подгружается на HTML-страницу только для того чтобы отобразить картинку и выдать в динамики звук.

RTMP-player JavaScript

var session = Flashphoner.createSession({urlServer:"wss://192.168.88.59:8443"});
session.createStream({name:"rtsp://192.168.88.5/live.sdp", display:myVideo}).play();

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

WCS url stream volume

Способ 3 — RTMFP

Протокол RTMFP также работает внутри флэш плеера. Разница с RTMP в том, что RTMFP работает поверх протокола UDP и тем самым является более пригодным для получения трансляции с низкой задержкой.

Код плеера на AS3 в этом случае полностью идентичен используемому в RTMP, добавлена одна буква F в строке протокола подключения к серверу.

var nc:NetConnection = nc.connect("rtmfp://192.168.88.59/live",obj);
var subscribeStream:NetStream = new NetStream(nc);
subscribeStream.play("rtsp://192.168.88.5/live.sdp");

Для порядка дадим скриншот с RTMFP

Screenshot with RTMFP

Способ 4 — RTMFP c оберткой HTML5

Этот способ идентичен пункту 2, с той разницей, что мы при инициализации в JavaScript устанавливаем RTMFP протокол для использования в нижележащей флэшке (swf-объекте).

Var session = Flashphoner.createSession({urlServer:"wss://192.168.88.59:8443", flashProto:"rtmfp"});
session.createStream({name:"rtsp://192.168.88.5/live.sdp", display:myVideo}).play();

Картинка плеера:

RTMFP HTML5 - player

Способ 5 — WebRTC

В данном случае Flash не используется совсем и видеопоток проигрывается средствами самого браузера, без использования сторонних плагинов. Это работает и в Android Chrome и Android Firefox — мобильных браузерах, где Flash не установлен. WebRTC дает самую низкую задержку — менее 0.5 секунды.

WebRTC Android Chrome and Android Firefox

Код плеера тот же:

var session = Flashphoner.createSession({urlServer:"wss://192.168.88.59:8443"});
session.createStream({name:"rtsp://192.168.88.5/live.sdp", display:myVideo}).play();

Автоматически определяется поддержка WebRTC, и если поддерживается то поток играет по WebRTC.

Playing WebRTC

Способ 6 — Websockets

WebRTC и Flash не покрывают все браузеры и платформы. Например, в браузере iOS Safari эти технологии не поддерживаются.

Websockets - WebRTC and Flash

На iOS Safari можно доставить видеопоток по транспорту Websocket (TCP соединению между браузером и сервером). В этот туннель можно завернуть сконвертированный с RTSP видеопоток. После того, как бинарные данные придут их можно декодировать с помощью JavaScript и отрисовать на Canvas HTML5-элементе.

Именно этим занимается Websocket — плеер при работе в браузере iOS Safari, а его код снаружи выглядит также:

var session = Flashphoner.createSession({urlServer:"wss://192.168.88.59:8443"});
session.createStream({name:"rtsp://192.168.88.5/live.sdp", display:myVideo}).play();

Это чем-то похоже на подход с флэшкой, когда под HTML5 лежит swf-элемент. В данном случае, под HTML5-страницей лежит не swf-объект, а JavaScript-приложение, которое тянет данные по вебсокетам, декодирует и отрисовывает на Canvas в нескольких потоках.

Так выглядит RTSP поток на Canvas в браузере iOS Safari

RTSP Canvas in iOS Safari

Способ 7 — HLS

При конвертации RTSP в HLS, видеопоток разбивается на сегменты, которые благополучно скачиваются с сервера и отображаются в HLS-плеере.

Convert RTSP to HLS

В качестве HLS-плеера мы используем video.js. Код плеера можно скачать здесь.

Как выглядит плеер:

HLS-player stream

Способ 8 — Android приложение, WebRTC

Приложение забирает поток с сервера по WebRTC. Задача сервера в этом случае — сконвертировать RTSP в WebRTC и скормить мобильному приложению.

Convert RTSP to WebRTC

Java-код плеера для Android находится здесь и выглядит так:

SessionOptions sessionOptions = new SessionOptions("wss://192.168.88.59:8443");
Session session = Flashphoner.createSession(sessionOptions);
StreamOptions streamOptions = new StreamOptions("rtsp://192.168.88.5/live.sdp");
Stream playStream = session.createStream(streamOptions);
playStream.play();

Тестовое мобильное приложение плеера можно установить из Google Play, а исходники приложения скачать здесь.

Так выглядит воспроизведение RTSP потока по WebRTC на планшете Asus под Android:

Playing RTSP stream via WebRTC

Способ 9 — iOS приложение, WebRTC

Приложение также как и в случае Android забирает поток с сервера по WebRTC.

iOS app WebRTC

Objective-C код плеера выглядит так:

FPWCSApi2SessionOptions *options = [[FPWCSApi2SessionOptions alloc] init];
options.urlServer = @"wss://192.168.88.59:8443";
FPWCSApi2Session *session = [FPWCSApi2 createSession:options error:&error];
FPWCSApi2StreamOptions *options = [[FPWCSApi2StreamOptions alloc] init];
options.name = @"rtsp://192.168.88.5/live.sdp";
FPWCSApi2Stream *stream = [session createStream:options error:nil];
stream play:&error;

Скачать исходный код плеера для iOS можно здесь.

А из App Store можно установить тестовое приложение, которое использует показанные выше куски кода. Его работа с RTSP-потоком выглядит так:

App Store test app

Результаты

Подведем итоги и объединим полученные результаты в табличку:

  Способ отображения Применение Задержка
1 RTMP Там, где важно использование legacy — флэш клиента, Flex или Adobe Air medium
2 RTMP + HTML5 В браузерах IE, Edge, Mac Safari, если там установлен Flash Player medium
3 RTMFP Там, где важно использование legacy — флэш клиента, Flex или Adobe Air и важна низкая задержка low
4 RTMFP + HTML5 В браузерах IE, Edge, Mac Safari, если там установлен Flash Player и важна низкая задержка. low
5 WebRTC В браузерах Chrome, Firefox, Opera на десктопах и мобильных браузерах под Android, где важна real-time задержка. real-time
6 Websocket В браузерах, где нет Flash и WebRTC, но нужна средняя или низкая задержка. medium
7 HLS Во всех браузерах. Где не важна задержка. high
8 Android app, WebRTC В нативных мобильных приложениях  под Android, где требуется real-time задержка. real-time
9 iOS app, WebRTC В нативных мобильных приложениях  под iOS, где требуется real-time задержка. real-time

Для тестирования мы использовали сервер Web Call Server 5, который конвертирует RTSP поток для раздачи в 9 перечисленных направлениях.

Ссылки

Web Call Server 5 — сервер для раздачи RTSP потока
Flash Streaming — пример swf приложения, проигрывающего потоки по RTMP и RTMFP. Способы 1 и 3.
Source — исходный код swf приложения на Flex / AS3.

Player — пример web-приложения, которое воспроизводит RTSP поток по RTMP, RTMFP, WebRTC, Websocket. Способы 2,4,5,6.
Source — исходный код веб-плеера.

HLS плеер — пример web-плеера, играющего HLS. Способ 7.
Source — исходный код HLS плеера.

Android плеер WebRTC — пример мобильного приложения, которое играет поток по WebRTC. Способ 8.
Source — исходный код мобильного приложения.

iOS плеер WebRTC — пример мобильного приложения, которое играет WebRTC поток. Способ 9.
Source — исходный код мобильного приложения.