Трансляция WebRTC-видеопотока из браузера на YouTube Live в 65 строк JavaScript-HTML-кода

в 10:56, , рубрики: javascript, live, rtmp, WebRTC, YouTube, браузеры, Разработка систем связи

image

В данной статье мы расскажем как работают трансляции Youtube Live и покажем как человек с базовыми знаниями JavaScript может закодить трансляцию на Youtube Live с HTML страницы с использованием технологии WebRTC.

Для работы категорически потребуются следующие знания и умения:

1) Базовые знания JavaScript / HTML
2) Умение работать в командной строке Linux.
3) Прямые руки.

Трансляции в Youtube Live

Youtube дает возможность проводить трансляции в реальном времени. Т.е. не просто залить видеоролик, а создать полноценную живую трансляцию себя, своего кота мурзика или иного ответственного мероприятия.

Телестудия Youtube располагается на этой странице и в браузере Google Chrome выглядит так:

image

Для того чтобы сделать вещания доступными, нужно нажать кнопку Enable live streaming и пройти верификацию из двух шагов. Далее кнопка превращается в Create live event и можно начинать вещание.

image

Нажимаем Go live now чтобы перейти непосредственно к вещанию.

Youtube открывает Google Hangouts окно, через которое проводятся все манипуляции с видеопотоком.

image

Таким образом, мы создали живую трансляцию на Youtube Live, стартовали вещание, остановили вещание. Получили ролик с записью на Youtube. Трансляция проходила средствами Google Hangouts.

Все здорово, но судя по IT новостям, Гугл закрывает API Hangouts для разработки видео приложений с 25 апреля 2017 года. Для разработчиков это означает, что с помощью API Hangouts уже нельзя будет сделать свое кастомное приложение, которое стримит видео, в том числе и на Youtube.

Трансляция с RTMP live encoder

Далее рассмотрим альтернативный вариант создания трансляции, не привязанный к Google Hangouts и позволяющий транслировать видеопоток со специализированного устройства видеозахвата (RTMP Live Encoder).

image

Если кликнуть по кнопке Stream Now, попадаем в знакомый интерфейс создания трансляции.

Наиболее важная часть — это настройки кодировщика:

image

Как видите, здесь всего два поля:

1) Server URL
2) Stream name / key

Если нажать кнопку Reveal, название вашего потока отобразится и будет доступно для копирования.

Этих данных достаточно для того чтобы отправить видеопоток с RTMP Live Encoder на Youtube Live с любого местоположения и любого компьютера, без использования Google Hangouts. RTMP Live Encoder (он же кодировщик) — это устройство или программное обеспечение, которое захватывает поток с веб-камеры или с профессиональной видеокамеры, кодирует видео в RTMP протокол и отправляет по указанному адресу (Encoder setup).

Чтобы получить качественный аудио и видеопоток нужно использовать стандартные для Live Encoders кодеки, а именно H.264 видеокодек и AAC аудио кодек. Эта комбинация кодеков является самой распространенной и надежной и является фактическим стандартом применения в RTMP при использовании автономных кодировщиков.

Например плагин для браузера Adobe Flash Player тоже является кодировщиком и может стримить видео прямо с веб-страницы браузера, но он не поддерживает аудио кодек AAC для стриминга и поэтому с вещанием могут возникнуть проблемы, а именно может не быть звука.

Поэтому мы сразу берем в тестирование только те кодировщики, которые явно поддерживают кодеки H.264 и AAC. На текущий момент нам известны два кандидата на тестирование, которые используют данные кодеки:

Adobe Flash Media Live Encoder на Mac OS — это бесплатный программный кодировщик от Adobe, который может кодировать RTMP потоки в H.264 и AAC. Обратите внимание, что AAC аудио кодек поддерживается только в версии FMLE для Mac OS. Если вы используете тот же софт на Windows, AAC кодек будет недоступен. Вместо него будет mp3.

