Во всех наших приложениях сотрудники могут общаться при помощи встроенного чата. При этом все чаще можно увидеть приложения, которые позволяют общаться пользователям по видеосвязи без перехода в сторонние сервисы.
В этой статье я расскажу про удобный способ создания такого функционала. Расскажу про готовые инструменты, опишу основные моменты, мысли, ссылки. Будет интересно!

Что такое WebRTC
Web Real Time Communications — это технология, которая позволяет осуществлять передачу аудио и видео потоков. На базе нее строятся приложения для видеконференций, например, Google meet, также ее применяют в приложениях для совместой работы (miro) и социальных сетях (vk). Подробно описывать WebRTC не будем, на эту тему полно статей и документации, сосредоточемся на технологии Angular.
Openvidu
Это платформа для создания видеозвонков основанная на webrtc. Она включает в себя бекенд реализацию и клиентские библиотеки. Мы сосредоточимся на клиенте так как статья посвящена Angular.
Приведем возможности клиентской бибилиотеки Openvidu:
-
Осуществлять аудио/видео звонки
-
Демонстрировать экран
-
Поддержка чата
-
Возможность переключения устройств ввода/вывода
-
Определение речи
-
Кастомизация клиентских библиотек
Многие возможности мы рассмотрим на примерах ниже.
Основные объекты из API Openvidu для построения приложения:
-
OpenVidu — класс отвечающий за основную точку входа для работы с webRtc
-
Session — представляет из себя реализацию звонков. По сути комната в рамках которой участники конференции могут взаимодействовать
-
Publisher — описывает участника сессии, который стримит аудио/видео поток
-
Subscriber — описывает участника, который может получать аудио/видео поток от Publisher в рамках сессии
Подготовка окружения
Для демо приложения воспользуемся готовым docker контейнером, который содержит в себе сервер openvidu. Документацию для установки можно найти по ссылке.
Предпологается, что у вас установлен docker
Для запуска контейнера необходимо выполнить следующую команду.
docker run -p 4443:4443 --rm -e OPENVIDU_SECRET=MY_SECRET openvidu/openvidu-server-kms:2.20.0
Также для разработки и тестирования могут потребоваться виртуальные камеры. Можно рассмотреть следущие:
-
SplitCam
-
ManyCam
С помощью них можно подставить любое видео в качестве видеопотока для приложения. А также API браузера сможет определять виртуальные устройства в качестве источника.
Эти два простых шага достаточны для создания клиентского демо приложения. Приступим!
Создание приложения
Для примера создадим приложение для совещаний, в котором будут находиться N пользователей. Каждый из них будет иметь возможность совершать базовые действия в приложении:
-
Подключаться к конференции
-
Включать/выключать видео/аудио
-
Демонстрировать экран
-
Идентифицировать говорящего
Подключение участников к видеоконференции
Создадим video-call.service.ts, который будет отвечать за работу с OpenVidu и упралять логикой видеозвонка. Для начала реализуем подключение к серверу и создание сессии join:
join() { this.session = this.OV.initSession(); this.subscribeSessionEvents(); from(this.getToken()) .pipe( switchMap((token: string) => { return from(this.session.connect(token, { clientData: this.userName })) }), tap(() => { this.initPublisher(); }) ).subscribe(); }
В этом методе происходит следующее:
-
создание объекта сессии
-
подписка на события сессии
-
получение токена с сервера
-
подключение к сессии видеозвонка
-
создание паблишера
Рассмотрим подробнее создание паблишера:
initPublisher() { const publisher: Publisher = this.OV.initPublisher('', { audioSource: undefined, videoSource: this.deviceId, publishAudio: true, publishVideo: true, resolution: '640x480', frameRate: 30, insertMode: 'APPEND', mirror: false }); this.session.publish(publisher); this.currentUser$.next(publisher); }
initPublisher создает инстанс паблишера в который передаются настройки:
-
audioSource/videoSource — источники звука и видео. Это могут быть все возможные физические и виртуальные камеры и микрофоны
-
publishAudio/publishVideo — состояние публикации звука или видео
-
а также различные настройки качества и разрешения видео
Для трансляции видео нужно сделать компонент в котором будет связываться элемент video и видеопоток.
Шаблон компонента, который содержит тег video
<div class="ov-video"> <video #videoElement></video> </div>
Код компонента. В нем происходит получение ссылки на video элемент и при помощи API openvidu и метода addVideoElement видеопоток привязвается к html.
@ViewChild('videoElement') elementRef: ElementRef | undefined; _streamManager: StreamManager; ngAfterViewInit() { this._streamManager.addVideoElement(this.elementRef.nativeElement); }
Результат работы программы

