текст перекладу
У цій статті:
- Вступ
- Чому WebRTC?
- Ключові концепції WebRTC
- Створення WebRTC з'єднання
- Реалізація (Signaling сервер на Node.js та фронтенд на React.js)
- P2P з PeerJs
- Огляд SFU та MCU
- Висновки
Вступ
WebRTC (Web Real-Time Communication) — це революційна технологія, яка забезпечує можливість реального мультимедійного зв’язку прямо в веб-браузерах. Вона позбавляє необхідності в сторонніх плагінах або програмному забезпеченні, що дозволяє створювати зручні, ефективні та доступні взаємодії безпосередньо в браузері. У цій статті ми розглянемо, як працює WebRTC, його основні компоненти та реалізуємо додаток для реального часу за допомогою Node.js як signaling сервера та React.js для фронтенду.
Чому WebRTC?
- Нативна реальний зв'язок у браузерах:
WebRTC — єдиний протокол, який дозволяє здійснювати реальний медіа-зв’язок безпосередньо в веб-браузерах, усуваючи залежність від власних плагінів. - Затримка менш ніж в одну секунду:
Завдяки можливості миттєвого передавання даних WebRTC підтримує різноманітні застосунки:
- Відеоконференції: Використовуються такими платформами, як Zoom та Google Meet для багатосторонніх відеодзвінків.
- Ігри в реальному часі: Забезпечує низьку затримку та високу частоту кадрів, що важливо для ігрових застосунків.
- Особисте спілкування: Дає змогу здійснювати особисті взаємодії в таких платформах, як онлайн-навчання та чат-аплікації.
- Відкритий стандарт:
Відкритий стандарт WebRTC гарантує сумісність з основними браузерами та платформами, що сприяє його широкому використанню.
Ключові концепції WebRTC
- Peer-to-Peer (P2P) зв'язок:
WebRTC встановлює прямий зв'язок між двома браузерами, зменшуючи затримки та залежність від серверів.
На зображенні вище показано два браузери, які безпосередньо з'єднані між собою в P2P режимі. У WebRTC P2P з’єднанні медіа-дані (аудіо, відео тощо) передаються безпосередньо між двома пірінгами без проміжних серверів. Це покращує ефективність і зменшує затримку.
Хоча медіа-дані передаються безпосередньо між пірінгами, WebRTC потребує деяких серверів для виконання специфічних завдань, таких як сигналізація, проходження NAT та обробка медіа.
- Signaling сервер:
Цей сервер забезпечує початковий зв'язок між пірінгами, обмінюючись метаданими та деталями з'єднання, такими як IP-адреси. Для цього використовуються Web-Socket або HTTP.
import { WebSocket, WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
let senderSocket: WebSocket | null = null;
let receiverSocket: WebSocket | null = null;
wss.on('connection', (ws) => {
ws.on('message', (data) => {
const message = JSON.parse(data.toString());
if (message.type === 'sender') senderSocket = ws;
else if (message.type === 'receiver') receiverSocket = ws;
else if (message.type === 'createOffer' && ws === senderSocket)
receiverSocket?.send(JSON.stringify({ type: 'createOffer', sdp: message.sdp }));
else if (message.type === 'createAnswer' && ws === receiverSocket)
senderSocket?.send(JSON.stringify({ type: 'createAnswer', sdp: message.sdp }));
else if (message.type === 'iceCandidate') {
const target = ws === senderSocket ? receiverSocket : senderSocket;
target?.send(JSON.stringify({ type: 'iceCandidate', candidate: message.candidate }));
}
});
});
- STUN та TURN сервери:
- STUN (Session Traversal Utilities for NAT): Допомагає визначити публічні IP-адреси за допомогою NAT-устрійств, що дозволяє здійснювати прямі P2P з’єднання.
На зображенні вище показано два браузери, які спілкуються через STUN сервер та signaling сервер.
текст перекладу
Сервер STUN допомагає визначити публічні IP-адреси пірінгів, що є важливим для встановлення прямого P2P з’єднання, особливо коли пірінги знаходяться за пристроями трансляції мережевих адрес (NAT), такими як маршрутизатори.
- TURN (Traversal Using Relays around NAT): Пересилає дані, коли прямі з’єднання заблоковані брандмауерами або обмеженими мережами.
STUN може встановлювати P2P з’єднання для більшості NAT, за винятком кількох випадків, коли він має непередбачуване відображення портів. У таких випадках два пірінга просто не можуть спілкуватися безпосередньо 1-на-1, і весь їхній трафік передається через TURN сервер. TURN означає Traversal Using Relay NAT, який має публічні адреси, тому пірінги можуть з ним зв’язуватися, навіть якщо вони знаходяться за брандмауерами або проксі-серверами. TURN можна використовувати як резервне рішення, пересилаючи аудіо/відео/дані між пірінгами так само, як традиційна архітектура медіа-серверів.
-
ICE Candidates:
Представляють потенційні кінцеві точки з’єднання. Браузери обмінюються кандидатами ICE для вибору найкращого шляху з’єднання. -
Модель "Оферта та Відповідь":
- Початковий пірінг надсилає “оферту”, яка містить деталі його з’єднання.
- Одержуючий пірінг відповідає “відповіддю”, щоб підтвердити з’єднання.
Встановлення WebRTC з’єднання
Встановлення WebRTC з’єднання між двома пірінгами передбачає серію кроків, що здійснюються через signaling сервер та API RTCPeerConnection , яке надається браузером. Ось розбір процесу:
- Браузер 1 створює екземпляр об’єкта RTCPeerConnection, який представляє WebRTC з’єднання.
- Браузер 1 генерує “оферту”, яка містить його кандидатів ICE та деталі сесії (закодовані в форматі Session Description Protocol (SDP)).
- Браузер 1 встановлює локальне описання об’єкта RTCPeerConnection як згенеровану оферту.
- Браузер 1 надсилає оферту браузеру 2 через signaling сервер.
- Браузер 2 отримує оферту від браузера 1 через signaling сервер.
- Браузер 2 встановлює віддалене описання свого об’єкта RTCPeerConnection як отриману оферту.
- Браузер 2 генерує “відповідь”, що містить його власних кандидатів ICE та деталі сесії.
- Браузер 2 встановлює локальне описання свого об’єкта RTCPeerConnection як згенеровану відповідь.
- Браузер 2 надсилає відповідь браузеру 1 через signaling сервер.
- Браузер 1 отримує відповідь від браузера 2 та встановлює віддалене описання свого об’єкта RTCPeerConnection як отриману відповідь.
На цьому етапі WebRTC з’єднання встановлено між двома пірінгами, і вони можуть почати обмін медіа-даними безпосередньо в режимі peer-to-peer.
Щоб насправді надсилати та отримувати медіа (аудіо та відео), необхідно виконати кілька додаткових кроків:
- Обидва браузери повинні отримати дозвіл від користувача для доступу до камери та мікрофону.
- Після надання дозволів кожен браузер може отримати локальні аудіо- та відео-потоки за допомогою API getUserMedia().
- Кожен браузер додає локальні аудіо- та відео-треки до RTCPeerConnection за допомогою методу addTrack().
- Коли трек додається до RTCPeerConnection, це викликає подію onTrack на віддаленому пірінгу, дозволяючи йому отримати та відобразити вхідні медіа-потоки.
Реалізація
Для створення WebRTC додатку ми використаємо Node.js для налаштування signaling сервера та React для фронтенду, використовуючи API RTCPeerConnection для реального зв’язку.
- Signaling сервер на Node.js
Signaling сервер буде побудований на базі Node.js і слугуватиме WebSocket сервером для обміну повідомленнями сигналізації між пірінгами.
текст перекладу
Він підтримуватиме три типи повідомлень:
- createOffer: Це повідомлення буде надіслане ініціатором з’єднання (Браузер 1) на signaling сервер, який потім пересилає його отримувачу (Браузеру 2).
- createAnswer: Це повідомлення буде надіслане отримувачем (Браузер 2) на signaling сервер, який потім пересилає його ініціатору (Браузеру 1).
- addIceCandidate: Це повідомлення буде надіслано обома пірінгами на signaling сервер, який потім пересилає його іншому пірінгу. Воно містить кандидати ICE, необхідні для встановлення WebRTC з’єднання.
- Фронтенд з React.js
Встановлення WebRTC з’єднання:
- ініціатор з’єднання (Браузер 1) створює екземпляр об’єкта RTCPeerConnection і генерує оферту за допомогою методу createOffer().
- Оферта буде надіслана на signaling сервер через відповідне WebSocket повідомлення (createOffer).
- Отримувач (Браузер 2) отримає оферту від signaling сервера і встановить її як віддалене описання свого екземпляра RTCPeerConnection.
- Браузер 2 згенерує відповідь за допомогою методу createAnswer() і надішле її назад на Браузер 1 через signaling сервер (повідомлення createAnswer).
- Обидва пірінги встановлять отриману відповідь/оферту як їхні віддалене/локальне описання відповідно, завершивши процес встановлення з’єднання.
Обмін кандидатами ICE:
- Коли пірінги збирають кандидатів ICE (потенційні кінцеві точки з’єднання), вони надсилають їх на signaling сервер за допомогою повідомлення addIceCandidate.
- Signaling сервер пересилає ці кандидати ICE іншому пірінгу, дозволяючи їм встановити найбільш ефективне пряме з’єднання.
Надсилання та отримання медіа:
- Після встановлення WebRTC з’єднання обидва пірінги можуть отримати локальні аудіо- та відео-потоки за допомогою API getUserMedia().
- Локальні потоки додаються до екземплярів RTCPeerConnection за допомогою методу addTrack().
- Коли трек додається до RTCPeerConnection, це викликає подію onTrack на віддаленому пірінгу, що дозволяє йому отримувати та відображати вхідні медіа-потоки.
Отримати доступ до повного репозиторію коду: WebRTC
Спрощення P2P комунікації за допомогою бібліотек
WebRTC пропонує надійну платформу для реального часу peer-to-peer комунікації, але реалізація її з нуля може бути складною через об’ємний шаблонний код. На щастя, сторонні бібліотеки, як-от PeerJS, спрощують цей процес. PeerJS абстрагує складність встановлення WebRTC з’єднань, надаючи розробникам зручний API. Це дозволяє зосередитися на побудові основної логіки додатка, залишаючи складні деталі WebRTC бібліотеці.
Проблеми з архітектурою Peer-to-Peer (P2P)
Хоча P2P комунікація чудово підходить для однієї особи або невеликих групових дзвінків, вона стикається з серйозними проблемами при масштабуванні до більших груп:
- Проблеми з масштабуванням: P2P не масштабується добре для понад 3-4 учасників у тому ж дзвінку. Кожен додатковий учасник збільшує кількість одночасних з’єднань, що призводить до підвищеного використання пропускної здатності та зниження продуктивності.
Огляд інших архітектур
Щоб подолати ці обмеження, в WebRTC реалізаціях часто використовують альтернативні архітектури, як-от SFU та MCU:
- Selective Forwarding Unit (SFU):
SFU отримує потоки від кількох учасників і вибірково пересилає їх іншим. Це зменшує навантаження на пропускну здатність кожного клієнта та робить групові дзвінки більш ефективними. - Multipoint Control Unit (MCU):
У налаштуванні MCU всі медіа-потоки надсилаються на центральний сервер, де вони змішуються та обробляються в один потік для кожного учасника.
текст перекладу
Цей підхід ідеально підходить для сценаріїв, які вимагають складної обробки медіа, але за рахунок збільшення навантаження на сервер.
Ці архітектури вирішують проблеми масштабування та продуктивності P2P і краще підходять для великих застосунків. Ми обговоримо ці архітектури, їх переваги та реальні варіанти використання в окремій статті.
Висновок
WebRTC відкриває безмежні можливості для додатків в реальному часі — від відеоконференцій до ігор. Поєднуючи Node.js для сигналізації та React.js для фронтенду, ми можемо ефективно використовувати можливості WebRTC для створення динамічних і чутливих комунікаційних платформ. Незалежно від того, чи створюєте ви додаток для чату один на один або інструмент для багатокористувацьких відеоконференцій, можливості WebRTC та його простота інтеграції роблять його ідеальним вибором.
Маєте питання або хочете обговорити WebRTC? Не соромтеся звертатися до мене через X !
Перекладено з: WebRTC Applications with Node.js and React.js