Wirecast — это платный кодировщик, имеющий бесплатную триальную версию в которой поверх транслируемого видео вставляется логотип и накладывается звук каждые 30 секунд. Wirecast имеет Windows-дистрибутив.

Начнем с Adobe FMLE. Устанавливаем FMLE на Mac и подцепляем к компьютеру (в тестах использовался Mac Mini) веб-камеру. С виртуальными камерами FMLE, похоже не работает, поэтому нужна честная USB веб-камера или встроенная (если у вас макбук).

В качестве видеокодека выставляем H.264 с разрешением 640x480. В качестве аудиокодека оставляем то, что задано по-умолчанию AAC 22050 Hz mono. Другие конфигурации и настройки H.264 и AAC также должны работать без проблем.

В поле FMS URL проставляем RTMP-адрес трансляции, который был получен на Youtube.
В поле Stream проставляем название стрима, которое опять же было получено на Youtube.

* Поле имеет такое странное название FMS URL потому что FMLE думает что в мире существует только один сервер, способный принимать RTMP видеопоток — Flash Media Server от Adobe (сейчас Adobe Media Server), но как мы видим это не так, и с данной задачей прекрасно справляется, например Youtube и еще сотня другая серверов и сервисов.

image

После того как все настройки выставили, нажимаем зеленую кнопку Start чтобы начать трансляцию и видео отправляется на Youtube. На картинке немного мутно, но мой Mac перегружен и скриншоты я снимаю через Teamviewer, поэтому на особое качество рассчитывать не приходится. Чтобы получить качественный стрим, позаботьтесь о качественной веб-камере с высоким разрешением и о мощном CPU, например процессор Core i7 и SSD диск были бы полезны для беспрепятственного и качественного кодирования RTMP видеопотока.

image

Так как мы достигли некоторого успеха при использовании FMLE, то тестировать Wirecast особого смысла нет. Если у вас возникли проблемы с FMLE или нет под рукой Mac OS, попробуйте сделать тоже самое с Wirecast. Например в этой статье можно найти несколько скриншотов с описанием как транслировать видеопоток в Wirecast. Кодировщик Wirecast интересен тем, что его можно использовать даже без веб-камеры. Вещать и кодировать в RTMP можно обычный видеоролик.

Конвертация из WebRTC в RTMP

Выше мы провели тест, показывающий как создать вещание на сервисе Youtube Live и как отправить RTMP видеопоток, закодированный в H.264 + AAC на Youtube.

Следующая задача — сделать тоже самое с помощью WebRTC. WebRTC — это технология, встроенная в браузеры, которая позволяет браузеру захватывать видео с камеры и аудио с микрофона и отправлять в сеть. Таким образом, браузер, поддерживающий WebRTC может работать в точности как Live Encoder — делать захват и отправлять. WebRTC поддерживается в следующих браузерах:

  • Chrome
  • Firefox
  • Opera
  • Chrome for Android
  • Firefox for Android

Т.е. WebRTC видеопотоки можно отправлять с десктопных браузеров Chrome, FF и тех же браузеров под управлением Android.

В результате, наша задача — сделать трансляцию на Youtube из браузера Google Chrome с обычной HTML страницы, без использования Google Hangouts или RTMP Live Encoder.

Проблемы три:

  • WebRTC не поддерживает RTMP протокол, который требует Youtube.
  • WebRTC не поддерживает AAC аудио кодек, который требует Youtube.
  • WebRTC в Chrome не поддерживает кодек H.264 на мобильных устройствах, там используется кодек VP8.

По этим трем причинам, WebRTC не может напрямую отправить аудио+видеопоток на Youtube Live.

Если же говорить про Adobe Flash Player, у него другая проблема

  • Не кодирует аудио в AAC

Поэтому вне зависимости от того, используется браузер с поддержкой WebRTC (Chrome) или браузер с поддержкой Flash Player (IE или Safari), нельзя отправить RTMP-видеопоток H.264 + AAC напрямую из браузера.

