首页 > 其他分享 >webrtc

webrtc

时间:2024-03-15 19:45:36浏览次数:30  
标签:const 获取 媒体 pc video SDP webrtc

一、什么是WebRTC

WebRTC(Web Real-Time Communication)是一个由Google、Mozilla、Opera等公司发起的开源项目,它支持网页浏览器进行实时音视频对话。它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和音频流或者其他任意数据的传输。对于开发者而言,WebRTC提供了一套W3C Javascript API,包括音视频的采集、编解码、网络传输、显示等功能,使得开发者能够快速构建出音视频应用。WebRTC标准在较高层面上涵盖了两种不同的技术:媒体捕获设备和点对点连接。

二、媒体捕获

媒体捕获设备包括摄像头和麦克风,还包括屏幕捕获设备。可以利用navigator 这个浏览器内置对象身上的API来获取媒体流。

  1. navigator.mediaDevices.getUserMedia():获取摄像头和麦克风媒体流
  2. navigator.mediaDevices.getDisplayMedia():获取屏幕录制的媒体流

API的具体使用可以参考 MDN。从技术手册可以知道,getUserMedia()方法需要传入一个constraints约束对象作为参数。该参数用来指定请求的媒体类型和相对应的参数,而且必须指定至少一个类型。媒体类型具体可以配置哪些属性,可以使用navigator.mediaDevices.getSupportedConstraints()来获取。

image-20240315142430748

2.1 获取媒体流

// 指定约束对象,获取音频流和视频流,并设置视频流的分辨率为 1280 x 720
const constraints = {
  audio: true,
  video: {
    with: 1280,
    height: 720,
  },
};
// 获取媒体流
const stream = navigator.mediaDevices.getUserMedia(constraints);
console.log(stream);

运行上面的代码,浏览器会询问是否打开摄像头和麦克风,设置为允许就能获取媒体流了。打开控制台,发现getUserMedia()方法返回的是一个Promise。

image-20240315143416498

2.2 展示画面

将上面获取到的媒体流数据,绑定到一个video标签的srcObject属性上,就能通过video标签看到视频画面了。

但是需要注意两个地方:

  1. getUserMedia()方法返回的是Promise,所以需要在then方法中去绑定video标签的srcObject属性,或者使用async await的方式去获取Promise的值
  2. video标签需要设置autoplay属性,否则视频没办法自动播放
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webrtc</title>
  <style>
    .play-content {
      width: 500px;
      height: 500px;
    }
  </style>
</head>

<body>
  <video class="play-content" autoplay></video>
  <script src="./webrtc01.js"></script>
</body>

</html>
// 指定约束对象,获取音频流和视频流,并设置视频流的分辨率为 1280 x 720
const constraints = {
  audio: true,
  video: {
    with: 1280,
    height: 720,
  },
};

// 获取媒体流
navigator.mediaDevices.getUserMedia(constraints).then(value => {
  // 将媒体流与video标签绑定
  document.querySelector(".play-content").srcObject = value
})

执行上面的代码,就能看到视频画面了

2.3 获取屏幕

在上面使用了getUserMedia()这个API来获取媒体流。接下来使用getDisplayMedia()这个API来捕获屏幕。使用方法和getUserMedia()一致

// 指定约束对象,获取音频流和视频流,并设置视频流的分辨率为 1280 x 720
const constraints = {
  audio: true,
  video: {
    with: 1280,
    height: 720,
  },
};
// 获取屏幕的媒体流,并与video标签绑定
navigator.mediaDevices.getDisplayMedia(constraints).then((value) => {
  document.querySelector(".play-content").srcObject = value;
});

运行上面代码,浏览器会让你选择一个要打开的窗口。随便选择一个,就能获取到媒体流了。

image-20240315145755149

三、点对点连接

通过getUserMedia()getDisplayMedia()这两个API已经可以获取到媒体流了,那现在就需要考虑如何将媒体流发送给远端的浏览器。WebRTC要建立点对点的连接,首先有两个关键的问题要解决:

  1. 媒体协商:

    媒体协商主要关注通信双方支持的编解码器及其参数。这包括音频参数(如采样率、采样大小、通道数)和视频参数(如分辨率、帧率等)。媒体协商的目的是确保双方能够交换和理解彼此的音视频流。这通常通过Session Description Protocol(SDP)进行。

  2. 网络协商:

    网络协商则主要关注在互联网上建立可通信的链路。由于大多数设备没有独立的公网IP,因此需要进行网络地址转换(NAT)。WebRTC使用STUN(Session Traversal Utilities for NAT)和TURN(Traversal Using Relays around NAT)协议来帮助完成这一操作。STUN协议用于发现公共IP地址和UDP端口号,而TURN协议则用于在直接通信不可行时提供中继服务。网络协商的目标是找到一条可靠的网络路径,使得通信双方能够建立连接并进行实时通信。

