WebRTC(Web 实时通讯)是一项强大的技术,可直接在 Web 浏览器和移动应用程序之间实现实时音频、视频和数据共享。无论您是在构建视频集会应用程序、直播平台还是交互式 Web 应用程序,WebRTC 都已成为通讯领域的变革者。
在本博客中,我们将从头开始学习 WebRTC,探索其焦点概念,了解其架构,并深入研究一些现实的编码示例。最后,您将掌握构建自己的 WebRTC 应用程序的底子知识。
1. 了解 WebRTC 的底子知识
1.1 什么是 WebRTC?
WebRTC(Web 实时通讯)是一组开源技术,可实现 Web 浏览器和移动应用程序之间通过互联网直接举行实时通讯。它允许点对点音频、视频和数据共享,而无需任何插件或其他软件。WebRTC 广泛用于构建视频集会、语音通话、直播、在线游戏等应用程序。
WebRTC 点对点连接
1.2 WebRTC 的工作原理
- 媒体捕捉:WebRTC 允许网络浏览器和移动应用程序访问用户的媒体装备(例如摄像头和麦克风),以捕捉音频和视频流。
- 信令:在两个对等体可以通讯之前,它们需要建立连接。信令过程涉及在对等体之间互换元数据和控制消息,以协商会话设置并处置处罚网络细节。
- 对等连接:信令过程完成后,两个装备之间就会建立直接的对等连接。WebRTC 利用安全高效的对等连接协议在它们之间传输音频、视频和数据流。
- 编解码器和加密:WebRTC 支持多种音频和视频编解码器,可高效编码和传输媒体流。别的,它还采用加密技术来保护对等端之间的通讯,确保隐私和数据完整性。
- NAT 和防火墙穿越:WebRTC 旨在跨不同网络工作并处置处罚网络地点转换器 (NAT) 和防火墙。它利用交互式连接建立 (ICE) 等技术来发现和建立直接通讯路径。
- 数据通道:除了音频和视频流之外,WebRTC 还包括数据通道,允许对等方直接互换非媒体数据,实现实时数据共享。
WebRTC 受到主流网络浏览器的支持,包括 Google Chrome、Mozilla Firefox、Safari 和 Microsoft Edge。WebRTC 之所以受到广泛采用,是因为其开源特性、易于实现,而且无需第三方插件即可构建无缝实时通讯应用程序。
2. 了解须要的 WebRTC API
要利用 WebRTC(Web 实时通讯),您需要熟悉促进 Web 浏览器之间实时通讯所需的 API 和库。WebRTC 可直接在 Web 应用程序内实现点对点音频、视频和数据传播输,使其成为构建视频集会、语音通话和其他实时通讯功能的理想选择。以下是您应该了解的根本组件:
2.1 getUserMedia API(获取用户媒体)
该API可以访问用户的媒体装备(摄像头和麦克风),并提供可与RTCPeerConnection一起利用的MediaStream对象。
2.2 RTCPeerConnection API
该 API 是 WebRTC 的焦点,负责建立和管理浏览器之间的点对点连接。它处置处罚 ICE(交互式连接建立)协商、NAT 遍历和媒体传播输。
2.3 RTCDataChannel API
此 API 提供无需服务器的点对点数据通讯功能。它可用于在对等点之间发送恣意数据。
2.4 Signaling(信令)
WebRTC 需要在建立直接连接之前通过信令在对等端之间互换连接详细信息。此过程不是由 WebRTC 标准定义的,需要单独的信令机制,例如 WebSocket 或服务器端应用程序。
2.5 其他 WebRTC API
- MediaStream:允许访问来自用户媒体装备(如摄像头和麦克风)的音频和视频流。
- RTCIceCandidate:表现 ICE 候选,在对等连接建立期间利用。
- RTCSessionDescription:表现建立连接的会话描述。
3. 什么是 STUN、TURN 和 ICE?
ICE, STUN and TURN
ICE(交互式连接建立)、STUN(NAT 会话遍历实用程序)和 TURN(利用中继绕过 NAT 举行遍历)是 WebRTC 框架的重要组成部门,可实现互联网上的实时通讯。它们用于在客户端之间建立点对点连接,即使它们位于防火墙或网络地点转换 (NAT) 装备后面。
ICE(交互式连接建立) ICE 是一种联合 STUN 和 TURN 服务器的技术,用于发现并建立 WebRTC 客户端之间的最佳连接路径,即使在具有挑衅性的网络环境中也能实现实时通讯。
STUN(NAT 的会话遍历实用程序) STUN 是一种用于发现客户端所处公共 IP 地点和端口的协议。ICE 是一种联合 STUN 和 TURN 服务器的技术,用于发现并建立 WebRTC 客户端之间的最佳连接路径,即使在具有挑衅性的网络环境中也能实现实时通讯。
TURN(利用中继绕过 NAT)当由于网络配置受限而无法建立直接对等连接时,TURN 服务器可充当中介。它们在客户端之间中继媒体流,确保可靠的通讯。
4. 设置开发环境
4.1 让我们用 React 创建一个简单的网页
起首,确保你的呆板上安装了 Node.js。然后,打开终端或下令提示符并运行以下下令来创建一个新的 React 应用程序:
- npx create-react-app simple-webrtc
复制代码 接下来,导航到项目目录并启动 Web 服务器
- cd simple-webrtc
- npm start
复制代码 然后,在代码编辑器中打开该项目。您会在文件夹中找到重要代码文件src。您可以编辑App.js以修改网页内容。
- import React from 'react';
- import './App.css';
- function App() {
- return (
- <div className="App">
- <h1>Welcome to My Simple Web Page</h1>
- <p>This is a basic web page built with React.</p>
- </div>
- );
- }
- export default App;
复制代码 在我的网页示例中,我将利用 Ant Design 作为 UI 库,以使我的生活更轻松。编辑后,我的 React 页面将如下所示:
- import React from 'react';
- import {Button, Typography, Input} from 'antd';
- import '../App.css';
- const {Title, Paragraph} = Typography;
- const {TextArea} = Input;
- function App() {
- const renderHelper = () => {
- return (
- <div className="wrapper">
- <Input
- placeholder="User ID"
- style={{width: 240, marginTop: 16}}
- />
- <Input
- placeholder="Channel Name"
- style={{width: 240, marginTop: 16}}
- />
- <Button
- style={{width: 240, marginTop: 16}}
- type="primary"
- >
- Call
- </Button>
- <Button
- danger
- style={{width: 240, marginTop: 16}}
- type="primary"
- >
- Hangup
- </Button>
- </div>
- );
- };
- const renderTextarea = () => {
- return (
- <div className="wrapper">
- <TextArea
- style={{width: 240, marginTop: 16}}
- placeholder='Send message'
- />
- <TextArea
- style={{width: 240, marginTop: 16}}
- placeholder='Receive message'
- disabled
- />
- <Button
- style={{width: 240, marginTop: 16}}
- type="primary"
- disabled={sendButtonDisabled}
- >
- Send Message
- </Button>
- </div>
- );
- };
- return (
- <div className="App">
- <div className="App-header">
- <Title>WebRTC</Title>
- <Paragraph>This is a simple demo app that demonstrates how to build a WebRTC application from scratch, including a signaling server. It serves as a step-by-step guide to help you understand the process of implementing WebRTC in your own projects.</Paragraph>
- <div className='wrapper-row' style={{justifyContent: 'space-evenly', width: '50%'}}>
- {renderHelper()}
- {renderTextarea()}
- </div>
- <div
- className='playerContainer'
- id="playerContainer"
- >
- <video
- id="peerPlayer"
- autoPlay
- style={{width: 640, height: 480}}
- />
- <video
- id="localPlayer"
- autoPlay
- style={{width: 640, height: 480}}
- />
- </div>
- </div>
- </div>
- );
- }
- export default App;
复制代码 现在,我们已经乐成为WebRTC创建了一个根本的网页。

