С WebRTC прямая трансляция может воспроизводиться так!

WebRTC
С WebRTC прямая трансляция может воспроизводиться так!

Как реализовать видеозвонок в реальном времени между двумя людьми? Сначала вы можете подумать о потоковом вещании в прямом эфире: поток захвата -> поток отправки -> поток извлечения. Однако, если этот процесс реализован на переднем крае, его можно будет увидеть только на крыше. Однако появление WebRTC изменило этот статус-кво.

在线客服处理流程图 (2).png

С WebRTC внешний интерфейс может легко реализовывать прямую трансляцию и даже аудио- и видеовызовы в реальном времени, не обращая внимания на процесс «получение потока -> push-поток -> pull-поток».

Что такое WebRTC? Каков основной принцип? как использовать? Пусть парень барбекю расскажет вам историю!

Что такое WebRTC?

WebRTC расшифровывается как Web Real-time Communication, технология мгновенного веб-коммуникации. Это решение для обмена мгновенными сообщениями, инициированное Google. Причина, по которой он называется схемой, а не протоколом, заключается в том, что он охватывает полный набор схем реализации, таких как сбор аудио и видео, установление связи, передача информации и отображение аудио и видео. Запуск этой схемы позволяет быстро реализовать приложение для аудио- и видеосвязи.

image.png

Если вы веб-разработчик, вы можете легко собирать и воспроизводить аудио и видео через API WebRTC, предоставляемый браузером, устанавливать сквозной канал связи и обмениваться аудио- и видеоданными через установленный канал.

Хотя WebRTC кажется браузерным, из-за духа открытого исходного кода Google он может обеспечить полнофункциональную совместимость платформы путем компиляции кода C++. Поэтому, если вы хотите удаленно управлять компьютером с Windows через Интернет, вы можете позволить своим детям C++ подхватить волну WebRTC, а WebRTC также поддерживает сбор рабочих столов в реальном времени!

Как WebRTC обеспечивает сквозной обмен аудио и видео?

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

demo.png

Однако производительность в реальном времени оставляет желать лучшего. Вам нужно подождать, пока другая сторона загрузит файл, прежде чем загружать файл. Конечно, этот процесс также может выполняться в режиме реального времени: вы можете построить файловый поток на сервере, чтобы немедленно передать файловый поток, который достигает сервера, на съемник. Так хлопотно, почему бы не пропустить этот сервер?

demo (1).png

P2P-соединение

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

Итак, как создать P2P-соединение? Здесь мы впервые посмотрим на то, как реальный интернет-мир общается вот так!

реальный онлайн мир

Реальная сеть выглядит так:

demo (2).png

Однако, поскольку большая часть версии Интернет-протокола (IP-протокола), развернутой в настоящее время в Интернете, — это IPV4, в IPV4 используется 32-битный двоичный адрес, который может генерировать 4,3 миллиарда IP-адресов.Если каждый пользовательский терминал подключен к независимому IP-адресу в Интернет, то 4,3 миллиарда адресов будет недостаточно.

Таким образом, текущая сетевая структура в основном заключается в том, что терминалы с несколькими устройствами получают доступ к Интернету через один или несколько уровней прокси-серверов NAT, то есть через локальную сеть.

Что такое НАТ?

NAT: преобразование сетевых адресов — технология, решающая проблему подключения устройств в частной сети к общедоступной сети.

Так как же работает NAT?

未命名文件.png

  • Когда устройство A хочет отправить запрос на сервер 172.20.98.44:7777 => 8.8.8.8:23456, запрос сначала достигнет NAT, и NAT изменит исходный адрес и исходный порт пакета и соответствующую проверку. код, а затем Отправить на сервер, и в это время формируется отношение сопоставления потока:
172.20.98.44:7777 => 6.6.6.6:12345 => 8.8.8.8:23456
  • Когда сервер обрабатывает запрос и возвращает данные ответа на NAT, NAT изменяет адрес назначения, порт назначения и соответствующий контрольный код в соответствии с отношением сопоставления, а затем отправляет его на устройство A:
8.8.8.8:23456 => 6.6.6.6:12345 => 172.20.98.44:7777

Это основная функция NAT, которая позволяет устройствам интрасети нормально получать доступ к общедоступным сетевым серверам.