也就是说,要确保webRTC的成功通信,需要通过媒体协商来确定双方都可用的编解码方式,还需要通过网络协商确定两端可建立正确通信链路的ip地址。下面是一张webRTC建立通信的图解,针对里面的过程,进行逐一讲解

img

3.1 RTCPeerConnection

具体介绍查看MDN

RTCPeerConnection是WebRTC(Web实时通信)API的一部分,它用于在浏览器之间建立点对点(peer-to-peer)连接,以支持实时通信,如音频、视频和数据交换。RTCPeerConnection提供了创建和管理这些连接所需的底层机制。

根据上面的图解,可以知道WebRTC建立通信的流程大致有以下过程:

  1. 客户端1创建RTCPeerConnection对象,并将本地媒体流通过addTrack方法添加到对象身上
  2. 通过createOffer方法创建本地SDP描述,并通过RTCPeerConnection对象的setLocalDescription方法设置本地描述
  3. 将SDP描述信息通过信令服务器转发给客户端2
  4. 客户端2收到发来的SDP描述,创建RTCPeerConnection对象,并通过setRemoteDescription方法设置远端描述
  5. 客户端2通过createAnswer方法创建本地的SDP描述,并通过 setLocalDescription方法设置本地描述
  6. 客户端2将Answer SDP通过信令服务器转发给客户端1
  7. 客户端1收到发来的Answer SDP,通过setRemoteDescription方法设置远端描述

根据以上流程,创建一个WebRtcClient类。该类具有绑定本地媒体流、创建offer、创建answer、接收answer等方法。

在获取本地流时,我获取的是屏幕捕获的流,这样方便看到效果。

class WebRtcClient {
  // 初始化 RTCPeerConnection 对象
  constructor() {
    this.pc = new RTCPeerConnection();
    this.offer = "";
    this.answer = "";
  }

  // 获取本地媒体流,并绑定到本地 video标签
  async init() {
    const localVideoBox = document.querySelector(".local");
    const remoteVideoBox = document.querySelector(".remote");
    // 设置约束
    const constraints = {
      audio: true,
      video: true,
    };
    // 获取视频流 (切换选择使用摄像头还是屏幕)
    // const stream = await navigator.mediaDevices.getUserMedia(constraints);
    const stream = await navigator.mediaDevices.getDisplayMedia(constraints);
    localVideoBox.srcObject = stream;

    // 将本地媒体流轨道添加到  RTCPeerConnection对象 中
    stream.getTracks().forEach((track) => {
      this.pc.addTrack(track, stream);
    });

    // 监听远程流变化
    this.pc.ontrack = (e) => {
      console.log("远端流变化了", e);
      remoteVideoBox.srcObject = e.streams[0];
    };
  }

  // 创建offer
  async createOffer() {
    // 存在新的候选,需要更新SDP信息
    this.pc.onicecandidate = async (e) => {
      if (e.candidate) {
        this.offer = this.pc.localDescription;
      }
    };
    // 创建offer, 并设置为本地SDP描述
    const offer = await this.pc.createOffer();
    await this.pc.setLocalDescription(offer);
  }

  // 创建answer
  async createAnswer(offer) {
    // 存在新的候选,需要更新SDP信息
    this.pc.onicecandidate = async (e) => {
      if (e.candidate) {
        this.answer = this.pc.localDescription;
      }
    };
    // 收到对端发送的offerSDP,设置为远端SDP
    await this.pc.setRemoteDescription(offer);
    // 创建answer,设置为本地SDP
    const answer = await this.pc.createAnswer();
    await this.pc.setLocalDescription(answer);
  }

  // 添加answerSDP
  async addAnswer(answer) {
    await this.pc.setRemoteDescription(answer);
  }
}

const client = new WebRtcClient();
client.init();

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .local,
    .remote {
      width: 300px;
      height: 300px;
    }
  </style>
</head>

<body>
  <video class="local" autoplay></video>
  <video class="remote" autoplay></video>
  <script src="./webrtcClient.js"></script>
</body>

</html>

