В данной статье мы расскажем как разработать многопользовательскую WebRTC видео трансляцию из браузера через свой сервер ретранслятор. Трансляция будет идти из браузера Google Chrome и обычной USB вебкамеры. Для трансляции видео будет создана отдельная HTML — страница Streamer, а воспроизведением будет заниматься HTML-страница Player.
Схема трансляции
Browser1 — транслирующий. Подключается к серверу и транслирует видео с веб камеры.
Browser2, Browser3, Browser4 — зрители. Подключаются и получают видео для воспроизведения. Для ре-трансляции видеопотоков по WebRTC будет использоваться Web Call Server.
Принцип понятен и можно переходить к написанию кода. Создадим две HTML-страницы. Первая будет называться streamer.html и будет отправлять видеопоток на сервер. Вторая будет называться player.html и играть видеопоток с сервера.
Streamer — HTML
<html>
<head>
<script language="javascript" src="flashphoner.js"></script>
</head>
<body onLoad="init()">
<h1>The streamer</h1>
<div id="localVideo" style="width:320px;height:240px;border: 1px solid"></div>
<input type="button" value="start" onClick="start()"/>
<p id="status"></p>
</body>
</html>
В заготовке html-страницы Streamer мы использовали следующие вещи:
1) Скрипт flashphoner.js
Этот скрипт является основным скриптом JavaScript API и его можно найти в последней сборке Web SDK.
<script language="javascript" src="flashphoner.js"></script>
2) Div элемент localVideo — это блок, в котором будет размещено видео, захваченное с вебкамеры.
<div id="localVideo" style="width:320px;height:240px;border: 1px solid"></div>
3) Кнопка Start, по которой будет происходить запуск трансляции с вызовом функции start().
<input type="button" value="start" onClick="start()"/>
4) Обратите внимание, что в body добавлена обработка события onLoad c вызовом функции инициализации.
<body onLoad="init()">
5) Элемент с id = status, используется для отображения статусов.
<p id="status"></p>
Streamer — JavaScript
Переходим к написанию JavaScript — кода. Мы намеренно не используем JQuery, Bootstrap или какие-либо другие фреймворки чтобы оставить код минимальным:
var localVideo;
function init(){
Flashphoner.init();
localVideo = document.getElementById("localVideo");
}
function start() {
Flashphoner.createSession({urlServer: "wss://wcs5-eu.flashphoner.com:8443"}).on(Flashphoner.constants.SESSION_STATUS.ESTABLISHED, function (session) {
//session connected, start streaming
startStreaming(session);
}).on(Flashphoner.constants.SESSION_STATUS.DISCONNECTED, function () {
setStatus("DISCONNECTED");
}).on(Flashphoner.constants.SESSION_STATUS.FAILED, function () {
setStatus("FAILED");
});
}
function startStreaming(session) {
session.createStream({
name: "stream222",
display: localVideo,
cacheLocalResources: true,
receiveVideo: false,
receiveAudio: false
}).on(Flashphoner.constants.STREAM_STATUS.PUBLISHING, function (publishStream) {
setStatus(Flashphoner.constants.STREAM_STATUS.PUBLISHING);
}).on(Flashphoner.constants.STREAM_STATUS.UNPUBLISHED, function () {
setStatus(Flashphoner.constants.STREAM_STATUS.UNPUBLISHED);
}).on(Flashphoner.constants.STREAM_STATUS.FAILED, function () {
setStatus(Flashphoner.constants.STREAM_STATUS.FAILED);
}).publish();
}
function setStatus(status) {
document.getElementById("status").innerHTML = status;
}
В этом примере всего четыре функции:
1) init
Отвечает за инициализацию JavaScript API и берет ссылку на div — элемент localVideo.
2) start
Эта функция создает подключение к серверу по протоколу websockets. Адрес подключения: wss://domain:8443. На месте domain должен быть домен вашего WCS сервера (предполагаем, что сервер уже установлен, настроен и имеет выделенный домен, например webrtc.mycompany.com. Порт TCP 8443 должен быть открыт для входящих подключений).
Из кода этой функции понятно, следующим действием после получения статуса ESTABLISHED, будет вызов функции startStreaming и отправка потока на сервер.
3) startStreaming
Здесь мы создаем новый объект Stream, используя функцию API: session.createStream();. При создании стрима в качестве основных параметров передаются:
● streamName — имя видеопотока
● display — это элемент div, в котором будет отображаться захваченное для данного видеопотока видео с веб-камеры
Имя потока желательно генерировать уникальное, но мы для теста используем просто stream222.
4) setStatus
Данная функция отображает статус сессии (session) или потока (stream) на HTML-странице.
Выносим наш скрипт в отдельный файл streamer.js. Код страницы streamer.html будет выглядеть так:
<html>
<head>
<script language="javascript" src="flashphoner.js"></script>
<script language="javascript" src="streamer.js"></script>
</head>
<body onLoad="init()">
<h1>The streamer</h1>
<div id="localVideo" style="width:320px;height:240px;border: 1px solid"></div>
<input type="button" value="start" onClick="start()"/>
<p id="status"></p>
</body>
</html>
Streamer — тестирование
В итоге у нас получилось мини стриминг-приложение, состоящее из трех скриптов:
● streaming.html
● streaming.js
● flashphoner.js
Копируем наши скрипты на web-сервер чтобы начать тестирование. В качестве веб-сервера мы используем Apache 2 со стандартным /var/www/html
В результате наш рабочий стример выглядит так, как показано на скриншоте ниже. После нажатия на кнопку Start, с сервером устанавливается соединение и на сервер отправляется WebRTC видеопоток:
Чтобы убедиться в том, что поток действительно отправляется, переходим во вкладку chrome://webrtc-internals. Здесь можно в режиме реального времени наблюдать что происходит с видеопотоком и отслеживать такие параметры как битрейт, разрешение, фреймрейт, количество отправленных пакетов, RTT и многое другое.
Таким образом, наш стример заработал и WebRTC видеопоток корректно отправляется на сервер, откуда осталось его забрать. Для того чтобы забрать и воспроизвести поток, создадим новую страницу player.html
Player — HTML
Страницу плеера копипастим из стримера, с той лишь разницей, что будем использовать скрипт: player.js вместо streamer.js, и вместо localVideo, зададим id = remoteVideo для нашего div — элемента.
<html>
<head>
<script language="javascript" src="flashphoner.js"></script>
<script language="javascript" src="player.js"></script>
</head>
<body onLoad="init()">
<h1>The player</h1>
<div id="remoteVideo" style="width:320px;height:240px;border: 1px solid"></div>
<input type="button" value="start" onClick="start()"/>
<p id="status"></p>
</body>
</html>
Player — JavaScript
В скрипте плеера также есть некоторые отличия, но подход остается прежним: инициализируется Flashphoner API, по кнопке Start открывается соединение с сервером через websocket, ждет события ESTABLISHED и начинает воспроизведение потока.
Список отличий скрипта player.js от скрипта streamer.js:
● Используется remoteVideo вместо localVideo
● После установки соединения вызываем startPlayback вместо startStreaming
● При создании стрима методом createStream(), передаются параметры receiveAudio=true и receiveVideo=true
● Вызывается метод play() вместо publish()
var remoteVideo;
function init(){
Flashphoner.init();
remoteVideo = document.getElementById("remoteVideo");
}
function start() {
Flashphoner.createSession({urlServer: "wss://wcs5-eu.flashphoner.com:8443"}).on(Flashphoner.constants.SESSION_STATUS.ESTABLISHED, function (session) {
//session connected, start streaming
startPlayback(session);
}).on(Flashphoner.constants.SESSION_STATUS.DISCONNECTED, function () {
setStatus("DISCONNECTED");
}).on(Flashphoner.constants.SESSION_STATUS.FAILED, function () {
setStatus("FAILED");
});
}
function startPlayback(session) {
session.createStream({
name: "stream222",
display: remoteVideo,
cacheLocalResources: true,
receiveVideo: true,
receiveAudio: true
}).on(Flashphoner.constants.STREAM_STATUS.PLAYING, function (playStream) {
setStatus(Flashphoner.constants.STREAM_STATUS.PLAYING);
}).on(Flashphoner.constants.STREAM_STATUS.STOPPED, function () {
setStatus(Flashphoner.constants.STREAM_STATUS.STOPPED);
}).on(Flashphoner.constants.STREAM_STATUS.FAILED, function () {
setStatus(Flashphoner.constants.STREAM_STATUS.FAILED);
}).play();
}
function setStatus(status) {
document.getElementById("status").innerHTML = status;
}
В результате получаем WebRTC-плеер, состоящий из двух скриптов:
● player.html
● player.js
Не забываем, что для работы плеера также необходим файл API flashphoner.js, поэтому копируем файлы плеера в ту же папку на web-сервере.
В итоге наше окончательное приложение для WebRTC онлайн трансляций состоит из пяти файлов:
● streamer.html
● streamer.js
● player.html
● player.js
● flashphoner.js
Приступим к тестированию и снова отправим видеопоток через streamer.html. После этого откроем новую вкладку браузера с player.html и нажмем Start.
В итоге трансляция состоялась и мы получили WebRTC — видеопоток на плеер. Теперь можно подключиться к этому же видеопотоку с других устройств или просто открыть несколько вкладок браузера, каждая из которых будет забирать этот же видеопоток.
Таким образом мы отправили видеопоток на сервер и раздали его в режиме один ко многим, тем самым реализовав простую видеотрансляцию на несколько подключений.
3 минуты
Попробуем развернуть трансляцию за 3 минуты, учитывая следующее:
1) Уже установлен Web Call Server 5 для ретрансляции видеопотоков и настроен SSL. Без настройки SSL / HTTPS, трансляция в Google Chrome работать не будет, так как для доступа к веб камере и микрофону соединение должно быть безопасным и страница, на которой вы тестируете трансляцию должна быть открыта по HTTPS. Порт TCP 8443 открыт и готов принимать соединения по протоколу wss://
2) Уже установлен и сконфигурирован HTTP сервер, например Apache. Web-сервер настроен для работы через HTTPS и имеет FTP/SFTP/SSH доступ, через который можно залить / скачать тестовые скрипты.
WCS5 и Apache могут быть установлены на одной системе либо разнесены по разным серверам. Apache в данном случае просто отдает контент в виде HTML-страниц и скриптов, а WCS5 обслуживает подключения с видео.
Чтобы провести тестирование без установки, можно воспользоваться демо-сервером wss://wcs5-eu.flashphoner.com:8443 — он открыт для коннектов и тестирования.
Минута 1
Загружаем тестовые скрипты и распаковываем в папке /var/www/html на веб-сервере.
wget --no-check-certificate https://flashphoner.com//downloads/examples/webrtc-broadcasting-example-0.5.15.1977.2088.tar.gz
tar -xzf webrtc-broadcasting-example-0.5.15.1977.2088.tar.gz
Минута 2
Открываем скрипты streamer.js и player.js на редактирование, находим и меняем:
wss://wcs5-eu.flashphoner.com:8443
на
wss://domain.com:8443
здесь domain.com — доменное имя вашего сервера, на котором установлен WCS5
Минута 3
Открываем streamer.html в браузере по https:// и нажимаем Start. Открываем в новой вкладке player.html и нажимаем Start.
Трансляция с веб-камеры готова. Далее можно модифицировать текущие примеры и тестировать например трансляции многие-ко-многим с публикацией нескольких потоков со стримеров и их дальнейшей раздачей на плееры.
Ссылки
1. Начальная установка и конфигурация сервера Web Call Server 5
2. Web SDK для WCS5
3. Скачать исходный код трансляции
4. Статистика WebRTC в chrome://webrtc-internals
Web Call Server 5 — это стриминг медиасервер с поддержкой WebRTC, RTMP и других протоколов для разработки web приложений и мобильных приложений с низкой задержкой видео. Сервер включает в себя Web SDK, Android SDK и iOS SDK для разработки кросс-платформенных видеочатов, онлайн видеотрансляций, трансляций с IP-камер и других приложений потокового видео для браузеров и мобильных устройств.
Автор: flashphoner