4.2. 构建根本的 WebRTC 视频通话
4.2.1 步调 1:设置本地媒体流(摄像头和麦克风)。
- let localStream;
- const setupDevice = () => {
- console.log('setupDevice invoked');
- navigator.getUserMedia({ audio: true, video: true }, (stream) => {
- // render local stream on DOM
- const localPlayer = document.getElementById('localPlayer');
- localPlayer.srcObject = stream;
- localStream = stream;
- }, (error) => {
- console.error('getUserMedia error:', error);
- });
- };
复制代码 在 WebRTC 中处置处罚媒体流和束缚对于控制实时通讯期间的音频和视频行为至关重要。您可以在向用户请求媒体时指定束缚,例如分辨率、帧速率或特定装备。束缚有助于定制媒体捕捉以满足特定要求。
- const constraints = {
- video: {
- width: { ideal: 1280 },
- height: { ideal: 720 },
- frameRate: { ideal: 30 },
- },
- audio: true,
- };
- navigator.mediaDevices.getUserMedia(constraints)
- .then((stream) => {
- // Handle the media stream as needed.
- })
- .catch((error) => {
- // Handle the error if constraints cannot be satisfied.
- });
复制代码 4.2.2 第 2 步:建立 RTCPeerConnection。
- const servers;
- const pcConstraints = {
- 'optional': [
- {'DtlsSrtpKeyAgreement': true},
- ],
- };
- // When user clicks call button, we will create the p2p connection with RTCPeerConnection
- const callOnClick = () => {
- console.log('callOnClick invoked');
- if (localStream.getVideoTracks().length > 0) {
- console.log(`Using video device: ${localStream.getVideoTracks()[0].label}`);
- }
- if (localStream.getAudioTracks().length > 0) {
- console.log(`Using audio device: ${localStream.getAudioTracks()[0].label}`);
- }
- localPeerConnection = new RTCPeerConnection(servers, pcConstraints);
- localPeerConnection.onicecandidate = gotLocalIceCandidateOffer;
- localPeerConnection.onaddstream = gotRemoteStream;
- localPeerConnection.addStream(localStream);
- localPeerConnection.createOffer().then(gotLocalDescription);
- };
- // async function to handle offer sdp
- const gotLocalDescription = (offer) => {
- console.log('gotLocalDescription invoked:', offer);
- localPeerConnection.setLocalDescription(offer);
- };
- // async function to handle received remote stream
- const gotRemoteStream = (event) => {
- console.log('gotRemoteStream invoked');
- const remotePlayer = document.getElementById('peerPlayer');
- remotePlayer.srcObject = event.stream;
- };
- // async function to handle ice candidates
- const gotLocalIceCandidateOffer = (event) => {
- console.log('gotLocalIceCandidateOffer invoked', event.candidate, localPeerConnection.localDescription);
- // when gathering candidate finished, send complete sdp
- if (!event.candidate) {
- const offer = localPeerConnection.localDescription;
- // send offer sdp to signaling server via websocket
- sendWsMessage('send_offer', {
- channelName,
- userId,
- sdp: offer,
- });
- }
- };
复制代码 处置处罚 WebRTC 中的媒体流和束缚对于控制实时通讯期间的音频和视频行为至关重要。以下是如何管理媒体流和束缚的简要概述:
我们利用gotLocalIceCandidateOffer函数处置处罚 ICE 候选。候选网络完成后,我们通过信令发送完整的 SDP。如果为event.candidate空,则表现 ICE 候选网络已准备停当。处置处罚 ICE 候选的方法有两种:一种是将 ICE 候选插入 SDP 并将它们一起发送,另一种是通过信令将每个 ICE 候选发送给远程用户。然后远程用户在其本地对等连接中设置它。
在此阶段,我们已经完成了 RTCPeerConnection 的设置并天生了 offer SDP。但是,为了与远程浏览器建立连接,我们需要一个信令服务器来互换 SDP。
4.3 实现信令服务器
信令服务器在 WebRTC 通讯中起着至关重要的作用。它促进对等端之间互换会话信息 (SDP),从而允许它们建立直接的对等连接。信令过程包括将本地浏览器天生的 SDP 请求发送到远程浏览器,反之亦然。
信令服务器
一旦信令服务器收到本地浏览器的 SDP 请求,它就会将其转发到远程浏览器。然后远程浏览器天生其 SDP 应答并通过信令服务器将其发送回本地浏览器。
这种 SDP 提供和回复的互换使得两个浏览器能够协商媒体流的参数,例如编解码器、支持的分辨率以及乐成举行点对点通讯所需的其他设置。
信令服务器不传输现实的媒体流;它仅充当在对等端之间互换 SDP 的信使。一旦 SDP 互换完成,媒体流就会直接在对等端之间传输,从而为实时通讯创建直接且安全的连接。
请记住,您可以利用各种技术来实现信令服务器,例如 WebSockets、HTTP 或任何其他符合的通讯协议。信令服务器技术的选择取决于您的 WebRTC 应用程序的详细要求。
4.4 利用 Express.js 建立 NodeJs 服务器
- const debug = require('debug')(`${process.env.APPNAME}:index`);
- const app = require('express')();
- const server = require('http').Server(app);
- const wss = require ('./wss');
- const HTTPPORT = 4000;
- const WSSPORT = 8090;
- // init the websocket server on 8090
- wss.init(WSSPORT)
- // init the http server on 4000
- server.listen(HTTPPORT, () => {
- debug(`${process.env.APPNAME} is running on port: ${HTTPPORT}`);
- });
复制代码 NodeJs实现WebSocket
- const debug = require('debug')(`${process.env.APPNAME}:wss`);
- const WebSocket = require('ws');
- let channels = {}
- function init (port) {
- debug('ws init invoked, port:', port)
- const wss = new WebSocket.Server({ port });
- wss.on('connection', (socket) => {
- debug('A client has connected!');
-
- socket.on('error', debug);
- socket.on('message', message => onMessage(wss, socket, message));
- socket.on('close', message => onClose(wss, socket, message));
- })
- }
- function send(wsClient, type, body) {
- debug('ws send', body);
- wsClient.send(JSON.stringify({
- type,
- body,
- }))
- }
- function clearClient(wss, socket) {
- // clear client by channel name and user id
- Object.keys(channels).forEach((cname) => {
- Object.keys(channels[cname]).forEach((uid) => {
- if (channels[cname][uid] === socket) {
- delete channels[cname][uid]
- }
- })
- })
- }
- function onMessage(wss, socket, message) {
- debug(`onMessage ${message}`);
- const parsedMessage = JSON.parse(message)
- const type = parsedMessage.type
- const body = parsedMessage.body
- const channelName = body.channelName
- const userId = body.userId
-
- switch (type) {
- case 'join': {
- // join channel
- if (channels[channelName]) {
- channels[channelName][userId] = socket
- } else {
- channels[channelName] = {}
- channels[channelName][userId] = socket
- }
- const userIds = Object.keys(channels[channelName])
- send(socket, 'joined', userIds)
- break;
- }
- case 'quit': {
- // quit channel
- if (channels[channelName]) {
- channels[channelName][userId] = null
- const userIds = Object.keys(channels[channelName])
- if (userIds.length === 0) {
- delete channels[channelName]
- }
- }
- break;
- }
- case 'send_offer': {
- // exchange sdp to peer
- const sdp = body.sdp
- let userIds = Object.keys(channels[channelName])
- userIds.forEach(id => {
- if (userId.toString() !== id.toString()) {
- const wsClient = channels[channelName][id]
- send(wsClient, 'offer_sdp_received', sdp)
- }
- })
- break;
- }
- case 'send_answer': {
- // exchange sdp to peer
- const sdp = body.sdp
- let userIds = Object.keys(channels[channelName])
- userIds.forEach(id => {
- if (userId.toString() !== id.toString()) {
- const wsClient = channels[channelName][id]
- send(wsClient, 'answer_sdp_received', sdp)
- }
- })
- break;
- }
- case 'send_ice_candidate': {
- const candidate = body.candidate
- let userIds = Object.keys(channels[channelName])
- userIds.forEach(id => {
- if (userId.toString() !== id.toString()) {
- const wsClient = channels[channelName][id]
- send(wsClient, 'ice_candidate_received', candidate)
- }
- })
- }
- default:
- break;
- }
- }
- function onClose(wss, socket, message) {
- debug('onClose', message);
- clearClient(wss, socket)
- }
复制代码 React实现WebSocket
- import React, {useRef} from 'react';
- import {useEffect} from 'react';
- const URL_WEB_SOCKET = 'ws://localhost:8090/ws';
- function App() {
- const ws = useRef(null);
- useEffect(() => {
- const wsClient = new WebSocket(URL_WEB_SOCKET);
- wsClient.onopen = () => {
- console.log('ws opened');
- ws.current = wsClient;
- // setup camera and join channel after ws opened
- join();
- setupDevice();
- };
- wsClient.onclose = () => console.log('ws closed');
- wsClient.onmessage = (message) => {
- console.log('ws message received', message.data);
- const parsedMessage = JSON.parse(message.data);
- switch (parsedMessage.type) {
- case 'joined': {
- const body = parsedMessage.body;
- console.log('users in this channel', body);
- break;
- }
- case 'offer_sdp_received': {
- const offer = parsedMessage.body;
- onAnswer(offer);
- break;
- }
- case 'answer_sdp_received': {
- gotRemoteDescription(parsedMessage.body);
- break;
- }
- case 'quit': {
- break;
- }
- default:
- break;
- }
- };
- return () => {
- wsClient.close();
- };
- }, []);
- const sendWsMessage = (type, body) => {
- console.log('sendWsMessage invoked', type, body);
- ws.current.send(JSON.stringify({
- type,
- body,
- }));
- };
- }
复制代码 利用时要审慎const ws = useRef(null),并考虑为什么不直接利用wsClient = new WebSocket(URL_WEB_SOCKET)。React Hooks 的行为不同,ws每次页面重新渲染时变量都会被重置。为了确保 WebSocket 连接在渲染过程中保持不变,我们可以利用钩子useRef。这类似于在类上利用实例变量,而且与钩子不同,它不受重新渲染的影响useState。
通过利用useRef,我们可以在组件的整个生命周期内保持对 WebSocket 实例的稳定引用。这使我们能够有效地管理 WebSocket 连接,而不会受到渲染更新的影响。请记住 重要useRef用于处置处罚在渲染过程中连续存在的可变值,使其成为管理 React 组件中 WebSocket 连接的理想选择。
有了信令服务器,您的 WebRTC 应用程序将能够建立连接并实现远程对等点之间的无缝音频和视频通讯。
4.5 完成召唤应答部门
现在,我们险些已经到达了完整 WebRTC 应用程序的最后一部门,当远程用户接到对方的召唤时,我们需要处置处罚应答逻辑。该过程与之前类似,但这次我们将天生应答 SDP 并通过信令服务器将其返回给召唤者。
- const onAnswer = (offer) => {
- console.log('onAnswer invoked');
- setCallButtonDisabled(true);
- setHangupButtonDisabled(false);
- if (localStream.getVideoTracks().length > 0) {
- console.log(`Using video device: ${localStream.getVideoTracks()[0].label}`);
- }
- if (localStream.getAudioTracks().length > 0) {
- console.log(`Using audio device: ${localStream.getAudioTracks()[0].label}`);
- }
- localPeerConnection = new RTCPeerConnection(servers, pcConstraints);
- localPeerConnection.onicecandidate = gotLocalIceCandidateAnswer;
- localPeerConnection.onaddstream = gotRemoteStream;
- localPeerConnection.addStream(localStream);
- localPeerConnection.setRemoteDescription(offer);
- localPeerConnection.createAnswer().then(gotAnswerDescription);
- };
- const gotRemoteStream = (event) => {
- console.log('gotRemoteStream invoked');
- const remotePlayer = document.getElementById('peerPlayer');
- remotePlayer.srcObject = event.stream;
- };
- const gotAnswerDescription = (answer) => {
- console.log('gotAnswerDescription invoked:', answer);
- localPeerConnection.setLocalDescription(answer);
- };
- const gotLocalIceCandidateAnswer = (event) => {
- console.log('gotLocalIceCandidateAnswer invoked', event.candidate, localPeerConnection.localDescription);
- // gathering candidate finished, send complete sdp
- if (!event.candidate) {
- const answer = localPeerConnection.localDescription;
- sendWsMessage('send_answer', {
- channelName,
- userId,
- sdp: answer,
- });
- }
- };
- }
复制代码 5. 开始直播
最后,我们乐成完成了设置 WebRTC 的复杂过程。现在,让我们通过运行npm start并打开两个网页来启动 Web 应用程序——一个用于召唤者,另一个用于被召唤者。单击Call召唤者页面上的按钮,即可开始通过 WebRTC 举行直播。
利用 WebRTC 举行直播
6. 了解演示应用程序
以下是利用 WebRTC API 的典型 10 个步调:
- 从本地装备(例如麦克风、网络摄像头)捕捉媒体流。
- 从 MediaStream 获取 URL blob。
- 利用 URL blob 预览本地媒体。
- 创建一个 RTCPeerConnection 对象。
- 将本地流添加到新创建的连接。
- 将您自己的会话描述发送给远程端。
- 从对等方接收远程会话描述。
- 处置处罚收到的会话描述并将远程流添加到您的 RTCPeerConnection。
- 从远程流中获取 URL blob。
- 利用 URL blob 播放远程对等点的音频和/或视频。
通过全面的端到端图表,您可以完整了解此 WebRTC 应用程序的整个流程。
7. 实现数据通道
WebRTC 中的数据通道是一种功能,允许在点对点连接中两个对等端之间以低延迟方式双向通讯恣意数据。与媒体流(用于音频和视频)不同,数据通道提供了一种在浏览器之间直接互换非媒体数据的方法,使实在用于各种实时应用程序。
实现数据通道涉及在 RTCPeerConnection 中创建数据通道并处置处罚其状态和消息事件以在对等端之间互换数据。数据通道 API 提供 send() 等方法来发送数据,以及 onmessage、onopen、onclose 和 onerror 等事件来处置处罚通讯事件。
7.1 实现对等体之间的数据互换
- const createDataChannel = () => {
- try {
- console.log('localPeerConnection.createDataChannel invoked');
- sendChannel = localPeerConnection.createDataChannel('sendDataChannel', {reliable: true});
- } catch (error) {
- console.error('localPeerConnection.createDataChannel failed', error);
- }
- sendChannel.onopen = handleSendChannelStateChange;
- sendChannel.onClose = handleSendChannelStateChange;
- localPeerConnection.ondatachannel = gotReceiveChannel;
- };
- const sendOnClick = () => {
- console.log('sendOnClick invoked', sendMessage);
- sendChannel.send(sendMessage);
- setSendMessage('');
- };
- const gotReceiveChannel = (event) => {
- console.log('gotReceiveChannel invoked');
- receiveChannel = event.channel;
- receiveChannel.onmessage = handleMessage;
- receiveChannel.onopen = handleReceiveChannelStateChange;
- receiveChannel.onclose = handleReceiveChannelStateChange;
- };
- const handleMessage = (event) => {
- console.log('handleMessage invoked', event.data);
- setReceiveMessage(event.data);
- setSendMessage('');
- };
- const handleSendChannelStateChange = () => {
- const readyState = sendChannel.readyState;
- console.log('handleSendChannelStateChange invoked', readyState);
- if (readyState === 'open') {
- setSendButtonDisabled(false);
- } else {
- setSendButtonDisabled(true);
- }
- };
- const handleReceiveChannelStateChange = () => {
- const readyState = receiveChannel.readyState;
- console.log('handleReceiveChannelStateChange invoked', readyState);
- };
- }
复制代码 7.2 发送和接收非媒体数据
我们已经乐成利用 WebRTC 实现了点对点数据通道。为了查看实在际效果,让我们通过运行npm start并打开两个网页来启动 Web 应用程序。在召唤者的页面上,单击Call按钮以启动对等连接。
连接后,输入Hello, World!!!召唤者的文本地区并单击Send按钮。
通过数据通道发送消息
您将看到该消息在另一端被实时接收,展示了 WebRTC 的无缝数据传输能力。
从数据通道接收消息
8. 高级 WebRTC 功能
8.1 管理音频和视频编解码器以获得最佳性能
选择在质量和带宽消耗之间取得均衡的编解码器。WebRTC 支持各种编解码器,例如视频的 VP8、VP9、H.264,以及音频的 Opus、G.711、G.722。选择编解码器时,请考虑目标装备和网络条件。例如,VP8 受到广泛支持而且质量精良,而 H.264 大概更适合某些装备上的硬件加快解码。
8.2 利用加密保护 WebRTC 连接
WebRTC 利用数据报传输层安全性 (DTLS) 协议来加密媒体流。DTLS 为 UDP 数据传输提供安全加密。在建立对等连接时,WebRTC 利用 DTLS 协商和互换用于加密媒体流的加密密钥。
如果您利用 WebRTC 数据通道互换非媒体数据,请启用数据通道消息加密。数据通道利用 DTLS 上的 SCTP(流控制传输协议)举行安全数据传输。
确保您的信令服务器和媒体服务器(如果利用)支持安全传输协议,例如 HTTPS 和 WSS(WebSocket Secure)。HTTPS 为互换信令数据提供了安全通道,而 WSS 则确保 WebRTC 中利用的 WebSocket 连接的安全通讯。
8.3 实现屏幕共享功能
利用getDisplayMedia或navigator.mediaDevices.getDisplayMediaAPI 来捕捉用户的屏幕。此 API 允许用户授予与应用程序共享其屏幕的权限。请务必处置处罚用户拒绝或没有所需权限的情况。
8.4 利用 WebRTC 和 WebAssembly 举行性能优化
WebAssembly 提供了一种在浏览器中直接执行用 C、C++ 和 Rust 等语言编写的代码以及 JavaScript 的方法。依附靠近原生的性能,它可以更高效地执行视频处置处罚、图像识别和加密/解密等计算密集型使命。
通过将性能关键使命卸载到 WebAssembly 模块,开发人员可以通过多种方式优化他们的 WebRTC 应用程序:
- 视频和音频处置处罚:WebAssembly 可以处置处罚视频和音频的编码/解码、过滤和分析,从而减轻主 JavaScript线程的负担并提高团体性能。
- 加密和解密:WebRTC 数据通道通常需要安全通讯。利用 WebAssembly 举行加密/解密使命可以加快进程并确保数据安全。
- 人工智能和呆板学习:复杂的人工智能算法和呆板学习模型可以通过 WebAssembly 执行,从而实现 WebRTC 应用程序内大型数据集的实时处置处罚。
9. 完整示例代码
所有代码都在git上,可以完整获取到!
9.1 WebRTC 示例代码
https://github.com/giftedunicorn/webpig/blob/main/src/pages/webrtc.js
9.2 信令服务器示例代码
https://github.com/giftedunicorn/webpig/blob/main/server/index.js
9.2 Agora RTC Web SDK 示例代码
https://github.com/giftedunicorn/webpig/blob/main/src/pages/agorawebsdk.js
10. 结束
恭喜!您现在已经了解了 WebRTC 的底子知识并构建了一个根本的视频通话应用程序。这只是您的 WebRTC 之旅的开始。借助 WebRTC 的巨大潜力,您可以探索各种应用程序,从视频集会到在线游戏等等。继承尝试,磨练您的技能,并对不停发展的 WebRTC 世界保持好奇心。
请记住,实时通讯触手可及,因此请拥抱这项强大的技术,将您的 Web 应用程序提升到新的程度。祝您编码愉快!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |