Стриминг видеозвонков по RTMP

zyisxywts0ok9pzset52n9xt8fk.png


Сегодня стриминг-платформы на пике популярности, так как миллионы талантливых людей регулярно делятся своими знаниями — читай, используют стриминг на всю катушку. Так как этот рынок растет, то существует и масса приложений, которые могут стримить видео в реальном времени, используя камеру смартфона или ноутбука. Возможно, вы тоже хотите внедрить в ваше приложение такую функциональность; если так, то спешим обрадовать — теперь Voximplant позволяет прокидывать видеозвонки по RTMP в любой CDN, который поддерживает этот протокол.

Эта функциональность стала возможна благодаря новому модулю Voxengine — StreamingAgent. Под катом вас ждут 5 шагов по настройке этой интеграции, добро пожаловать!

Схема


utqvc_ywlxmexe__hqqhfzh7wyc.png


Видеозвонок из мобильного/веб-приложения или SIP приходит в наше облако, которое направляет его в стриминговый CDN. В свою очередь, CDN отправляет аудио- и видеопотоки конечным пользователям — как он обычно и делает. Обратите внимание, что RTMP поддерживает только H.264, поэтому очень важно явно указывать этот кодек при стриминге.

Вам понадобятся


  • аккаунт на стриминговом сервисе, например, Twitch или Youtube;
  • аккаунт Voximplant. Если у вас его нет, то регистрация живет здесь;
  • приложение Voximplant, а также сценарий, правило и один пользователь. Все это мы создадим в этом туториале;
  • веб-клиент для захвата видео и аудио — воспользуемся нашей демкой videochat


1. Настройки стриминга


Первым делом вам нужно будет получить значения двух параметров, который мы используем в облачном сценарии — stream name/key и server URL. Ниже показано, как получить эти значения на примере Twitch и YouTube.

Twitch


Зайдите в аккаунт, нажмите на аватарку в правом верхнем углу и выберите Video Producer.

cplfn7v5zf_luwn8jrv7ptez5ai.png

В разделе Settings выберите Channel, а затем нажмите Copy в верху страницы — так вы получите ваш Primary Stream Key. Обратите внимание, что ключ доступен только при активированной двухфакторной аутентификации. Вставьте это значение в ваш текстовый редактор или просто оставьте эту страницу открытой, чтобы скопипастить значение позже.

Чтобы найти server url, зайдите на страницу stream.twitch.tv/ingests, выберите один из рекомендованных серверов и скопируйте его без последнего слэша, например: rtmp://live-sfo.twitch.tv/app

YouTube


Войдите в аккаунт, нажмите на аватарку в правом верхнем углу и выберите YouTube Studio (beta).

z6ymjdecbhzwvkxrr9tnwux2whm.png

Если у вас нет канала на YouTube, то появится диалог о создании канала. Нажмите Create channel и вы увидите дашборд созданного канала с уведомлением, что стриминг будет возможен в течение 24 часов.

jkvte_pkxhn3v9zffgtkcor7p8s.png

Находясь в YouTube Studio, через меню слева зайдите в Other features —> Live stream now. Откроется новая страница, внизу которого будет блок Encoder setup. Отсюда необходимо взять значения Server URL и Stream name/key (либо оставить страницу открытой).

2arxqwczdmsctf6lgaelw9df1yw.png

2. Настройки VOXIMPLANT


Теперь надо сделать настройки со стороны Voximplant. Сначала войдите в свой аккаунт: https://manage.voximplant.com/auth. В меню слева нажмите «Приложения», затем «Новое приложение» и создайте приложение с именем streaming. Зайдите в новое приложение, переключитесь на вкладку «Сценарии», чтобы создать сценарий startStream с таким кодом (не забудьте подставить значения из предыдущего шага в строках 8 и 9):

require(Modules.StreamingAgent);

VoxEngine.setVideoCodec("H264");

VoxEngine.addEventListener(AppEvents.CallAlerting, function (e) {
  const streaming = VoxImplant.createStreamingAgent({
    protocol: "RTMP",
    url: "rtmp://live-sfo.twitch.tv/app",
    streamName: "live_********************",
    keyframeInterval: 4
  });

  e.call.sendMediaTo(streaming);

  streaming.addEventListener(StreamingAgentEvents.Connected, function (e) {
    Logger.write("LOG: StreamingAgentEvents.Connected: " + e.reason);
  });
  streaming.addEventListener(StreamingAgentEvents.Disconnected, function (e) {
    Logger.write("LOG: StreamingAgentEvents.Disconnected: " + e.reason);
  });
  streaming.addEventListener(StreamingAgentEvents.ConnectionFailed, function (e) {
    Logger.write("LOG: StreamingAgentEvents.ConnectionFailed: " + e.reason);
  });
  streaming.addEventListener(StreamingAgentEvents.Error, function (e) {
    Logger.write("LOG: StreamingAgentEvents.Error: " + e.reason);
  });
  streaming.addEventListener(StreamingAgentEvents.StreamStarted, function (e) {
    Logger.write("LOG: StreamingAgentEvents.StreamStarted: " + e.reason);
  });
  streaming.addEventListener(StreamingAgentEvents.StreamError, function (e) {
    Logger.write("LOG: StreamingAgentEvents.StreamError: " + e.reason);
  });
  streaming.addEventListener(StreamingAgentEvents.StreamStopped, function (e) {
    Logger.write("LOG: StreamingAgentEvents.StreamStopped: " + e.reason);
  });

  e.call.answer();

  e.call.addEventListener(CallEvents.Disconnected, function (e) {
    Logger.write("LOG: terminating in 6 secs");
    setTimeout(VoxEngine.terminate, 6000);
  });
});