Устройства в интрасети могут использовать NAT для доступа к общедоступному сетевому серверу, но при подключении P2P оба устройства могут находиться в разных интрасетях.Как эти два устройства могут выполнять подключение P2P?

Технология обхода NAT

demo (4).png

Техническое решение, позволяющее двум устройствам в двух интрасетях устанавливать одноранговое соединение, в совокупности называется технологией обхода NAT. Вообще говоря, P2P может устанавливать UDP-соединение или TCP-соединение, поэтому этот механизм также называетсяПробивка отверстий UDPилиПробивание отверстий TCP.因为webRTC使用的传输层协议是UDP协议,所以我这里主要讲解Пробивка отверстий UDPпринцип.

  • Первым шагом является добавление сервера обмена сообщениями. Роль сервера обмена сообщениями заключается в обнаружении и записи портов, отображаемых устройством интрасети в NAT, и общедоступного IP-адреса его NAT. Такие серверы также известны как серверы STUN. Согласно характеристикам NAT, когда устройство А отправляет запрос на сервер STUN, будет сформирована связь отображения:172.20.98.44:7777 => 6.6.6.6:12345 => 3.3.3.3:34567, то сервер STUN отвечает устройству A с помощью 6.6.6.6:12345. Точно так же устройство B также делает запрос ответа для получения соответствующего отношения отображения.

demo (9).png

  • Обмен картографическими отношениями. Устройству A и устройству B необходимо обменяться сопоставлениями NAT, чтобы подготовиться к следующему шагу по установлению соединения. Здесь для обмена требуется другой протокол.
  • После завершения обмена адрес NAT-B устройства A на устройство B8.8.8.8:23456Отправьте пакет запроса, так как запрос не инициирован устройством B. Из соображений безопасности NAT-B не будет пересылать пакет запроса на устройство B, а отклонит его.Однако NAT-A записывает это отношение сопоставления в соответствии с характеристиками , обратно с адреса8.8.8.8:23456Входящие пакеты будут перенаправлены на устройство А. Точно так же устройство B также отправляет6.6.6.6:12345Инициируйте тот же запрос, чтобы сообщить NAT-B, что6.6.6.6:12345Все входящие запросы перенаправляются на устройство B.
  • После выполнения вышеуказанных действий устройство A и устройство B могут установить P2P-соединение и успешно отправлять сообщения. Конечно, это соединение должно поддерживаться пакетом пульса, чтобы предотвратить его закрытие.

Выше приведен полный процесс создания UDP-подключения.После того, как отверстие пробито, устройство может пересечь NAT для реализации P2P-соединения.

WebRTC — это сквозное соединение на основе UDP.

Основываясь на вышеизложенном, передача аудио и видео через WebRTC для сквозной передачи также должна иметь дело с процессом пробивки отверстий UDP. Когда мы вызываем WebRTC для создания сквозного соединения, а не для реализации этого процесса пробивки отверстий UDP (если вы хотите, и это противоречит первоначальному замыслу предлагаемого WebRTC,Простота организации обмена мгновенными аудио- и видеосообщениями — это цель WebRTC.). Более того, нам нужно вызвать API в соответствии с процессом, чтобы завершить создание WebRTC.

Узнайте об использовании WebRTC API из раздела «Создание соединения WebRTC».

Рассмотрим весь процесс создания соединения:

未命名文件 (1).png

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

Несмотря на то, что совместимость WebRTC очень хорошая (за исключением мощного IE), каждый браузер по-прежнему имеет различия в предоставлении API верхнего уровня, поэтому нам нужна прокладка, чтобы устранить эту разницу:webrtcHacks/adapter

Сломай:

  1. Создайте экземпляр RTC. WebRTC предоставляет API RTCPeerConnection для создания соединений. Код ниже, гдеconfigurationнеобязательный,configurationИспользуется для настройки информации сервера STUN/TURN. Здесь сервер STUN/TURN также нужно построить самостоятельно, посмотрите, нужен ли он вам.Развертывание оглушения и поворота серверов.
let connection = new RTCPeerConnection([configuration]);

Если вы не настраиваете конфигурацию, это означает, что это соединение может быть осуществлено только во внутренней сети.

  1. Получите доступ к устройству микрофона камеры. Следующий код может открыть микрофон камеры, не полагаясь на какие-либо плагины (браузер в это время запросит авторизацию) и получить медиапоток. вconstraintsОтносится к запрошенному типу носителя и соответствующим параметрам;mediaStreamОтносится к медиапотоку, который может бытьmediaStreamАтрибут srcObject, назначенный элементу видео, реализует потоковое воспроизведение мультимедиа в реальном времени. Для получения дополнительной информации о медиаустройствах см.здесь
