Чжан Юйхан, фронтенд-инженер WeDoctor Cloud Service Team, неграмотный программист-Дева.
предисловие
Внезапная вспышка COVID-19 в начале 2020 года практически отрезала офлайн-медицинские каналы, и в этом контексте WeDoctor, как лидер индустрии цифрового здравоохранения, быстро решил насущные потребности большого количества людей, нуждающихся в медицинской помощи. лечение через онлайн-консультации и другие формы. Являясь важной частью веб-консультации WeDoctor, видеоконсультация между врачами и пациентами использует технологию WebRTC, описанную далее.
Что такое WebRTC
WebRTC (Web Real-Time Communication) — это механизм GIPS, который Google приобрел в 2010 году за 68,2 млн долларов США, разработчика программного обеспечения VoIP, Global IP Solutions, а в 2011 году сменил название на WebRTC. Платформа для обмена данными в режиме реального времени между аудио, видео и данные.
Так что же может WebRTC? В дополнение к вышеупомянутым онлайн-консультациям / удаленным клиникам / удаленным консультациям в области медицины, существуют также популярные решения для интерактивной прямой трансляции электронной коммерции и решения для индустрии образования.Кроме того, с быстрым строительством 5G, WebRTC Он также обеспечивает хорошая техническая поддержка облачных игр.
WebRTC-архитектура
Картинка ниже взята изОфициальный веб-сайт WebRTCОбщая схема архитектуры WebRTC
Из рисунка нетрудно увидеть, что весь дизайн архитектуры WebRTC можно условно разделить на следующие три части:
- Purple предоставляет API-интерфейсы для разработки веб-интерфейса.
- Сплошная синяя часть показывает API, используемые основными производителями браузеров.
- Часть с синей пунктирной линией содержит 3 части: звуковой движок, видеодвижок, сетевая передача (транспорт). можно настроить
Принцип одноранговой связи WebRTC
Какие трудности и какие проблемы необходимо решить для реализации аудио- и видеосвязи в реальном времени между клиентами (возможно, разными веб-браузерами или мобильными приложениями) в двух разных сетевых средах (с микрофонами и камерами)?
- Как узнать о существовании друг друга, как найти друг друга?
- Как общаться друг с другом возможностями аудио и видео кодеков?
- Как передавать аудио- и видеоданные, как вас может увидеть собеседник?
на вопрос 1: Хотя WebRTC поддерживает сквозную связь, это не означает, что WebRTC больше не нужен сервер. В процессе двухточечной связи обеим сторонам необходимо обмениваться некоторыми метаданными, такими как мультимедийная информация, сетевые данные и так далее. Мы обычно называем этот процесс: сигнализация (сигнализация). Соответствующий серверсигнальный сервер. Его часто называют комнатным сервером, потому что он может не только обмениваться мультимедийной и сетевой информацией друг с другом, но и управлять информацией о комнате, например, уведомлять друг друга о том, кто присоединился к комнате, кто вышел из комнаты, и сообщать третьему вечеринка, достигнуто ли количество людей в комнате. Во избежание избыточности и максимальной совместимости с существующими технологиями стандарт WebRTC не определяет методы и протоколы сигнализации. В следующей практической главе этой статьи мы реализуем сигнальный сервер с использованием технологий Koa и Socket.io.
на вопрос 2: Первое, что нам нужно знать, это то, что разные браузеры имеют разные возможности кодирования и декодирования аудио и видео. Например: сторона Peer-A поддерживает H264, VP8 и другие форматы кодирования, а сторона Peer-B поддерживает H264, VP9 и другие форматы. Чтобы убедиться, что обе стороны могут правильно кодировать и декодировать, проще всего взять пересечение поддерживаемых ими обоих форматов — H264. В WebRTC есть специализированный протокол, который называетсяSession Description Protocol(SDP), который можно использовать для описания такой информации, как описано выше. Следовательно, две стороны, участвующие в аудио- и видеосвязи, должны обмениваться информацией SDP, если они хотят знать форматы мультимедиа, поддерживаемые другой стороной. Процесс обмена SDP обычно называютпереговоры со СМИ.
на вопрос 3: что по сутисетевые переговорыПроцесс: Обе стороны, участвующие в аудио- и видеосвязи в реальном времени, должны понимать сетевые условия друг друга, чтобы можно было найти канал для взаимного общения. Идеальная сетевая ситуация состоит в том, что компьютер каждого браузера имеет свой собственный частный общедоступный IP-адрес, так что можно установить прямое одноранговое соединение. Но на самом деле, из-за соображений сетевой безопасности и недостаточного количества адресов IPV4, все наши компьютеры находятся в определенной локальной сети, большой или маленькой, и нам нужноNAT (преобразование сетевых адресов). В WebRTC мы используем механизм ICE для установления сетевых соединений. Так что же такое ДВС?
ICE (установка интерактивной связи), ICE — это не протокол, а фреймворк, объединяющий протоколы STUN и TURN. вSTUN (Утилиты обхода сеанса для NAT, приложение обхода сеанса NAT), который позволяет клиентам за NAT (или несколькими NAT) узнать их соответствующий общедоступный IP-адрес и порт, что обычно называется «пробиванием отверстий». Однако если тип NAT симметричный, то пробить дырку не получится. Вот где TURN пригодится.TURN(Traversal USing Replays around NAT) является протоколом расширения STUN/RFC5389 и добавляет к нему функцию Replay (relay).Короче говоря, его цель состоит в том, чтобы решить проблему невозможности обхода симметричного NAT.После того, как STUN не может выделить общедоступный IP-адрес , вы можете запросить общедоступный IP-адрес в качестве адреса ретрансляции через сервер TURN.
В WebRTC есть три типа кандидатов ICE:
- принимающий кандидат
- кандидаты на отражение
- эстафетный кандидат
принимающий кандидат, который указывает IP-адрес и порт в локальной сети. Это самый высокий приоритет из трех кандидатов, что означает, что в нижней части WebRTC он сначала попытается установить соединение внутри локальной сети.
кандидаты на отражение, что означает получение внешнего сетевого IP-адреса и порта хоста в NAT. У него более низкий приоритет, чем у кандидата хоста. То есть, когда WebRTC пытается подключиться локально и терпит неудачу, он пытается подключиться через IP-адрес и порт, полученные кандидатом на отражение.
эстафетный кандидат, который указывает IP-адрес и порт сервера ретрансляции, то есть данные мультимедиа ретранслируются через сервер. Когда две взаимодействующие стороны клиента WebRTC не могут пройти P2P NAT, для обеспечения нормальной связи между двумя сторонами качество обслуживания может быть гарантировано только посредством передачи сервера.
Из приведенного выше рисунка видно, что в нелокальной локальной сети WebRTC получает собственный внешний сетевой IP-адрес и порт через STUN-сервер, а затем обменивается сетевой информацией с удаленным WebRTC через сигнальный сервер. После этого обе стороны могут попытаться установить P2P-соединение. Когда обход NAT не удался, он будет ретранслирован через сервер ретрансляции (TURN).
Стоит отметить, что в WebRTC сетевая информация обычноcandidateЧтобы описать, и сервер STUN, и сервер воспроизведения на приведенном выше рисунке также могут быть одним и тем же сервером. В практической главе в конце статьи используется проект coturn с открытым исходным кодом, который объединяет функции STUN (перфорация отверстий) и TURN (ретрансляция).
Подводя итог объяснению трех проблем, мы можем использовать следующий рисунок, чтобы проиллюстрировать основной принцип двухточечной связи WebRTC:
Короче говоря, мультимедийная информация SDP и сетевая информация-кандидат на каждом конце получаются через API, предоставляемый WebRTC, и обмениваются через сигнальный сервер, а затем устанавливается канал соединения на обоих концах для завершения видео- и голосового вызова в реальном времени. .
Несколько важных API WebRTC
API захвата аудио и видео
const constraints = {
video: true,
audio: true
};
// 非安全模式(非https/localhost)下 navigator.mediaDevices 会返回 undefined
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
document.querySelector('video').srcObject = stream;
} catch (error) {
console.error(error);
}
Получить входной и выходной список аудио- и видеоустройств
try {
const devices = await navigator.mediaDevices.enumerateDevices();
this.videoinputs = devices.filter(device => device.kind === 'videoinput');
this.audiooutputs = devices.filter(device => device.kind === 'audiooutput');
this.audioinputs = devices.filter(device => device.kind === 'audioinput');
} catch (error) {
console.error(error);
}
RTCPeerConnection
В качестве API для создания двухточечных соединений RTCPeerConnection является ключом к нашей аудио- и видеосвязи в реальном времени. (Обратитесь к документации MDN)
Следующие методы RTCPeerConnection в основном используются в практической главе этой статьи:
метод переговоров со СМИ
- createOffer
- createAnswer
- setLocalDesccription
- setRemoteDesccription
важные события
- onicecandidate
- onaddstream
Из описания в предыдущей главе мы можем узнать, что наиболее важным звеном в P2P-коммуникациях является обмен медиа-информацией.
Из приведенного выше рисунка нетрудно понять, что весь процесс согласования медиа может быть упрощен до трех шагов, соответствующих четырем методам согласования медиа:
- Вызывающая сторона Amy создает предложение (createOffer) и передает сообщение предложения (содержимое представляет собой информацию SDP вызывающей стороны Amy) принимающей стороне Bob через сигнальный сервер и вызывает setLocalDescription для сохранения предложения, содержащего локальную информацию SDP. .
- Получив информацию о предложении противоположного конца, Боб вызывает метод setRemoteDescription, чтобы сохранить предложение, содержащее информацию SDP противоположного конца, и создает ответ (createAnswer) и отправляет сообщение ответа (содержимое представляет собой информацию SDP получателя). end Bob) к SDP через сигнальный сервер.
- Вызывающая сторона Эми вызывает метод setRemoteDescription после получения информации об ответе противоположной стороны, чтобы сохранить ответ, содержащий информацию SDP противоположной стороны.
После вышеуказанных трех шагов часть согласования мультимедиа в процессе связи P2P завершена.Фактически, вызывающая сторона и принимающая сторона вызывают setLocalDescription, а также начинают собирать собственную сетевую информацию каждого конца (кандидата), а затем каждый конец прослушивает событие onecandidate.Соответствующие кандидаты собираются и отправляются на противоположный конец через сигнальный сервер, затем открывается сетевой канал P2P-связи, и видеопоток другой стороны получается путем отслеживания события onaddstream для завершения весь процесс видеозвонка.
WebRTC на практике
Строительство котурн сервера
Примечание: Если это только локальный тест локальной сети, вам не нужно создавать сервер coturn.Если вам нужен доступ к внешней сети, вам необходимо приобрести облачный хост и привязать доменное имя, поддерживающее доступ https, перед созданием сервера coturn. Вот сайт, который я создал для тестирования WebRTC:webrtc-demo
Конструкция сервера coturn в основном предназначена для решения проблемы невозможности обхода NAT, и его установка также относительно проста:
1. git clone https://github.com/coturn/coturn.git
2. cd coturn/
3. ./configure --prefix=/usr/local/coturn
4. make -j 4
5. make install
// 生成 key
6. openssl req -x509 -newkey rsa:2048 -keyout /etc/turn_server_pkey.pem -out /etc/turn_server_cert.pem -days 99999 -nodes
конфигурация сервиса coturn
vim /usr/local/coturn/etc/turnserver.conf
listening-port=3478
external-ip=xxx.xxx // 你的主机公网 IP
user=xxx:xxx // 账号: 密码
realm=xxx.com // 你的域名
Запустить сервис coturn
1. cd /usr/local/coturn/bin/
2. ./turnserver -c ../etc/turnserver.conf
// 注意:云主机内的 TCP 和 UDP 的 3478 端口都要开启
тренировочный кодекс
Прежде чем писать код, в сочетании с основными принципами двухточечной связи WebRTC в приведенном выше разделе можно нарисовать следующую блок-схему:
Это нетрудно увидеть из рисунка, если предположить, что PeerA является инициатором, а PeerB — получателем.Для реализации двухточечной WebRTC аудио- и видеосвязи в режиме реального времени необходим сигнальный (Signal) сервер для управления информацией о помещении и пересылать сетевую информацию и информацию о мультимедиа.В этой статье это сигнальный сервер, построенный с помощью koa и socket.io:
// server 端 server.js
const Koa = require('koa');
const socket = require('socket.io');
const http = require('http');
const app = new Koa();
const httpServer = http.createServer(app.callback()).listen(3000, ()=>{});
socket(httpServer).on('connection', (sock)=>{
// ....
});
// client 端 socket.js
import io from 'socket.io-client';
const socket = io.connect(window.location.origin);
export default socket;
После настройки сервера сигнализации в сочетании с блок-схемой необходимо выполнить следующие шаги:
- PeerA и PeerB соответственно подключены к сигнальному серверу, и сигнальный сервер записывает информацию о помещении.
// server 端 server.js
socket(httpServer).on('connection', (sock)=>{
// 用户离开房间
sock.on('userLeave',()=>{
// ...
});
// 检查房间是否可加入
sock.on('checkRoom',()=>{
// ...
});
// ....
});
// client 端 Room.vue
import socket from '../utils/socket.js';
// 服务端告知用户是否可加入房间
socket.on('checkRoomSuccess',()=>{
// ...
});
// 服务端告知用户成功加入房间
socket.on('joinRoomSuccess',()=>{
// ...
});
//....
- В качестве инициатора сторона A инициирует видеоприглашение стороне получателя B. После получения согласия на видеозапрос от B обе стороны создадут локальное RTCPeerConnection и добавят локальный видеопоток.Отправитель создаст предложение установить описание информации о локальном sdp и передать сигнальный сервер. Отправить собственную информацию SDP узлу.
socket.on('answerVideo', async (user) => {
VIDEO_VIEW.showInvideoModal();
// 创建本地视频流信息
const localStream = await this.createLocalVideoStream();
this.localStream = localStream;
document.querySelector('#echat-local').srcObject = this.localStream;
this.peer = new RTCPeerConnection();
this.initPeerListen();
this.peer.addStream(this.localStream);
if (user.sockId === this.sockId) {
// 接收方
} else {
// 发送方 创建 offer
const offer = await this.peer.createOffer(this.offerOption);
await this.peer.setLocalDescription(offer);
socket.emit('receiveOffer', { user: this.user, offer });
}
});
- Как упоминалось ранее, при вызове setLocalDescription он также начнет собирать информацию о собственной сети (кандидате).Если он находится не в локальной сети или сетевое «прокалывание» не увенчалось успехом, он также попытается инициировать запрос к серверу Stun/Turn, то есть для сбора «кандидата на реле», поэтому при создании RTCPeerConnection нам также необходимо прослушивать события кандидата в сеть ICE:
initPeerListen () {
// 收集自己的网络信息并发送给对端
this.peer.onicecandidate = (event) => {
if (event.candidate) { socket.emit('addIceCandidate', { candidate: event.candidate, user: this.user }); }
};
// ....
}
- Когда получатель B получает информацию о предложении, содержащую SDP, от отправителя A на противоположной стороне через сигнальный сервер, он вызывает setRemoteDescription для сохранения информации SDP противоположной стороны, создания и установки локальной информации SDP и передачи информации SDP. содержащий локальный SDP через сигнальный сервер информационный ответ
socket.on('receiveOffer', async (offer) => {
await this.peer.setRemoteDescription(offer);
const answer = await this.peer.createAnswer();
await this.peer.setLocalDescription(answer);
socket.emit('receiveAnsewer', { answer, user: this.user });
});
- Когда инициатор A получает информацию об ответе получателя B через сигнальный сервер, он также вызывает setRemoteDescription, чтобы две стороны завершили обмен информацией SDP.
socket.on('receiveAnsewer', (answer) => {
this.peer.setRemoteDescription(answer);
});
- Когда обмен информацией SDP между двумя сторонами завершится и сетевые кандидаты, собранные мониторингом icecandidate, будут обменены через сигнальный сервер, они получат видеопотоки друг друга.
socket.on('addIceCandidate', async (candidate) => {
await this.peer.addIceCandidate(candidate);
});
this.peer.onaddstream = (event) => {
// 拿到对方的视频流
document.querySelector('#remote-video').srcObject = event.stream;
};
Суммировать
После 6 шагов, описанных в предыдущей главе, можно выполнить полный P2P-видеозвонок в реальном времени.Код можно передать черезlearn-webrtcЗагрузите, стоит отметить, что VIDEO_VIEW в коде представляет собой JS SDK, ориентированный на уровень пользовательского интерфейса видео, включая модальное окно для запуска видео, получение модального изображения и модальное изображение в видео. Извлечено из SDK. В этой статье лишь кратко представлены основные принципы связи WebRTC P2P.На самом деле SDK, используемый в производственной среде, не только поддерживает связь точка-точка, но также поддерживает видеозвонки с несколькими людьми, совместное использование экрана и другие функции, которые все реализовано на базе WebRTC.