Решением является конвертация видеопотока на стороне сервера, которая показана на схеме ниже.

image

Таким образом, в трансляции появляется сервер-посредник, который принимает WebRTC видеопоток и конвертирует его в формат, который принимает Youtube.

Для тестирования будем использовать Web Call Server 5. Это медиасервер с поддержкой WebRTC технологии и RTMP протокола, имеющий триальную версию.

Наша задача — установить Web Call Server 5 на Linux-сервер и отправить на него WebRTC видеопоток, который будет перенаправлен на Youtube. Для этого потребуется локальный железный сервер на 64-битной Linux системе или VPS сервер у хостера. Минимальные требования: 1 ядро процессора и 1 гигабайт RAM, Linux x86_64.

В локальной сети обнаружили старенький двухъядерный Athlon 64 бит, 1.8 GHz с установленной на него CentOS 6 и 2 гигабайтами RAM. Для экспериментов решили использовать его.

Процесс установки описан на сайте разработчика.

1. Скачиваем архив

wget https://flashphoner.com/download-wcs5-server.tar.gz

При скачивании wget ругается на сертификаты. Приходится добавлять флаг:

wget --no-check-certificate https://flashphoner.com/download-wcs5-server.tar.gz

2. Распаковываем

tar -xzf download-wcs5-server.tar.gz

3. Запускаем инсталлятор

./install.sh

При инсталляции выдаёт ошибку и указывает на отсутствие Java.

4. Устанавливаем java c помощью менеджера пакетов, после чего запускаем инсталлер снова.

yum install java
./install.sh

Во время инсталляции, инсталлер спрашивает, не в локальной ли сети находится сервер. Отвечаем утвердительно ‘yes’, после чего инсталлер прописывает в настройки локальный IP адрес сервера 192.168.1.59.

5. Далее запускаем сервер.

service webcallserver start

Запуск сервера занимает около минуты.

6. Открываем dashboard по адресу 192.168.1.59:8888 в Chrome

image

Браузер ожидаемо жалуется на отсутствие нормальных SSL-сертификатов. Позже их можно будет импортировать, например взять бесплатные на letsencrypt.

Сейчас же просто жмем Advanced / Proceed и подтверждаем исключение безопасности.

7. По девелоперской документации нужно сделать еще одну вещь, относящуюся к сертификатам. Нужно сделать тоже самое на странице: 192.168.1.59:8443

Это для того чтобы сигнальные websocket соединения также проходили. Без них не будет работать WebRTC, т.к. Для его работы требуется обмен SDP через отдельное соединение.

image

После этих двух манипуляций с сертификатами, должна открыться страница Dashboard с демо-примерам. Нужный нам демо-пример называется WebRTC as RTMP re-publishing и выглядит так:

image

Давайте его протестируем в браузере Google Chrome. Задача этого примера — отправить WebRTC аудио+видео поток на Web Call Server 5, конвертировать в RTMP и перенаправить по заданному направлению.

image

Для начала тестирования достаточно нажать кнопку Start и разрешить использование камеры и микрофона по запросу браузера.

На скриншоте сверху происходит следующее:

1. Устанавливается соединение браузера Google Chrome и Web Call Server 5 по протоколу websocket через защищенное соединение: wss://192.168.1.59:8443

2. WebRTC аудио+видео поток отправляется на сервер и отображается статус PUBLISHING, который говорит об успешной отправке видеопотока на сервер.

3. Web Call Server перенаправляет полученный WebRTC аудио+видео поток на указанный RTMP адрес:

  • rtmp://localhost:1935/live
  • stream1

Таким образом RTMP видеопоток перенаправляется на localhost, т.е. На тот же самый сервер 192.168.1.59 в нашем случае. Т.е. Можно сказать, что Web Call Server принял WebRTC поток и завернул его на самого себя как RTMP.

Обратите внимание, как это коррелирует с Youtube Live. Там мы указывали Server URL и Stream name / key

image

4. Далее остается проиграть видеопоток во встроенном плеере. Там автоматически формируется адрес и проставляется имя потока.

image

Встроенный в страницу RTMP плеер очень простой и позволяет убедиться, что стрим на месте и воспроизводится корректно.

Полный адрес стрима выглядит так: rtmp://192.168.1.59:1935/live/rtmp_stream1

Здесь нужно обратить внимание на важную деталь — Web Call Server 5 подставляет в название стрима префикс rtmp_. Т.е. принимает поток с названием stream1, а перенаправляет его как rtmp_stream1. Это важно для тестирования на localhost, чтобы имена стримов были разными.

Локальное тестирование прошло успешно и пришла пора отправить стрим на Youtube Live.
Вспомним, что для тестирования Youtube Live c RTMP live video encoder мы использовали

Server URL: rtmp://a.rtmp.youtube.com/live2
Stream name / key: myfm-c9td-etew-eqdf

Т.е. Youtube ожидает от нас имени видеопотока именно такого и никакого иначе: myfm-c9td-etew-eqdf. И если Web Call Server проставит префикс rtmp_, то результирующее имя будет rtmp_myfm-c9td-etew-eqdf и Youtube не примет поток.

Для того чтобы это обойти, редактируем конфиг /usr/local/FlashphonerWebCallServer/conf/flashphoner.properties на стороне сервера.
Комментируем или убираем строку конфига:

#rtmp_transponder_stream_name_prefix =rtmp_

Тем самым, говорим серверу не проставлять префикс и перенаправлять полученный стрим с тем же именем.

image

Изменение данной настройки требует перезагрузки. Выполняем команду перезагрузки сервера и ждем 1 минуту.

service webcallserver restart

После перезагрузки переходим к заключительному этапу тестирования. Снова открываем dashboard и WebRTC as RTMP re-publishing демо-пример, но на этот раз вводим RTMP адрес в точности как для Live Encoder.

image

И наконец, открываем Youtube Live и смотрим результат:

image

На этот раз нам удалось пробросить WebRTC видеопоток на Youtube как RTMP и получить картинку.

В браузере Google Chrome во вкладке chrome://webrtc-internals можно увидеть графики, описывающие доставку WebRTC видеопотока на сервер:

image

На стороне Youtube, входящий трафик выглядит так:

image

Очень похоже на HTTP Live streaming (HLS) с подгрузкой видео-сегментов по протоколу HTTP (HTTPS).

Отлично, у нас получилось протестировать и убедиться что это действительно работает. Картинка есть, звук есть, видеопоток идет прямо из браузера и попадает на Youtube.

Теперь можно переходить к программированию. А именно, мы хотели бы иметь возможность сделать тоже самое с простой HTML-страницы и в перспективе со своего веб-сайта или веб-приложения.

Программирование HTML-страницы, отправляющей WebRTC на Youtube

Проще всего было бы разобраться в примере, скачав три файла с исходниками: HTML, JavaScript, CSS. Но мы не ищем легких путей и хотим создать минимальную страницу с нуля (так сказать from scratch).

Начинаем с создания болванки test-webrtc-youtube.html

<!DOCTYPE html>
<html>
<head lang="en">
   <meta charset="UTF-8">
   <title></title>
</head>
<body>
</body>
</html>

Теперь нужно скачать скрипт flashphoner.js, который делает всю работу, связанную с WebRTC и передачей видеопотока на сервер. Этот скрипт входит в Web SDK, которое доступно для скачивания по этой ссылке.

Скачиваем и распаковываем Web SDK на отдельный сервер, где установлен Apache (у кого-то Nginx).

wget https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/flashphoner-api-0.5.14.1977-48448b99eddb0da1248519290dba2d4d00d4a505.tar.gz

Создаем папку /var/www/html/test-webrtc-youtube в которой будет находиться html-страница и копируем в эту папку html и js файлы:

— test-webrtc-youtube.html
— flashphoner.js