navigator.mediaDevices.getUserMedia(constraints)
    .then(function(mediaStream) { ... })
    .catch(function(error) { ... })

getUserMedia может нормально получать медиапотоки только в локальной среде localhost и доверенном доменном имени (https), в противном случае будет сообщено об ошибке.

  1. Добавьте медиапоток в экземпляр RTCPeerConnection.
connection.addTrack(mediaStream.getVideoTracks()[0], stream);
  1. Поменяйте местами SDP. WebRTC использует режим Offer-Answer для обмена предложениями. Во-первых, инициатор создает SDP-предложение с помощью createOffer и передает его получателю через службу сигнализации; получатель создает SDP-ответ с помощью createAnswer и передает его инициатору через сервер сигнализации. Обе стороны должны установить SDP, сгенерированный ими самими и отправленный узлом в соединение через setLocalDescription и setRemoteDescription.

SDP(Session Description Protocol)Это протокол описания сеанса, основанный на тексте, который сам по себе не является транспортным протоколом и должен полагаться на другие транспортные протоколы (такие как SIP и HTTP) для обмена необходимой мультимедийной информацией для согласования мультимедиа между двумя объектами сеанса. SDP содержит информацию о носителе, сетевую информацию, функции безопасности и политики передачи, необходимые для установления сеанса.

Примечание. Если аудио- и видеопотоки передаются, необходимо добавить медиапоток в канал через addTrack перед созданием SDP-предложения, потому что информация о потоке должна быть собрана при создании SDP. Если не добавить, SDP не выживет.

//添加流媒体信息
connection.addTrack(stream.getVideoTracks()[0], stream);

//发起方创建Offer SDP
connection
    .createOffer()
    .then((sessionDescription) => {
        console.log("发送offer");
        if (connection) {
            console.log("设置本地description");
            connection.setLocalDescription(sessionDescription);
        }

        sendMessage(sessionDescription, targetId);
    })
    .catch(() => {
        console.log("offer create error");
    });
    
//接收方设置远端描述
connection.setRemoteDescription(             
   new RTCSessionDescription(sessionDescription)         
);

//接收方生成Answer SDP
connection
    .createAnswer()
    .then((sessionDescription) => {
        console.log("发送answer");

        if (connection) {
            console.log("设置本地description");
            connection.setLocalDescription(sessionDescription);
        }
        sendMessage(sessionDescription, targetId);
    })
    .catch(() => {
        console.log("创建answer失败");
    });

//发起方设置远端描述
connection.setRemoteDescription(             
   new RTCSessionDescription(sessionDescription)         
);

5. Кандидат обмена информацией о кандидате. Обе стороны соединения получают информацию о своем кандидате, прослушивая событие icecandidate RTCPeerConnection, а затем передают его партнеру через службу сигнализации. Обмен информацией о кандидатах является важным шагом в установлении соединения WebRTC. После получения кандидата однорангового узла необходимо создать экземпляр объекта RTCIceCandidate, а затем добавить его в экземпляр Rtc с помощью метода addIceCandidate класса RTCPeerConnection.

Кандидат информации о кандидате содержит информацию о сопоставлении NAT, соответствующую текущему устройству, включая: IP, порт, протокол

Время запуска события icecandidate наступает после выполнения setLocalDescription.

//监听icecandidate的触发
connection.addEventListener("icecandidate", (event) => {
    if (event.candidate) {
        console.log("发送candidate", event.candidate.candidate);
        sendMessage(
            {
                type: "candidate",
                label: event.candidate.sdpMLineIndex,
                id: event.candidate.sdpMid,
                candidate: event.candidate.candidate,
            },
            targetId
        );
    } else {
        console.log("End of candidates.");
    }
});

//添加候选人信息
const candidate = new RTCIceCandidate({
    sdpMLineIndex: message.label,
    candidate: message.candidate,
});
connection.addIceCandidate(candidate).catch((error) => {
    console.log(error);
});

