HTML5实现一对一视频聊天

Wesley13
• 阅读 919

相关技术栈

对于移动端来说,大多是视频聊天功能都是采用的Native端的代码来实现,这种方式性能好,兼容性强但是开发成本也会高一些,那么本文就来介绍一下采用纯H5的方式来实现视频聊天功能。

  1. WebRTC
  2. Socket.io
  3. Node.js

项目截图:

体验地址:https://app.nihaoshijie.com.cn/webrtc/index.html

推荐使用Safari打开。

WebRTC介绍

WebRTC 主要提供了三个核心的 API:

  • getUserMedia:可以获取本地的媒体流,一个流包含几个轨道,比如视频和音频轨道。
  • getDisplayMedia:获取电脑屏幕的视频流,不过暂时无法获取音频媒体流,如果需要音频流,手动添加到轨道内,使之同步播放。
  • RTCPeerConnection:用于建立 P2P 连接以及传输多媒体数据。
  • RTCDataChannel:建立一个双向通信的数据通道,可以传递多种数据类型。

通过这几个 API,我们可以获取本地的音视频流,然后与其他浏览器建立点对点连接并将音视频流发送给对方,还可以建立一个建立一个双向的数据通道,发送文本、文件等实时数据。

本次的项目,我们主要用到的是getUserMediaRTCPeerConnection相关的API。

getUserMedia音视频采集 API

可以使用浏览器提供的getUserMedia接口,采集本地的音视频。

const localVideo = document.getElementById('local-video');
//   非安全模式(非https/localhost)下 navigator.mediaDevices 会返回 undefined
const mediaStream = await navigator.mediaDevices.getUserMedia({ 
    video: true, 
    audio: true
});
localVideo.srcObject = mediaStream;

RTCPeerConnection创建点对点连接的 API

RTCPeerConnection 作为创建点对点连接的 API,是我们实现音视频实时通信的关键,主要会用到以下方法和事件:

媒体协商方法

  • createOffer

  • createAnswer

  • setLocalDesccription

  • setRemoteDesccription
    重要事件

  • onicecandidate

  • ontrack

对于点对点连接,就需要有发送方和接收方,对应上面的代码,分别是:

发送方:

const pc = new RTCPeerConnection(iceConfig);
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
sendToPeerViaSignalingServer(SIGNALING_OFFER, offer); // 发送方发送信令消息

接收方:

const pc = new RTCPeerConnection(iceConfig);
await pc.setRemoteDescription(offer);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
sendToPeerViaSignalingServer(SIGNALING_ANSWER, answer); // 接收方发送信令消息

添加音视频流:

// 添加音视频流
mediaStream.getTracks().forEach(track => {
    pc.addTrack(track, mediaStream);
});

接收音视频流:

remotePeer.ontrack = function(evt) {
    const remoteVideo = document.getElementById('remote-video');
    remoteVideo.srcObject = evt.streams[0];
}

有些会采用addstreamonaddstream属于老版本的API,这里不再推荐使用。

通信协商流程

在 WebRTC 中,有一个专门的协议,称为Session Description Protocol(SDP),可以用于描述上述这类信息。因此参与音视频通讯的双方想要了解对方支持的媒体格式,必须要交换 SDP 信息。而交换 SDP 的过程,通常称之为媒体协商。整个媒体协商流程如下:

  1. 呼叫端创建 Offer(createOffer)并将 offer 消息(内容是呼叫端的 SDP 信息)通过信令服务器传送给接收端,同时调用 setLocalDesccription 将含有本地 SDP 信息的 Offer 保存起来。

  2. 接收端收到对端的 Offer 信息后调用 setRemoteDesccription 方法将含有对端 SDP 信息的 Offer 保存起来,并创建 Answer(createAnswer)并将 Answer 消息(内容是接收端的 SDP 信息)通过信令服务器传送给呼叫端。

  3. 呼叫端收到对端的 Answer 信息后调用 setRemoteDesccription 方法将含有对端 SDP 信息的 Answer 保存起来。

更多关于WebRTC相关的文档可以参考[官网地址]webrtc.github.io/webrtc-org/architecture/

项目代码

在这里就不整体贴大段的代码来讲解了,感兴趣的童鞋可以参考源码[GitHub]github.com/lvming6816077/liveone来理解,这里笔者简单的说明一下整体的代码逻辑。

  1. 对于Vue端主要实现的是视频的预览功能和一些来电或者响应相关的CSS3动画。
  2. 对于Node.js端主要实现的是实时的信息通信(socket.io的room相关API),包括了识别对方的信令信息和用户的一些基本头像昵称信息的通信。
  3. 整体的WebRTC协议的逻辑都是安装上文中所讲解的代码方式来体现。

点击查看更多内容

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这