下面一步一步操作,实现通信

  1. 打开两个浏览器页面,分别共享不同的画面

    image-20240315180149695

  2. 左边浏览器中调用client对象的createOffer方法

    image-20240315180403818

  3. 复制左边client对象的offerSDP,调用右边client对象的createAnswer方法,传入offerSDP

    直接右键复制,实际应该使用信令服务器进行转发

    image-20240315180641383

    调用右边client对象的createAnswer方法,传入offerSDP

    image-20240315180758176

  4. 复制右边client对象的answerSDP,调用左边client对象的addAnswer方法,并传入answerSDP

    image-20240315181100723

    image-20240315181132629

    然后,两个浏览器页面就可以进行视频通话了

    image-20240315192801153

上面的SDP交换过程,是手动进行的,主要是为了了解整个通信流程。后面可以创建一个信令服务器,通过WebSocket实现SDP的交换。

标签:const,获取,媒体,pc,video,SDP,webrtc
From: https://www.cnblogs.com/finish/p/18076116

相关文章

  • WebRTC 同一个浏览器同一台 无需信令服务 实现视频通话
    这个仅仅是原理告你信令服务的作用<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><metahttp-equiv=&......
  • WEBRTC 局域网 自己搭建信令服务 实现视频通讯
    信令服务constapp=require('express')();constwsInstance=require('express-ws')(app);app.ws('/',ws=>{ ws.on('message',data=>{ wsInstance.getWss().clients.forEach(server=>{ if(server!==ws)......
  • WebRTC 通讯隧道和信令服务实现服务视频通话
    安装NAT穿透服务器(ICEServer)brewinstallcoturn//添加用户turnadmin-a-uadmin-rrealm-padmin//测试服务turnutils_peer-p34800turnutils_uclient-v-e192.168.1.112-r34800-uadmin-wadmin-p3478192.168.1.112安装信令服务器gitclonehttps......
  • windows编译ZLMediaKit流媒体服务webrtc
    环境说明ZLMediaKit编译需要的软件visualstudio2022cmake3.29.0-rc2OpenSSL1.1.1w(不想踩坑的话安装这个版本)libsrtp2.6.0ZLMediaKit编译后运行需要libsrtp编译后且配置环境变量ZLMediaKit编译后文件visualstudiocmakevisualstuid......
  • webrtc终极版(三)将官方的demo部署到自己的服务器中
    webrtc终极版(三)将官方的demo部署到自己的服务器中本节,我们详细介绍下,如何再本地搭建RTCMultiConnection服务目录webrtc终极版(三)将官方的demo部署到自己的服务器中前言一、安装步骤1.下载并解压文件2.使用npm安装总结前言webrtc终极版系列,再年前,写了前两篇,还剩下两篇没有写,......
  • webrtc终极版(二)搭建自己的iceserver服务,并用到RTCMultiConnection的demo中
    webrtc终极版(二)搭建自己的iceserver服务,并用到RTCMultiConnection的demo中目录webrtc终极版(二)搭建自己的iceserver服务,并用到RTCMultiConnection的demo中前言一、stunserver,turnserver,iceserver是什么?二、具体搭建步骤1.下载安装coturn2、处理证书问题3、处理各个ip以及端口的配......
  • webrtc终极版(题外话)辛苦写文章分享,竟然遇到喷子狂喷,写篇文章回怼下,顺便发表下面对喷子
    webrtc终极版(题外话)辛苦写文章分享,竟然遇到喷子狂喷,写篇文章回怼下,顺便发表下面对喷子的处理方式第一篇文章发过后,出人意料的是,收到了博客园某一位用户的狂喷【注:本系列文章会同步发布到csdn、博客园、稀土掘金等平台上】,如下图示图片可能不清楚,我再把这位喷子的原话粘贴下来:......
  • webrtc终极版(一)5分钟搭建多人实时会议系统webrtc
    webrtc终极版(一),支持https,在线部署【不是本地demo】,采用RTCMultiConnection官方demo,5分钟即可搭建成功@目录webrtc终极版(一),支持https,在线部署【不是本地demo】,采用RTCMultiConnection官方demo,5分钟即可搭建成功前言一、webrtc是什么?二、搭建demo步骤1.代码内容2.运行效果总结前......
  • 视频监控EasyCVR如何通过设置sei接口,实现在webrtc视频流中添加画框和文字?
    安防视频监控系统基于视频综合管理平台EasyCVR视频系统,采用了开放式的网络结构,可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力,具备权限管理、设备管理、鉴权管理、流媒体接入与转......
  • 视频监控EasyCVR如何通过设置sei接口,实现在webrtc视频流中添加画框和文字?
    安防视频监控系统基于视频综合管理平台EasyCVR视频系统,采用了开放式的网络结构,可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力,具备权限管理、设备管理、鉴权管理、流媒体接入与转......