Вышеупомянутые, вероятно, API-интерфейсы, необходимые для завершения всего установления соединения WebRTC. Кроме того, существует множество API-интерфейсов для практического мониторинга соединений, согласования кодирования аудио и видео во время создания соединения и создания соединений WebRTC путем установления каналов данных. кому интересно может обратитьсяWebRTC API.

реальный бой

Чтобы понять некоторые основные API для игры в WebRTC, давайте завершим пример в реальном бою — реализация связи в реальном времени между двумя людьми, как упоминалось в начале, здесь мы реализуем одновременную видеосвязь нескольких людей. Вот в основном пример, основанный на реализации интрасети, доступ к услуге через IP-адрес интрасети.

Реализация здесь в основном разделена на две части, следуя идее разделения передней и задней частей, одна часть — это реализация службы сигнализации, а другая часть — реализация интерфейсной интерактивной страницы.

Первый шаг — создать службу сигнализации: express + socket.io

Как упоминалось ранее, основная роль службы сигнализации заключается в передаче информации при создании соединения. Здесь, чтобы просто реализовать функцию, используется экспресс-фреймворк node и socket.io, который может поддерживать двустороннюю связь;

Создать HTTPS-сервис

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

const app = require("express")();
const fs = require("fs");
//读取证书
const key = fs.readFileSync(
    "/Users/XXX/Documents/study/https/172.20.210.160.key",
    "utf8"
);
const cert = fs.readFileSync(
    "/Users/XXX/Documents/study/https/172.20.210.160.crt",
    "utf8"
);

const http = require("https").Server(
    {
        key,
        cert,
    },
    app
);

//监听3005端口
http.listen(3005, function () {
    console.log("listening on *:3005");
});

На самом деле создать https можно и через настройку nginx.Я не хочу тут заниматься nginx, поэтому реализован код.

Междоменные настройки

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

const allowCors = function (req, res, next) {
    res.header("Access-Control-Allow-Origin", req.headers.origin);
    res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
    res.header("Access-Control-Allow-Headers", "Content-Type");
    res.header("Access-Control-Allow-Credentials", "true");
    next();
};
app.use(allowCors);

Реализация механизма ретрансляции сообщений socket.io.

Реализация очень проста, код завершает механизм, и я не могу не восхищаться величием мира с открытым исходным кодом.

const socketIo = require("socket.io");

function createSocketIo(httpInstance) {
    //初始化实例,支持跨域
    const io = socketIo(httpInstance, {
        cors: {
            origin: "*",
            allowedHeaders: ["Content-Type"],
            methods: ["GET,PUT,POST,DELETE,OPTIONS"],
        },
    });
    //监听每一个连接
    io.on("connection", function (socket) {
        //监听连接上的单个端,同时像其他端发送新人加入消息
        socket.on("connect", () => {
            console.log("连上了");
            socket.joinRoom("demo", () => {
                socket.broadcast.to("demo").emit("new", socket.id);
            });
        });
        //消息中转
        socket.on("message", (message) => {
            if (message.target) {
                socket.to(message.target).emit("message", {
                    originId: socket.id,
                    data: message.data,
                });
            }
            else {
                socket.broadcast.to('demo').emit("message", {
                    originId: socket.id,
                    data: message.data,
                });
            }
        });
    });
}

module.exports = createSocketIo;

Второй шаг, реализация интерфейсного интерактивного интерфейса

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

Здесь пользовательский интерфейс используетcreat-react-appБыстро создавайте проекты.

Интерфейс взаимодействия с пользователем состоит из двух частей, одна часть — это логика создания соединения WebRTC, а другая часть — логика взаимодействия socket.io.

Инкапсулирует соединения WebRTC для поддержки многоранговых соединений.

//无敌垫片
import "webrtc-adapter";

class ConnectWebrtc {
    protected connection: RTCPeerConnection | null;
    constructor() {
        this.connection = null;
    }

    //创建RTCPeerConnection实例,同时监听icecandidate,track事件
    create(
        onAddStream: EventListenerOrEventListenerObject,
        onReomveStream: EventListenerOrEventListenerObject,
        onCandidate: (candidate: RTCIceCandidate) => void
    ) {
        this.connection = new RTCPeerConnection(undefined);

        this.connection.addEventListener("icecandidate", (event) => {
            if (event.candidate) {
                onCandidate(event.candidate);
            } else {
                console.log("End of candidates.");
            }
        });
        this.connection.addEventListener("track", onAddStream);
        this.connection.addEventListener("removeTrack", onReomveStream);
    }

    //创建offer sdp
    createOffer(
        onSessionDescription: (
            sessionDescription: RTCSessionDescriptionInit
        ) => void
    ) {
        if (this.connection) {
            this.connection
                .createOffer()
                .then((sessionDescription) => {
                    if (this.connection) {
                        this.connection.setLocalDescription(sessionDescription);
                        onSessionDescription(sessionDescription);
                    }
                })
                .catch(() => {
                    console.log("offer create error");
                });
        }
    }
    
    //创建answer sdp
    createAnswer(
        onSessionDescription: (
            sessionDescription: RTCSessionDescriptionInit
        ) => void
    ) {
        if (this.connection) {
            this.connection
                .createAnswer()
                .then((sessionDescription) => {
                    if (this.connection) {
                        this.connection.setLocalDescription(sessionDescription);
                    }

                    onSessionDescription(sessionDescription);
                })
                .catch(() => {
                    console.log("创建answer失败");
                });
        }
    }

    //设置远端描述
    setRemoteDescription(
        sessionDescription: RTCSessionDescriptionInit | undefined
    ) {
        this.connection?.setRemoteDescription(
            new RTCSessionDescription(sessionDescription)
        );
    }

    //设置候选人
    setCandidate(message: any) {
        if (this.connection) {
            const candidate = new RTCIceCandidate({
                sdpMLineIndex: message.label,
                candidate: message.candidate,
            });
            this.connection.addIceCandidate(candidate).catch((error) => {
                console.log(error);
            });
        }
    }

    //讲媒体流添加到连接中
    addTrack(stream: MediaStream) {
        if (this.connection) {
            this.connection.addTrack(stream.getVideoTracks()[0], stream);
            this.connection.addTrack(stream.getAudioTracks()[0], stream);
        }
    }

    //从连接中删除媒体流
    removeTrack() {
        if (this.connection) {
            this.connection.removeTrack(this.connection.getSenders()[0]);
        }
    }
}

export default ConnectWebrtc;

Инкапсулируя создание соединения в ключевой шаг, можно создать несколько соединений WebRTC.

Компонент взаимодействия со страницей подключен к socket.io

import { useEffect, useRef, useState } from "react";
import { io, Socket } from 'socket.io-client';
import { server } from "./config";
import ConnectWebrtc from "./webrtc";

//媒体设备采集配置
const mediaStreamConstraints = {
    video: {
        width: 400,
        height: 400
    },
    audio: true
};

