Video live streaming - это технология потоковой трансляции видео тысячам и миллионам зрителей в режиме близком к реальному времени. Видеостриминг находит своё применение в различных областях: фитнес и образование; онлайн события: презентации, конференции, семинары; электронная коммерция; музыкальные концерты; игры и киберспорт. В этой статье мы рассмотрим, как можно легко интегрировать видеотрансляции в приложение или на сайт, используя Amazon Interactive Video Service. AWS Interactive Video Service - это решение для прямых трансляций, которое быстро интегрируется в мобильные и веб-приложения. В рамках своего сервиса Amazon предлагает: быстрое создание новых трансляций в течении пары минут; низкая (менее 3 секунд) задержка доставки видеопотока для зрителей; простая интеграция с мобильными приложениями и веб-сайтами через SDK для трансляции и проигрывания видео; масштабирование до десятков тысяч одновременных зрителей; сохранение трансляции для просмотра в записи. Ещё одна интересная возможность - это встраивание в трансляцию метаданных с гарантией их получения всеми зрителями. Метаданные будут синхронизированы с видео- и аудиопотоками. С помощью этой функциональности можно добавлять интерактивное взаимодействие со зрителями: обновлять статистику в видеоигре; показывать зрителю опросник и давать возможность выбрать ответ во время вебинара; предоставлять информацию о продукте и давать возможность купить демонстрируемый товар во время трансляций в e-commerce приложениях. Amazon предоставляет SDK для iOS, Android и Web для интеграции вещания и проигрывания видео. Также на сайте AWS можно найти SDK для работы с IVS более чем на 10 языках программирования, включая Java, Python и Go. Чтобы понять как работать с AWS IVS, давайте реализуем пример, состоящий из трёх компонент: стриминг видео из браузера; проигрывание видео в браузере; управление каналами и отправка метаданных зрителям на бэкенде. Начнём с создания минималистичной веб-страницы, на которой мы организуем вещание видеотрансляции. Создадим html страницу и включим туда ссылку на broadcast SDK: Далее нужно добавить canvas для отображения видео, которое мы будем транслировать: Добавим также на страницу input элементы для ingest endpoint и stream key: Ingest endpoint - это url сервера Amazon, куда будут отправляться видео- и аудиопотоки. Stream Key - текстовый ключ, который уникально идентифицирует канал вещания. Они предоставляются Amazon после создания канала. Ну и ещё нам понадобятся 2 кнопки для запуска и остановки трансляции: Как вы видите, на событиях onclick вызываются функции startBroadcast() и stopBroadcast(). Про них поговорим чуть позже. С веб-страницей мы закончили, поэтому теперь перейдем к javascript коду. Первым делом нам надо создать broadcast client: SDK предлагает несколько предопределенных конфигураций, которыми можно воспользоваться. Полный список можно посмотреть в документации к библиотеке. Давайте для примера возьмём IVSBroadcastClient.BASIC_LANDSCAPE. Чтобы отобразить на странице видео, которое мы будем захватывать с помощью камеры, привяжем созданный клиент к элементу preview: Чтобы получить список устройств, с которых мы можем производить захват видео и аудио, сделаем navigator.mediaDevices.enumerateDevices(): Теперь нужно получить поток одного из доступных видео устройств и зарегистрировать его в broadcast client: То же самое нужно сделать и для аудиопотока: На этом мы закончили с конфигурацией клиента. Если открыть получившуюся html страницу, то браузер запросит разрешение на использование видеокамеры и микрофона. После полученных разрешений на странице появится изображение с камеры. Всё почти готово к отправке медиапотоков на сервера AWS и началу трансляции. Осталось несколько штрихов. Во-первых, напишем обработчика для кнопки Start Broadcast: Тут мы получаем ingest endpoint и stream key из input элементов на странице и вызываем метод startBroadcast() у клиента. Во-вторых, сделаем остановку вещания через метод stopBroadcast: Итак, для вещания трансляции всё готово. Перейдем к интеграции веб-плеера для проигрывания трансляции зрителям. Также, как и в примере с вещанием, создадим простую веб-страницу. Включим ссылку на Amazon IVS Player на нашу страницу: Добавим на страницу 3 блока: поле для ввода url видеотрансляции, счётчик онлайн зрителей и видео элемент для плеера: С html кодом для страницы плеера закончили. Теперь перейдем к javascript коду. Первым делом проверим, поддерживает ли браузер плеер от Amazon: Далее создадим сам плеер и привяжем его к video элементу на странице: У плеера есть метод addEventListener, через который можно добавить подписчиков на изменения состояния трансляции и получать уведомления о них. В нашем примере нас интересуют 2 события: об ошибке и о полученных метаданных. Именно через метаданные потока мы будем передавать текущее количество онлайн зрителей. Напишем функцию, которая будет выводить ошибку пользователю на события ERROR и обновлять значение в элементе viewers при получении новых метаданных в трансляции: Всё почти готово. Нам только осталось запустить проигрывание потока. Для этого у плеера есть функция load, которая принимает url видеопотока. Чтобы запустить проигрывание, нужно вызвать play(). Для запуска проигрывания подпишемся на обновления поля playback-url: Проигрывание готово. Вещания и проигрывания трансляций недостаточно, чтобы интегрировать AWS Interactive Video Service. Наверняка вы не захотите создавать трансляции вручную, поэтому потребуется автоматизация на бэкенде. Amazon предоставляет SDK для взаимодействия с API их сервисов для большинства популярных языков программирования. В нашем примере давайте напишем бэкенд на Golang. Создадим go module в директории проекта: Подключим в проект зависимости на aws sdk, прописам их в go.mod: Чтобы подключиться к API Amazon из кода, надо получить AWS access keys. Это можно сделать в веб-интерфейсе AWS: перейдите в IAM console в меню слева выберите Users далее выберите своего пользователя или создайте нового во вкладке Security credentials нажмите Create access key скачайте созданные секреты и сохраните в ~/.aws/credentials Также нужно в файл ~/.aws/config сохранить регион по умолчанию, в котором у нас будут трансляции: Перейдем к написанию клиента, который будет в нашем бэкенде обёрткой к обращениям к AWS API. Сначала загрузим конфигурацию из ~/.aws/config и создадим клиент к API IVS: Теперь мы можем использовать созданный клиент для общения с API IVS. Перейдем к созданию нового Channel (канал), в который можно будет транслировать видео. Канал в терминах Amazon хранит всю конфигурацию, относящуюся к трансляции. При создании канала можно указать несколько важных настроек: LatencyMode. Данный параметр принимает 2 значения: NORMAL и LOW. LOW значение по умолчанию и означает низкую задержку доставки медиапотока зрителям. Type. Тип канала может быть BASIC или STANDARD. BASIC означает, что видео будет доставляться зрителям без перекодирования. STANDARD подразумевает, что видео будет перекодировано и оптимизировано под устройства пользователей и состояние их сети. По умолчанию используется режим STANDARD. Name. Можно задать имя, чтобы было проще ориентироваться между каналами. Например, в Name можно указать текстовый id трансляции во внутренней системе. Метод CreateChannel() возвращает описание Channel. Нас оттуда интересуют следующие поля: Arn - уникальный amazon resource name. Его нужно куда-нибудь сохранить, например, в базу, т.к. он нам понадобится позднее для работы с каналом через API Amazon. IngestEndpoint и StreamKey - этот url и ключ, которые понадобятся для отправки видео- и аудиопотоков. PlaybackUrl - это url для просмотра видеопотока зрителями. Запустим, что у нас получилось к данному моменту: Если вы перейдете в раздел IVS в интерфейсе AWS, то увидите в списке новый канал под названием test. Ранее мы обсудили, что будем через метаданные потока передавать текущее количество онлайн зрителей. API Amazon предоставляет объект Stream, в котором представлены следующие поля: ViewerCount - текущее количество зрителей. State - состояние стрима, принимает значения LIVE и OFFLINE. Health обозначает уровень "здоровья" стрима. Доступные значения HEALTHY, STARVING и UNKNOWN. Состояние STARVING означает, что есть проблемы с отправкой видео/аудиопотоков. Например, у ведущего трансляции наблюдаются проблемы с интернетом, и происходят задержки отправки потоков. StartTime - время начала трансляции. Полный список доступных полей можно посмотреть в документации. Нас больше всего интересует поле ViewCount. Именно его мы будем использовать, чтобы отправлять эти данные зрителям. Чтобы получить данные о Stream, мы можем воспользоваться методом GetStream(). На входе ему надо передать ARN канала: Чтобы добавить метаданные в медиапоток, существует метод PutMetadata(). Этот метод принимает ARN канала и строку-метаданные. Важно отметить, что максимальный размер метаданных, которые можно передать за один вызов, ограничен 1KB. Это ограничение стоит держать в голове, потому что передавать мегабайты текста, к сожалению, не получится. Также при вызове PutMetadata() стоит сделать проверку, находится ли Stream в состоянии вещания (LIVE). Иначе AWS вернёт ошибку ChannelNotBroadcasting. Теперь объединим методы GetStream и PutMetadata и реализуем функцию streamOnlineViewers: Данная функция в цикле запрашивает состояние и отправляет актуальный счётчик онлайн зрителей в метаданные трансляции. Стоит заметить, что метаданные также будут доступны и в записи трансляции. Ну и напоследок давайте реализуем удаление канала. Дело в том, что у AWS есть лимит на количество каналов - 5000 в одном регионе. Поэтому после окончания трансляции имеет смысл канал удалить: Теперь давайте посмотрим, что у нас получилось. В одной вкладке браузера откроем страницу с трансляцией видеопотока и дадим разрешение на доступ к камере и микрофону. На другой откроем страницу с плеером. Запустим наш Go код, чтобы создать новый канал: Далее запустим обновление счётчика онлайн зрителей: Скопируем ingest endpoint и stream key на вкладку с трансляцией видео. Вставим playback url в соответствующее поле на вкладке с плеером. Запустим трансляцию, нажав на кнопку Start Broadcast. На скриншоте видно, что трансляция успешно запустилась, а плеер корректно проигрывает видеопоток. Задержка составляет 4.5 секунды, что немного больше 3 секунд, но тоже достаточно близко. Также видим, что счётчик зрителей показывает 1. Если мы откроем плеер в другой вкладке или зайдем в админку AWS IVS, то счётчик обновится. После окончания трансляции удалим канал: Amazon Interactive Video Service тарифицирует отдельно отправку видео на их серверы (video input) и доставку до зрителей (video output). Отправка оплачивается за час видеопотока. В зависимости от типа выбранного канала (basic или standard) цена за час составляет $0.2 или $2. Доставка также оплачивается за час видеопотока. Цены существенно различаются в зависимости от региона зрителей и общего количества часов, которые были просмотрены. Чтобы понять, сколько это может стоить, посчитаем на примере: 1 час видеотрансляции; 1000 зрителей из Европы, в среднем каждый посмотрел по 30 минут; одна половина зрителей смотрели в HD, а другая - в FullHD. Итого получаем 30 долларов за такую трансляцию:  Мы рассмотрели простой пример, как можно воспользоваться Amazon Interactive Video Service для организации трансляций с низкой задержкой доставки видео зрителям. Amazon сделали удобный сервис, который скрывает всю сложность работы с видеотрансляциями за простым интерфейсом библиотек для разных языков. Interactive Video Service предлагает и другие возможности, которые мы не рассмотрели в этой статье. Например, сохранение трансляций в S3 с возможностью просмотра зрителями в записи. Другой интересной возможностью является IVS Chat для организации общения зрителей во время трансляций. При интеграции с IVS также полезно получать события об изменениях в состоянии трансляций (начало/конец, ошибки, запись стала доступна в S3 для просмотра) через сервис AWS EventBridge. AWS IVS публикует события в EventBridge, на которые можно подписаться в своём бэкенд сервисе. Из минусов Interactive Video Service можно выделить стоимость сервиса: с ростом объёмов цена может начать кусаться. С другой стороны для быстрого старта и проверки полезности функции видеотрансляций для ваших пользователей Amazon Interactive Video Service может отлично подойти. Ну и в заключение список полезных ссылок, которые могут помочь в интеграции Interactive Video Service: https://ivs.rocks/ - сайт с примерами применения. https://aws.amazon.com/ru/developer/tools/ - доступные SDK. https://docs.aws.amazon.com/ivs/latest/userguide/what-is.html - руководство пользователя. https://aws.amazon.com/ivs/pricing/ - цены на сервис. https://github.com/mastersobg/awsivs - репозиторий с исходным кодом для данной статьи.