Это простой сценарий, который инициирует стрим, а также отслеживает все его возможные состояния, как то: Connected, Connection failed, StreamStarted и т.д. — подробности работы сценарии будут чуть ниже. Сейчас же вам надо перейти на вкладку «Роутинг» вашего приложения и нажать «Новое правило». Назовите его streamRule, укажите сценарий startStream и оставьте маску по умолчанию (.*).

n00mvrvezfouzra2cxzg5d57t5i.png


Последнее, что надо сделать на этом этапе — создать пользователя. Перейдите на вкладку «Пользователи», нажмите «Создать пользователя», укажите имя (например, user1) и пароль, затем кликните «Создать». Эта пара логин-пароль понадобятся нам для аутентификации в веб-клиенте.

m7nfnx1ep_iu05e5aukzrk5qtsi.png


Конфигурация Voximplant закончена, но прежде чем мы перейдем к веб-клиенту, предлагаю разобраться, как работает модуль StreamingAgent в нашем сценарии.

3. Сценарий


Модуль StreamingAgent позволяет разработчикам запускать стримы по RTMP на популярные стиминговые платформы. Чтобы использовать функциональность модуля, мы должны подключить его в самом начале сценария:

require(Modules.StreamingAgent);


Далее необходимо явным образом указать кодек, который будет использоваться при стриминге. Так как многие платформы (Twitch и YouTube в том числе) используют RTMP, который, в свою очередь, поддерживает H.264, именно его мы и укажем:

VoxEngine.setVideoCodec("H264");


Если кодек не указан, то может быть вызвано событие StreamingAgentEvents.StreamError, содержащее текст об ошибке:

"Video codec mismatch. " + codecName + " granted, but should be H.264"


Затем мы добавляем обработчик для события CallAlerting, чтобы обработать видеозвонок из веб-клиента (да-да, скоро мы до него дойдем). Первым делом мы добавим в обработчик вызов метода createStreamingAgent. У метода есть следующие параметры, большинство из них — обязательные, опциональные отмечены отдельно:

  • protocol — пока поддерживается только RTMP;
  • url — server URL, см. шаг 1;
  • streamName — stream name/key, см. шаг 1;
  • applicationName (опциональный) — часть streamName, например, live2. Используйте этот параметр, если этого требует выбранная платформа;
  • keyframeInterval (опциональный, секунды) — как часто будет создаваться ключевой кадр в стриме. Если не указан, то по умолчанию стоит значение 2.


Выше, в листинге сценария, вызов метода createStreamingAgent выглядит так:

VoxEngine.addEventListener(AppEvents.CallAlerting, function (e) {
  const streaming = VoxImplant.createStreamingAgent({
    protocol: "RTMP",
    url: "rtmp://live-sfo.twitch.tv/app",
    streamName: "live_********************",
    keyframeInterval: 4
  });


Но мы можем опустить keyframeInterval и использовать applicationName, вот так:

VoxEngine.addEventListener(AppEvents.CallAlerting, function (e) {
  const streaming = VoxImplant.createStreamingAgent({
    protocol: "RTMP",
    url: "rtmp://a.rtmp.youtube.com/",
    applicationName: "live2",
    streamName: "somename"
  });


После того как создан объект стриминга, сценарий продолжает обрабатывать звонок внутри обработчика. Следующий шаг — направить входящий видеопоток из веб-клиента в созданный объект стриминга:

e.call.sendMediaTo(streaming);


Затем мы используем все возможные стриминговые события для отладки: обработчики ничего не делают, кроме отправки сведений в лог Voximplant-сессии. Вы можете не использовать этот кусок кода, если хотите.

После обработки событий сценарий отвечает на входящий звонок:

e.call.answer();


Наконец, мы должны корректно обработать окончание стриминга, когда веб-клиент прекращает отправку видео. Формально, мы можем не использовать и этот обработчик тоже, но при этом сессия закончится только по спустя 60 секунд после прекращения отправки видео. В этом ожидании нет смысла, поэтому лучше завершать сессию, отталкиваясь от событий Disconnected:

e.call.addEventListener(CallEvents.Disconnected, function (e) {
    Logger.write("LOG: terminating in 6 secs");
    setTimeout(VoxEngine.terminate, 6000);
  });


Понимая логику сценария, мы готовы приступить к последней –, но не по значению — части нашей конфигурации.

4. Веб-клиент


Клонируйте или скачайте наше демо videochat. Затем перейдите в папку репозитория и откройте файл WebApp/JS/app.js в текстовом редакторе/IDE. Измените имя приложения на 5 строке и сохраните файл:

tupxqtvsfoavctgugqzllleskea.gif


Собственно, всё.

5. Запускаем стриминг


Вам нужно запустить папку WebApp локально или на вашем веб-сервере. Для локального запуска можете воспользоваться утилитой live-server или приложением Web Server for Chrome. При запуске веб-клиента вы должны передать ему имя вашего аккаунта Voximplant, например:

http://127.0.0.1:8080/index.html#accname=johngalt

Запустив клиент, введите пару логин-пароль из пункта 2:

wq6uyyk0sjhb8psdxj7prt3p0s4.png


Введите любый набор символов рядом со знаком @ и нажмите Call. Если все было сделано правильно, скоро начнется ваш стрим :) Успешных вам стримов и продуктивной разработки!

© Habrahabr.ru