const Room = () => {
    //本地流
    const localStream = useRef<MediaStream>();
    //播放本地流的video标签
    const localVideoRef = useRef<HTMLVideoElement>(null);
    //保存多个连接实例对象
    const connectList = useRef<{ [target: string]: any }>({});
    //连接用户的列表
    const [userlist, setUserList] = useState<string[]>([]);
    //socket.io实例
    let socket = useRef<Socket>();

    //发送消息到指定对等方
    const sendMessage = (data: any, targetId?: string | null) => {
        socket.current?.emit('message', {
            target: targetId,
            data
        })
    }
    
    //将对等方传来的媒体流添加到指定video标签中
    const handeStreamAdd = (originId: string) => (event: any) => {
        let video = document.getElementById(originId) as HTMLVideoElement;

        if (video) {
            video.srcObject = event.streams[0];
        }
    }

    //获取与指定对等方WebRTC连接实例,如果不存在,则创建
    const getConnection = (originId: string) => {
        let connection = connectList.current?.[originId];
        if (!connection) {
            connection = new ConnectWebrtc();
            connection.create(handeStreamAdd(originId), () => { }, (candidate: RTCIceCandidate) => {
                sendMessage(
                    {
                        type: "candidate",
                        label: candidate.sdpMLineIndex,
                        id: candidate.sdpMid,
                        candidate: candidate.candidate,
                    },
                    originId
                );
            });
            
            //优先将媒体流添加到连接中
            connection.addTrack(localStream.current);
            connectList.current[originId] = connection;
        }
        return connection;
    }

    //创建与信令服务的socket.io连接
    const handleConnectIo = () => {
        socket.current = io(server);
        socket.current.on('connect', () => {
            console.log('连上了');
        });

        //监听消息
        socket.current.on('message', function (message) {
            //添加对等方
            if (!userlist.includes(message.originId)) {
                userlist.push(message.originId);
                setUserList([...userlist])
            }
     
            let connection = getConnection(message.originId);
            
            //当作为接收方时,设置远端描述,并创建answer sdp
            if (message.data.type === 'offer') {
                connection.setRemoteDescription(message.data);
                connection.createAnswer((sdp) => {
                   sendMessage(sdp, originId); 
                });
            } 
            //当作为发起方时,收到answer sdp则设置为远端描述
            else if (message.data.type === 'answer') {
                connection.setRemoteDescription(message.data);
            } 
            //当收到候选人信息时,将候选人信息加入到连接中
            else if (message.data.type === 'candidate') {
                connection.setCandidate(message.data);
            }
        });

        //当收到新用户加入房间时,主动发起WebRTC连接
        socket.current.on('new', (newId) => {
            const connection = getConnection(newId);
            connection.createOffer((sdp) => {
                   sendMessage(sdp, originId); 
            });

            if (!userlist.includes(newId)) {
                userlist.push(newId);
                setUserList([...userlist])
            }
        })
    }
    
    //打开本地媒体设备并设置到video标签中进行播放
    const handleGetLocalStream = (callback: () => void) => {
        navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
            .then((mediaStream) => {
                localStream.current = mediaStream;

                if (localVideoRef.current) {
                    localVideoRef.current.srcObject = mediaStream;
                }
                callback();
            }).catch((error) => {
                console.log(error)
            });
    }

    //组件挂载是优先打开媒体设备然后再建立socket.io连接
    useEffect(() => {
        handleGetLocalStream(() => {
            handleConnectIo();
        });
    }, []);

    return (
        <div>
            <div style={{ marginTop: 20 }}>
                <p>我的画面</p>
                <video ref={localVideoRef} autoPlay playsInline ></video>
            </div>
            <div style={{ marginTop: 20 }}>
                <p>其他人的画面</p>
                {
                    userlist.map(user => {
                        return <video id={user} key={user} autoPlay playsInline></video>
                    })
                }
            </div>
        </div>
    )
}

export default Room;

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

Достигнутый эффект аналогичен эффекту головы, поэтому я не буду его здесь показывать.

продлевать

Используйте диаграмму, чтобы представить отношения между пользователями в реальном бою выше:

demo (10).png

Сложные отношения, если добавить миллионы десятков тысяч связей, разве это не был бы взрыв.

Таким образом, P2P-соединение является децентрализованным методом подключения, подходит для небольшого количества подключений, для большого количества подключений необходимо вернуться к централизованной идее и реализовать возможность децентрализации центральным сервисом (таким как CDN). ).).

demo (12).png

На первый взгляд, это не возврат к традиционному способу живого аудио и видео. Так почему я должен выбрать WebRTC?

С точки зрения выбора технологии, WebRTC имеет лучшую совместимость и масштабируемость, чем другие аудио- и видеопротоколы (поскольку это открытый исходный код); кроме того, задержка соединения WebRTC ниже, что требует реального времени. все более и более сексуально интерактивным, является очень хорошим решением.

протокол задерживать сегментация данных HTML5 в прямом эфире Сценарии применения Плагины, связанные с интерфейсом
HLS 10~30s ломтик служба поддержки Прямая трансляция H5, прямая трансляция игры hls.js
RTMP 2s~5s непрерывный поток не поддерживается Интерактивный прямой эфир
HTTP-FLV 2с~5с, лучше, чем rtmp непрерывный поток служба поддержки Интерактивный прямой эфир flv.js
RTSP Обычно менее 500 мс непрерывный поток не поддерживается Интерактивный прямой эфир
webRTC в течение 1 с непрерывный поток Поддержка (Совместимость) Интерактивные развлечения Родной

В настоящее время некоторые отрасли с высокими требованиями к взаимодействию в реальном времени используют решения WebRTC. Можно сказать, что будущее очень светлое.

Суммировать

В этой статье кратко анализируется WebRTC с точки зрения принципа и реального боя.WebRTC — очень сложное решение, и моя статья определенно не имеет смысла. Если что-то не так, пожалуйста, поправьте меня.

наконец

Если вы считаете, что статья брата-барбекю хороша, пожалуйста, поставьте лайк и подпишитесь на нее; если есть какие-то недостатки, не стесняйтесь исправлять меня.