Демонстрация экрана участником
Демонстрация очень похожа на инициализацию камеры за исключением того что в качестве видеоисточника указывается ‘screen’
initScreenPublisher() { const publisher: Publisher = this.OV.initPublisher('', { audioSource: undefined, videoSource: 'screen', publishAudio: true, publishVideo: true, resolution: '640x480', frameRate: 30, insertMode: 'APPEND', mirror: false }); this.session.publish(publisher); this.currentUser$.next(publisher); }
Результат работы

Выключение/включение камеры/звука участниками
Для того чтобы отключить или включить видео/звук нужно воспользоваться следующими методами у паблишера
enableVideo() { this.currentUser$.value.publishVideo(true); this.videoEnabled = true; } disableVideo() { this.currentUser$.value.publishVideo(false); this.videoEnabled = false; }
Подсветка говорящего участника с помощью API определения речи
В начале создания приложения мы вызывали subscribeSessionEvents, настало время его рассмотреть подробнее:
subscribeSessionEvents() { this.session.on('streamCreated', (event: any) => { const subscriber: Subscriber = this.session.subscribe(event.stream, ''); this.users$.value.push(subscriber); this.users$.next([...this.users$.value]); }); this.session.on('streamDestroyed', (event: any) => { // Удалить пользователя с конференции }); this.session.on('publisherStartSpeaking', (event: any) => { // пробросить событие и подстветить юзера с event.connection.connectionId }); this.session.on('publisherStopSpeaking', (event: any) => { // пробросить событие и подстветить }); }
Сессия сама предоставляет нам информацию об участнике который начинает и заканчивает говорить
-
publisherStartSpeaking — участник начинает говорить в объекте event содержится идентификатор участника, имея эту информацию можно выдеделить компонент этого участника
-
publisherStopSpeaking — по этому событию можно снять выделение участника
Переключение камеры
Есть два сценария выбора камеры
-
при инициализации паблишера
-
при переключении во время публикации
Для первого варианта необходимо получать информацию о текущих девайсах устройства, для этого можно воспользоваться как стандартными браузерными API так и оберткой из OpenVidu
getDevices() { from(this.OV.getDevices()) .pipe( tap(x => { const videoDevices = x.filter(x => x.kind === 'videoinput'); ..... }) ).subscribe(); }
Устройства можно вывести в выпадающий список в интерфейсе и при выборе его устанавливать значение deviceId в паблишер (методы выше initPublisher)
Для того, чтобы переключать камеры в режиме реального времени, нужно получить mediaStream из выбранного устройства
selectCamera(value) { this.videoCallService.getVideoMediaTrack({videoSource: value}).pipe( untilDestroyed(this), tap(mediaTrack => { if (mediaTrack) { this.videoCallService.videoMediaTrack$.next(mediaTrack); } } )).subscribe(); }
Далее воспользуемся API:
replaceTrack(track: MediaStreamTrack) { this.publisher.replaceTrack(track).then(() => ... .catch(error => console.error('Error replacing track')); }
На этом этапе мы научились делать весь фукнкционал который обозначили в начале статьи
Рекомендации, решения, мысли, ссылки
-
В Chrome существует особая политика с автовоспроизведением видео. Ее стоит учитывать, так как существуют сценарии когда видеопоток не будет стартовать, например пока пользователь не сделает какое-либо действие на странице.
-
Помимо трансляции видео с камеры( виртуальной камеры) или рабочего стола, можно транслировать обычное видео с помощью API браузера — captureStream
-
Документация MediaStream — в ней можно узнать детали потоков медиаданных
-
Для включения видеоэкрана «во весь экран» можно воспользоваться API requestFullscreen
-
В одной из статей я писал про технологию Web Speech API. Интересно можно ли ее применить для WebRTC, например, для преобразования аудиопотока в текст прямо в браузере. Был ли у вас такой опыт?
-
У ZOOM есть свой sdk для построения подобных приложений, интересны его возможности
Заключение
Сейчас все больше приложений позволяют осуществлять видеозвонки — от социальных сетей до приложений для совместной работы. С помощью технологии WebRTC вы можете улучшить пользовательский опыт ваших клиентов, дав им возможность звонить из приложений.
ссылка на оригинал статьи https://habr.com/ru/company/europlan/blog/595731/
Добавить комментарий