WebRTC实现Web实时语音/视频聊天/文件传输

答案是:能!

借助 WebRTC 不仅能做到音视频聊天,还能实现点对点文件传输。

WebRTC是什么?

WebRTCWeb Real-Time Communication )是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点( Peer-to-Peer )的连接,实现视频流和(或)音频流或者其他任意数据的传输。

WebRTC 包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点( Peer-to-Peer )的数据分享和电话会议成为可能。

WebRTC的来历

2010年5月,Google以6820万美元收购 VoIP 软件开发商 Global IP SolutionsGIPS 引擎,并改为名为“WebRTC”。 WebRTC 使用 GIPS 引擎,实现了基于网页的视频会议,并支持 722PCMILBCISAC 等编码,同时使用谷歌自家的 VP8 影片解码器;同时支持 RTP/SRTP 传输等。

2012年1月,谷经把这款软件集成到Chrome浏览器中。

WebRTC当前的浏览器支持情况

  • 桌面PC端
    • Microsoft Edge
    • Google Chrome 23
    • Mozilla Firefox 22
    • Opera 18
    • Safari 11
  • Android端
    • Google Chrome 28(从版本29开始默认开启)
    • Mozilla Firefox 24
    • Opera Mobile 12
  • Google Chrome OS
  • Firefox OS
  • iOS 11
  • Blackberry 10内置浏览器

附一张浏览器版本支持图如下:

WebRTC技术组成

底层技术

  • 影像引擎 ( VideoEngine )
  • 音效引擎 ( VoiceEngine )
  • 会话管理 ( Session Management )
  • iSAC 音效压缩
  • VP8 Google自家 WebM 项目的影片编解码器
  • APIs ( Native C++ API , Web API )

WebRTC 的底层实现非常复杂,附一张音视频处理流程图如下:

重要API

WebRTC 虽然底层实现极其复杂,但是面向开发者的API还是非常简洁的,主要分为三方面:

  • Network Stream API
    MediaStream
    MediaStreamTrack
    
  • RTCPeerConnection
    RTCPeerConnection
    RTCIceCandidate
    RTCIceServer
    
  • Peer-to-peer Data API
    • DataChannel :数据通道接口,表示一个在两个节点之间的双向的数据通道。

WebRTC技术点介绍

Network Stream API 网络流媒体接口

主要有两个 APIMediaStreamMediaStremTrack

  • MediaStreamTrack 代表一种单类型数据流,一个 MediaStreamTrack 代表一条 媒体轨道VideoTrackAudioTrack 。这给我们提供了混合不同轨道实现多种特效的可能性。
  • MediaStream 一个完整的音视频流,它可以包含多个 MediaStreamTrack 对象,它的主要作用是协同多个媒体轨道同时播放,也就是我们常说的音画同步。

MediaStream

我们要通过浏览器实现音视频通话,首先需要访问音/视频设备,这很简单:

const constraints = {
      audio: {
        echoCancellation: true,
        noiseSuppression: false
      },
      video: true
    };
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    document.getElementById('#video').srcObject = stream;
复制代码

调用 navigator.mediaDevices.getUserMedia 方法即可得到流媒体对象 MediaStream

constraints 是一个约束配置,它是用来规范当前采集的数据是否符合需要。

因为,我们采集视频时,不同的设备有不同的参数设置。

常用的如下所示:

{
    "audio": {
        echoCancellation: boolean,
        noiseSuppression: boolean
    },  // 是否捕获音频
    "video": {  // 视频相关设置
        "width": {
            "min": "381", // 当前视频的最小宽度
            "max": "640" 
        },
        "height": {
            "min": "200", // 最小高度
            "max": "480"
        },
        "frameRate": {
            "min": "28", // 最小帧率
             "max": "10"
        }
    }
}
复制代码

有些机器只具备麦克风,没有摄像头怎么办呢?这时如果 video: true 就会抛出异常: Requested device not found

我们需要检测是否具备设备可行性,通过 navigator.mediaDevices.enumerateDevices 可以枚举出所有的媒体设备,格式如下

{
    deviceId: "2c6e3e1b727b1442f905459e4cd47902988ccac6dff4361ae657cf44c4f3f55c"
    groupId: "781470b0bba090c6eb2b26eaa2e643e65a08e37f252f406d31da4d90cc3952e9"
    kind: "audioinput"
    label: "默认 - 麦克风"
},
{
    deviceId: "fe4d04d603512966a729e1313067574f462dbdc579d6ddaad7ad4460089239e1"
    groupId: "48c2f2d3191adf2d1d371d23d2219e228268ffbcfa4ba7dfe67a5855c81e6f13"
    kind: "videoinput"
    label: "默认 - 摄像头"
}
复制代码

MediaStreamTrack

上面我们获得了 MediaStream 对象,通过它我们可以拿到音频/视频的 MediaStreamTrack

const videoTracks = stream.getVideoTracks();
const audioTracks = stream.getAudioTracks();
复制代码

可以看到, MediaStream 中的视频轨与音频轨分为了两个数组。

当然,我们也可以单独操作 MediaStreamTrack 对象:

videoTracks[0].stop();
复制代码

它还提供了如下属性和方法,便于我们操作单个轨道数据:

enabled: boolean;
    readonly id: string;
    readonly isolated: boolean;
    readonly kind: string;
    readonly label: string;
    readonly muted: boolean;
    onended: ((this: MediaStreamTrack, ev: Event) => any) | null;
    onisolationchange: ((this: MediaStreamTrack, ev: Event) => any) | null;
    onmute: ((this: MediaStreamTrack, ev: Event) => any) | null;
    onunmute: ((this: MediaStreamTrack, ev: Event) => any) | null;
    readonly readyState: MediaStreamTrackState;
    applyConstraints(constraints?: MediaTrackConstraints): Promise<void>;
    clone(): MediaStreamTrack;
    getCapabilities(): MediaTrackCapabilities;
    getConstraints(): MediaTrackConstraints;
    getSettings(): MediaTrackSettings;
    stop(): void;
    addEventListener<K extends keyof MediaStreamTrackEventMap>(type: K, listener: (this: MediaStreamTrack, ev: MediaStreamTrackEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
    removeEventListener<K extends keyof MediaStreamTrackEventMap>(type: K, listener: (this: MediaStreamTrack, ev: MediaStreamTrackEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
    removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
复制代码
我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章