Pull to refresh

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

Reading time11 min
Views34K


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

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

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

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


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

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



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



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

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



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

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

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


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



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

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



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

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 и еще сотня другая серверов и сервисов.



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



Так как мы достигли некоторого успеха при использовании 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 напрямую из браузера.

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



Таким образом, в трансляции появляется сервер-посредник, который принимает 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



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

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

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

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



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



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



Для начала тестирования достаточно нажать кнопку 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



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



Встроенный в страницу 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_

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



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

service webcallserver restart

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



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



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

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



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



Очень похоже на 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;
}

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

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



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

yum install mod_ssl

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



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

В результате мы создали 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
Tags:
Hubs:
+26
Comments15

Articles