本例子是参考webrtc-tutorial-simple-video-chat做的。 这个教程应该主要是去宣传ScaleDrone的sdk, 他们的服务是收费的,但是免费的也可以用,就是有些次数限制。

本栗子的地址 本栗子的pages地址

因为使用的是ScaleDrone的js sdk, 后期很可能服务不稳定之类的

1. 准备

  • 使用最新版谷歌浏览器(62版)
  • 视频聊天中 一个是windows, 一个是mac
  • stun服务器使用谷歌的,trun使用ScaleDrone的sdk,这样我就不用管服务端了。

2. 先上效果图

3. 再上在线例子点击此处

4. 源码分析

// 产生随机数
if (!location.hash) {
    location.hash = Math.floor(Math.random() * 0xFFFFFF).toString(16);
}
// 获取房间号
var roomHash = location.hash.substring(1);

// 放置你自己的频道id, 这是我注册了ScaleDrone 官网后,创建的channel
// 你也可以自己创建
var drone = new ScaleDrone('87fYv4ncOoa0Cjne');
// 房间名必须以 'observable-'开头
var roomName = 'observable-' + roomHash;
var configuration = {
    iceServers: [{
        urls: 'stun:stun.l.google.com:19302' // 使用谷歌的stun服务
    }]
};

var room;
var pc;
function onSuccess() {}

function onError(error) {
    console.error(error);
}

drone.on('open', function(error){
    if (error) { return console.error(error);}

    room = drone.subscribe(roomName);
    room.on('open', function(error){
        if (error) {onError(error);}
    });

    // 已经链接到房间后,就会收到一个 members 数组,代表房间里的成员
    // 这时候信令服务已经就绪
    room.on('members', function(members){
        console.log('MEMBERS', members);

        // 如果你是第二个链接到房间的人,就会创建offer
        var isOfferer = members.length === 2;
        startWebRTC(isOfferer);
    });
});

// 通过Scaledrone发送信令消息
function sendMessage(message) {
    drone.publish({
        room: roomName,
        message
    });
}

function startWebRTC(isOfferer) {
    pc = new RTCPeerConnection(configuration);

    // 当本地ICE Agent需要通过信号服务器发送信息到其他端时
    // 会触发icecandidate事件回调
    pc.onicecandidate = function(event){
        if (event.candidate) {
            sendMessage({ 'candidate': event.candidate });
        }
    };

    // 如果用户是第二个进入的人,就在negotiationneeded 事件后创建sdp
    if (isOfferer) {
        // onnegotiationneeded 在要求sesssion协商时发生
        pc.onnegotiationneeded = function() {
            // 创建本地sdp描述 SDP (Session Description Protocol) session描述协议
            pc.createOffer().then(localDescCreated).catch(onError);
        };
    }

    // 当远程数据流到达时,将数据流装载到video中
    pc.onaddstream = function(event){
        remoteVideo.srcObject = event.stream;
    };

    // 获取本地媒体流
    navigator.mediaDevices.getUserMedia({
        audio: true,
        video: true,
    }).then( function(stream) {
        // 将本地捕获的视频流装载到本地video中
        localVideo.srcObject = stream;

        // 将本地流加入RTCPeerConnection 实例中 发送到其他端
        pc.addStream(stream);
    }, onError);

    // 从Scaledrone监听信令数据
    room.on('data', function(message, client){
        // 消息是我自己发送的,则不处理
        if (client.id === drone.clientId) {
            return;
        }

        if (message.sdp) {
            // 设置远程sdp, 在offer 或者 answer后
            pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function(){
                // 当收到offer 后就接听
                if (pc.remoteDescription.type === 'offer') {
                    pc.createAnswer().then(localDescCreated).catch(onError);
                }
            }, onError);
        }
        else if (message.candidate) {
            // 增加新的 ICE canidatet 到本地的链接中
            pc.addIceCandidate(
                new RTCIceCandidate(message.candidate), onSuccess, onError
            );
        }
    });
}

function localDescCreated(desc) {
    pc.setLocalDescription(desc, function(){
        sendMessage({ 'sdp': pc.localDescription });
    },onError);
}

5. WebRTC简介

5.1. 介绍

WebRTC 是一个开源项目,用于Web浏览器之间进行实时音频视频通讯,数据传递。 WebRTC有几个JavaScript APIS。 点击链接去查看demo。

5.2. 在哪里使用WebRTC?

  • Chrome
  • FireFox
  • Opera
  • Android
  • iOS

5.3. 什么是信令

WebRTC使用RTCPeerConnection在浏览器之间传递流数据, 但是也需要一种机制去协调收发控制信息,这就是信令。信令的方法和协议并不是在WebRTC中明文规定的。 在codelad中用的是Node,也有许多其他的方法。

5.4. 什么是STUN和TURN和ICE?

STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序)是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的Internet端端口。这些信息被用来在两个同时处于NAT路由器之后的主机之间创建UDP通信。该协议由RFC 5389定义。 wikipedia STUN

TURN(全名Traversal Using Relay NAT, NAT中继穿透),是一种资料传输协议(data-transfer protocol)。允许在TCP或UDP的连线上跨越NAT或防火墙。 TURN是一个client-server协议。TURN的NAT穿透方法与STUN类似,都是通过取得应用层中的公有地址达到NAT穿透。但实现TURN client的终端必须在通讯开始前与TURN server进行交互,并要求TURN server产生"relay port",也就是relayed-transport-address。这时TURN server会建立peer,即远端端点(remote endpoints),开始进行中继(relay)的动作,TURN client利用relay port将资料传送至peer,再由peer转传到另一方的TURN client。wikipedia TURN

ICE (Interactive Connectivity Establishment,互动式连接建立 ),一种综合性的NAT穿越的技术。 互动式连接建立是由IETF的MMUSIC工作组开发出来的一种framework,可整合各种NAT穿透技术,如STUN、TURN(Traversal Using Relay NAT,中继NAT实现的穿透)、RSIP(Realm Specific IP,特定域IP)等。该framework可以让SIP的客户端利用各种NAT穿透方式打穿远程的防火墙。[wikipedia ICE]

WebRTC被设计用于点对点之间工作,因此用户可以通过最直接的途径连接。然而,WebRTC的构建是为了应付现实中的网络: 客户端应用程序需要穿越NAT网关和防火墙,并且对等网络需要在直接连接失败的情况下进行回调。 作为这个过程的一部分,WebRTC api使用STUN服务器来获取计算机的IP地址,并将服务器作为中继服务器运行,以防止对等通信失败。(现实世界中的WebRTC更详细地解释了这一点。)

5.5. WebRTC是否安全?

WebRTC组件是强制要求加密的,并且它的JavaScript APIS只能在安全的域下使用(HTTPS 或者 localhost)。信令机制并没有被WebRTC标准定义,所以是否使用安全的协议就取决于你自己了。

6. WebRTC 参考资料