В данной статье мы расскажем как разработать многопользовательскую 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="https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/current/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 type="text/javascript" src="https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/current/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="https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/current/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="https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/current/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 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.
Трансляция с веб-камеры готова. Далее можно модифицировать текущие примеры и тестировать например трансляции многие-ко-многим с публикацией нескольких потоков со стримеров и их дальнейшей раздачей на плееры.
Ссылки
- Начальная установка и конфигурация сервера Web Call Server 5
- Web SDK для WCS5
- Скачать исходный код трансляции
- Статистика WebRTC в chrome://webrtc-internals
Web Call Server 5 — это стриминг медиасервер с поддержкой WebRTC, RTMP и других протоколов для разработки web приложений и мобильных приложений с низкой задержкой видео. Сервер включает в себя Web SDK, Android SDK и iOS SDK для разработки кросс-платформенных видеочатов, онлайн видеотрансляций, трансляций с IP-камер и других приложений потокового видео для браузеров и мобильных устройств.