Получается такая структура:

test-webrtc-youtube
-- flashphoner.js
-- test-webrtc-youtube.html

1. Добавляем на страницу следующие элементы:

<body onload="init_page()">
   <div id="localVideo" style="width:320px;height:320px;border: 1px solid"></div>
   Server URL <input type="text" id="urlServer" value="wss://192.168.1.59:8443"/><br/>
   Stream URL: <input type="text" id="rtmpUrl" value="rtmp://a.rtmp.youtube.com/live2"/><br/>
   Stream name / key: <input type="text" id="streamName" value="myfm-c9td-etew-xxxx"/><br/>
   <input type="button" onclick="publishToYoutube()" value="Start"/>
   <p id="status"></p>
</body>

1) localVideo — это просто div-блок, в который будет помещено видео с веб-камеры
2) urlServer, rtmpUrl, streamName — уже знакомые из предыдущего тестирования поля
3) status — в этом поле отображается статус соединения или потока

2. Добавляем три переменных:

var SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
var STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
var localVideo;

Первые две являются просто сокращением. Переменная localVideo будет хранить ссылку на div-элемент.

3. Инициализируем API

function init_page() {
   Flashphoner.init();
   localVideo = document.getElementById("localVideo");
}

4. Подключение к WCS серверу и начало стриминга.

function publishToYoutube(){
   var urlServer = document.getElementById("urlServer").value;
   Flashphoner.createSession({urlServer: urlServer}).on(SESSION_STATUS.ESTABLISHED, function(session){
       //session connected, start streaming
       startStreaming(session);
   }).on(SESSION_STATUS.DISCONNECTED, function(){
       setStatus("Connection DISCONNECTED");
   }).on(SESSION_STATUS.FAILED, function(){
       setStatus("Connection FAILED");
   });
}

При успешном подключении по событию ESTABLISHED, начинается стриминг вызовом функции startStreaming

5. Отправка видеопотока.

function startStreaming(session) {
   var streamName =  document.getElementById("streamName").value;
   var rtmpUrl =  document.getElementById("rtmpUrl").value;
   session.createStream({
       name: streamName,
       display: localVideo,
       cacheLocalResources: true,
       receiveVideo: false,
       receiveAudio: false,
       rtmpUrl: rtmpUrl
   }).on(STREAM_STATUS.PUBLISHING, function(publishStream){
       setStatus(STREAM_STATUS.PUBLISHING);
   }).on(STREAM_STATUS.UNPUBLISHED, function(){
       setStatus(STREAM_STATUS.UNPUBLISHED);
   }).on(STREAM_STATUS.FAILED, function(){
       setStatus(STREAM_STATUS.FAILED);
   }).publish();
}

Здесь мы создали стрим и вызвали для него функцию publish.

6. Все статусы отображаем отдельной функцией.

function setStatus(status){
   document.getElementById("status").innerHTML = status;
}

В конечном счете получили примерно тоже самое, что и при использовании демо из коробки.

Результат выглядит так:

image

Обратите внимание, что снова используется протокол https. Ваш веб-сервер должен быть настроен для работы через https. Обычно это делается достаточно просто, установкой mod_ssl:

yum install mod_ssl

Код HTML — страницы занял ровно 65 строк и выглядит так:

image

А скачать исходники можно здесь

В результате мы создали HTML-страницу размером 65 строк, включая скрипты, которая с использованием файла API flashphoner.js отправляет WebRTC видео на Web Call Server, который в свою очередь перенаправляет этот видеопоток на сервис Youtube Live.

На этом все. Для желающих повторить привожу использованные в статье ссылки и материалы.

Ссылки:

1) Youtube Live
2) Adobe Flash Media Live Encoder
3) Wirecast
4) Web Call Server (используемая версия 2047)
5) WebRTC
6) Исходники HTML+Javascript
7) Google закрывает Hangouts API

Автор: amayabay

Источник

Поделиться

* - обязательные к заполнению поля