前端WebRTC局域网1V1视频通话

2024-03-06 13:28

本文主要是介绍前端WebRTC局域网1V1视频通话,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基本概念

WebRTC(Web Real-Time Communications)

网络实时通讯,它允许网络应用或者站点,在不借助中间媒介的情况下,建立点对点(Peer-to-Peer)的连接,实现视频流和音频流或者其他任意数据的传输

NAT(Network Address Translation)

网络地址转换协议,用来给私网设备映射一个公网的 IP 地址

STUN(Session Traversal Utilities for NAT)

会话穿透,通过NAT找到公网地址进行P2P通信

TURN(Traversal Using Relay around NAT)

中继转发,当STUN不可用时,通过TURN转发音视频数据,显然这样是开销最大的
开源STUN&TURN服务器:coturn

ICE(Interactive Connectivity Establishment)

交互式连接建立,即网络信息
candidate:候选,优先级为:局域网、STUN、TURN

SDP(Session Description Protocol)

会话描述协议,即媒体信息,不是音视频流,在WebRTC中分为offer和answer

Signaling Server

信令服务器,用来交换ICE和SDP信息,WebRTC未做规定,自己选择实现技术,比如WebSocket

局域网视频通信

局域网不需要STUN/TURN服务器,只需信令服务器,这里使用Node.js ws库实现

效果

在这里插入图片描述

代码

客户端 index.html
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>WebRTC Demo</title><style>button {margin: 1rem;}video {width: 300px;}</style>
</head><body><div><div>信令服务器地址:<input id="inputServer" value="ws://192.168.205.165:8888" /><button onclick="start()">开始</button></div><video id="localVideo" autoplay muted></video><video id="remoteVideo" autoplay muted></video></div><script>const inputServer = document.querySelector("#inputServer");const remoteVideo = document.querySelector("#remoteVideo");const localVideo = document.querySelector("#localVideo");let peerConn;let webSocket;let localStream;// 打开本地摄像头navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then((mediaStream) => {localStream = mediaStream;localVideo.srcObject = mediaStream;}).catch((err) => {console.error(err);});// 创建WebRTC连接peerConn = new RTCPeerConnection();peerConn.addEventListener('icecandidate', (event) => {if (event.candidate) {webSocket.send(JSON.stringify({type: "ice",candidate: event.candidate}));}});peerConn.addEventListener("track", (event) => {remoteVideo.srcObject = event.streams[0];});function start() {// 连接信令服务器webSocket = new WebSocket(inputServer.value);webSocket.addEventListener('open', () => {webSocket.send(JSON.stringify({type: "join"}));});// 收到服务端消息webSocket.addEventListener('message', (event) => {const msg = JSON.parse(event.data);console.log(msg);switch (msg.type) {case "sendOffer":peerConn.addTrack(localStream.getVideoTracks()[0], localStream);peerConn.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true }).then((offer) => {peerConn.setLocalDescription(offer).then(() => {webSocket.send(JSON.stringify(offer));})});break;case "offer":peerConn.addTrack(localStream.getVideoTracks()[0], localStream);peerConn.setRemoteDescription(msg).then(() => {peerConn.createAnswer().then((answer) => {peerConn.setLocalDescription(answer).then(() => {webSocket.send(JSON.stringify(answer));})})});break;case "answer":peerConn.setRemoteDescription(msg);break;case "ice":peerConn.addIceCandidate(msg.candidate);break;default:}});webSocket.addEventListener('close', () => {console.log("websocket close");});}</script>
</body></html>
服务端 server.mjs
import { WebSocketServer } from 'ws';const wss = new WebSocketServer({ port: 8888 });let clients = []; // 已连接的客户端wss.on('connection', function connection(ws) {ws.on('message', function message(rawData) {const data = rawData.toString();const obj = JSON.parse(data);console.log("type", obj.type);switch (obj.type) {case "join":if (clients.length < 2) {clients.push(ws);if (clients.length === 2) {clients[0].send(JSON.stringify({ type: "sendOffer" }));}} else {console.log("room is full");}break;case "offer":clients[1].send(data);break;case "answer":clients[0].send(data);break;case "ice":clients.forEach((item) => {if (item !== ws) {item.send(data);}})break;default:}});ws.on('error', (err) => console.error("error:", err));ws.on('close', (code) => {console.log("ws close", code);clients = clients.filter((item) => {if (item === ws) {item = null;return false;}return true;});});
});

使用

  1. 在文件目录运行命令:node server.mjs
  2. 修改信令服务器地址,浏览器打开 index.html
  3. 将 index.html 复制到另一台电脑上用浏览器打开
  4. 允许使用摄像头和麦克风,两边点击开始按钮即可

参考资料

WebRTC_API
前端使用WebRTC

这篇关于前端WebRTC局域网1V1视频通话的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/780199

相关文章

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

HTML5表格语法格式详解

《HTML5表格语法格式详解》在HTML语法中,表格主要通过table、tr和td3个标签构成,本文通过实例代码讲解HTML5表格语法格式,感兴趣的朋友一起看看吧... 目录一、表格1.表格语法格式2.表格属性 3.例子二、不规则表格1.跨行2.跨列3.例子一、表格在html语法中,表格主要通过< tab

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

基于Python和MoviePy实现照片管理和视频合成工具

《基于Python和MoviePy实现照片管理和视频合成工具》在这篇博客中,我们将详细剖析一个基于Python的图形界面应用程序,该程序使用wxPython构建用户界面,并结合MoviePy、Pill... 目录引言项目概述代码结构分析1. 导入和依赖2. 主类:PhotoManager初始化方法:__in

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo