mobile CCTV,mobile surveillance,police body worn cameras

 forgetPW
 registerNow
search
view: 3441|reply: 1
打印 prevThread nextThread

WebRTC 实现Android点到点互连(含Demo)

[copyURL]

60

主题

1423

帖子

5887

积分

Moderator

Rank: 7Rank: 7Rank: 7

积分
5887
jumpTo
owner
poston 2017-11-3 09:38 | authorOnly 回帖奖励 |倒序浏览 |阅读模式
http://www.jianshu.com/p/2a760b56e3a9
背景简介WebRTC被誉为是web长期开源开发的一个新启元,是近年来web开发的最重要创新。WebRTC允许Web开发者在其web应用中添加视频聊天或者点对点数据传输,不需要复杂的代码或者昂贵的配置。目前支持Chrome、Firefox和Opera,后续会支持更多的浏览器,它有能力达到数十亿的设备。
然而,WebRTC一直被误解为仅适合于浏览器。事实上,WebRTC最重要的一个特征是允许本地和web应用间的互操作,很少有人使用到这个特性。
所以自然Android应用也可以植入WebRTC。好处是什么?简单来说就是你可以用很简洁的代码,在手机上实现点对点的视频聊天或者数据传输,点对点!点对点!点对点!重要的事情说三遍。
项目准备信令服务器代码:https://github.com/matthewYang92/WebRtcServer(代码改自ProjectRTC
  • 安装Node.js
  • 进入项目根目录,命令行:npm install
  • 命令行:node app.js
  • 打开浏览器输入127.0.0.1:3000,见到WebRtcServer标题,服务器ready
客户端代码:https://github.com/matthewYang92/WebRtcAndroidClient(代码参考AndroidRTC项目)
  • 下载后直接AndroidStudio打开
  • 将WebRtcClient.java类中的mSocketAddress变量改成你服务器的ip端口3000
  • 安装后启动App,如果服务器log显示-- xxxxx joined --证明客户端已连上服务器
  • 至少两个客户端连接到服务器之后,其中一端点击init开始连接
如果你已经成功跑通了Demo,那么恭喜你已经成功了一半,接下来我们分析下实现流程。
实现流程一、添加WebRTC库依赖compile 'org.webrtc:google-webrtc:1.0.+'
二、初始化核心类PeerConnectionFactory    PeerConnectionFactory.initialize(PeerConnectionFactory            .InitializationOptions            .builder(this)            .createInitializationOptions());三、创建PeerConnection对象        peerConnection = factory.createPeerConnection(                iceServers, //ICE服务器列表                constraints, //MediaConstraints                this); //Context四、建立P2P连接通道WebRTC是基于P2P的,但在端与端之间的连接通道还没建立起来之前,我们需要通过一个信令服务器为端与端之间传递信令建立通道。信令服务器要做的东西很简单,就是将一端的信息透传给另一端,步骤如下(以Demo为例):我们启动A端与B端,通过SocketIO连接到信令服务器,我们以A作为发送端,B为响应端。
信令交换
  • A向服务器发出init请求
  • 服务器将A的init请求转发给连接上服务器的其他端
  • B收到init请求后,调用peerConnection.createOffer()方法创建一个包含SDP的offer信令
  • offer信令创建成功后会调用SdpObserver监听中的onCreateSuccess()响应函数,在此处B通过peerConnection.setLocalDescription()方法将SDP赋予自己的PeerConnection对象,同时将offer信令发送给服务器
  • 服务器将offer信令转发给A端
  • A收到offer信令后,调用peerConnection.setRemoteDescription()方法将B发过来的SDP赋予自己的PeerConnection对象,并调用peerConnection.createAnswer()方法创建一个answer信令
  • answer信令创建成功后同样会调用SdpObserver监听中的onCreateSuccess()响应函数,在此处A同样通过peerConnection.setLocalDescription方法将SDP赋予自己的PeerConnection对象,同时将answer信令发送给服务器
  • 服务器将answer信令转发给B端
  • B收到A的answer信令后,利用peerConnection.setRemoteDescription()方法将A发过来的SDP赋予自己的PeerConnection对象
设置Candidate
  • PeerConnection.Observer监听会调用onIceCandidate()响应函数并提供IceCandidate对象。然后将IceCandidate对象组成candidate信令发送给服务器
  • 服务器将candidate信令转发给连接上服务器的其他端
  • 收到candidate信令后调用peerConnection.addIceCandidate()将IceCandidate赋予自己的PeerConnection对象
至此Peer-to-Peer的连接已经建立起来了
五、使用DataChannel收发信息
  • 初始化DataChannel对象
        /*    DataChannel.Init 可配参数说明:    ordered:是否保证顺序传输;    maxRetransmitTimeMs:重传允许的最长时间;    maxRetransmits:重传允许的最大次数;     */    DataChannel.Init init = new DataChannel.Init();    dataChannel = peerConnection.createDataChannel("dataChannel", init);
  • 在onDataChannel()回调中注册消息回调
        dataChannel.registerObserver(this);
  • 发送消息
        byte[] msg = message.getBytes();    DataChannel.Buffer buffer = new DataChannel.Buffer(            ByteBuffer.wrap(msg),            false);    dataChannel.send(buffer);
  • onMessage()回调收消息
        ByteBuffer data = buffer.data;    byte[] bytes = new byte[data.capacity()];    data.get(bytes);    String msg = new String(bytes);
六、关于ICE服务(以下内容引用自http://blog.csdn.net/youmingyu/article/details/53192714,博主的文章对我帮助良多,非常感谢)如果在局域网内,信令交换后就已经可以传递媒体流了,但如果双方不在同一个局域网,就需要进行NAT/防火墙穿透(我是在局域网下测试的,没有穿透,但还是把这方面内容介绍下)。
WebRTC使用ICE框架来保证穿透。ICE全名叫交互式连接建立(Interactive Connectivity Establishment),一种综合性的NAT/FW穿越技术,它是一种框架,可以整合各种NAT/FW穿越技术如STUN、TURN(Traversal Using Relay NAT 中继NAT实现的穿透)。ICE会先使用STUN,尝试建立一个基于UDP的连接,如果失败了,就会去TCP(先尝试HTTP,然后尝试HTTPS),如果依旧失败ICE就会使用一个中继的TURN服务器。使用STUN服务器穿透的结构如下:

image.png


我们可以使用Google的stun服务器:stun:stun.l.google.com:19302(Google嘛,翻墙你懂得,当然如果有精力可以自己搭建一个stun服务器),那么我们怎么把这个地址告诉WebRTC呢,还记得之前的iceServers吗,就是在创建PeerConnection对象的时候需要的参数,iceServers里面存放的就是进行穿透地址变换的服务器地址,添加方法如下(保险起见可以多添加几个服务器地址,如果有的话):
        iceServers.add(new PeerConnection.IceServer("stun:stun.l.google.com:19302"));参考官网
Android之WebRTC介绍



作者:matthew_Yang
链接:http://www.jianshu.com/p/2a760b56e3a9
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
reply

使用道具 report

60

主题

1423

帖子

5887

积分

Moderator

Rank: 7Rank: 7Rank: 7

积分
5887
sofa
 Owner| poston 2017-11-3 09:39 | authorOnly
背景
webRTC是Google在2010年收购GIP公司之后获得的一项技术。如下图所示,它提供了音视频的采集、处理(降噪,回声消除等)、编解码、传输等技术。

webRTC的目标是实现无需安装任何插件就可以通过浏览器进行P2P的实时音视频通话及文件传输,来看看Google的demo,是不是很酷?本文将带你分析webRTC的原理,并逐步编写一个简单的demo。

原理

如图,浏览器之间媒体流的传输是P2P的,但是这并不意味着webRTC不需要服务器支持。建立P2P视频连接需要的信息,如用来初始化通信的session信息,双方的ip、端口,视频分辨率,编解码格式等等,还是需要通过服务器来传输的。webRTC没有规定这些信息传输的机制,XHR、webSocket、Socket.io等都是可以的,因为Socket.io自带了房间的概念,便于双向视频的撮合,所以我在demo里选择了Socket.io。

当然,连接建立的过程不会这么简单。首先,提到P2P就绕不开NAT(Network Address Translation),webRTC使用ICE(Interactive Connectivity Establishment)框架,ICE是一种综合性的NAT穿越技术,它整合了STUN、TURN。当穿越网络时,ICE会先尝试STUN,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的Internet端端口从而建立UDP连接,如果失败了ICE就会再尝试TCP(先尝试HTTP,再尝试HTTPS),如果仍然失败就使用中继的TURN服务器。


再来看看建立连接过程中的具体步骤:

调用getUserMedia获取本地的MediaStreams;
从STUN获取自己的外网IP及端口,通过Signaling Server向对方发送Offer(SDP协议),并收到Answer;
同时webRTC会生成一些包含自己的内网、外网IP等信息的candidate,同样通过Signaling Server相互传输;
建立P2P连接,传输媒体信息。
API
getUserMedia: 获取本地视频、音频,可以传入constraints调整分辨率、帧率,返回一个promise;
RTCPeerConnection: 生成一个RTCPeerConnection实例,传输视频、音频流;
createOffer: 会话发起方生成SDP Offer,包含了本地媒体流信息;
setLocalDescription:在此方法被调用之前oncandidate事件不会被触发;
setRemoteDescription: 接收到offer或者answer之后调用;
addIceCandidate: 接收到icecandidate之后调用;
Steps
获取媒体流
var constraints = {
  audio: false,
  video: true
};

navigator.mediaDevices.getUserMedia(constraints)
.then(gotStream)
.catch(function(e) {
  alert('getUserMedia() error: ' + e.name);
});

function gotStream(stream) {
  localVideo.srcObeject = stream;
  localStream = stream;
}
getUserMedia存在兼容性问题,需要在项目中引用webRTC官方给出的adapter.js。constraints还可以配置video的分辨率、帧率、对移动端还可以选择前后摄像头:

var constraints = {
    video: {
        width: { min:640, ideal: 1280, max: 1920 },
        height: { min: 480 ideal: 720, max: 1080 },
        facingMode: 'user'     // 前置摄像头
    }
};
定义RTCPeerConnection
var serverConfig = {
'iceServers': [{
    'urls': 'stun:stun.l.google.com:19302'
  }]
};

function createPeerConnection() {
    var pc = new RTCPeerConnection(serverConfig);
    pc.onicecandidate = function(e) {
        if (e.candidate) {
            pc.addIceCandidate(e.candidate);
        }
    };
   
    // 添加对方的媒体流
    pc.onaddstream = function(e) {
        remoteVideo.srcObeject = e.stream;
        remoteStream = stream;
    };
}
由STUN、TURN配置生成对应的RTCPeerConnection实例,再定义相关的事件处理函数,如onicecandidate、onaddstream、onremovestream等。

创建连接
function start() {
  pc.addstream(localStream);

  if (isCaller) {
    pc.createOffer(function(sessionDescription) {
      pc.setLocalDescription(sessionDescription);
      send(sessionDescription);  // 根据不同的Signaling方式实现
    });

    if (receiveAnswer) {
      pc.setRemoteDescription(answer.sessionDescription);
    }
  } else {

    if (receiveOffer) {
      pc.setRemoteDescription(offer.sessionDescription);
    }

    pc.createAnswer(function(sessionDescription) {
      pc.setLocalDescription(sessionDescription);
      send(sessionDescription);
    });
  }
}
必须先getUserMedia后才能生成sessionDescription,并且只有在setLocalDescription后onicecandidate事件才会触发。上面代码中的只是为了说明大致流程,实际项目中结合socket.io的事件更容易实现。

中断会话
function stop() {
  pc.stop();
  pc = null;
}
关于socket.io有关的代码本文没有贴出,详情可参考socket.io的用法。

可行性
按照上面的步骤可以成功地搭建webRTC的小demo,但是能否将webRTC运用到实际项目中去呢?下面从浏览器兼容性和webRTC本身的性能两个方面去分析。

兼容性
IOS: 只有最新的ios11支持webRTC,且仅限safari浏览器,微信内置浏览器尚不支持getUserMedia,不支持DataChannel,视频编解码格式为H.264;
Android: 安卓4.4以上(不含4.4),经测试各大手机厂商自带浏览器均不支持getUserMedia,但微信内置浏览器可以正常运行,另外61版本以上的Chrome for Android也都支持;
PC: Chrome49以上,Firefox55以上,Edge支持,Safari只有11支持,IE不支持。
性能
诚然webRTC在回声消除,图像编解码等方面已经做得十分出色,但它在性能上的问题还是不可忽视的:

由于需要进行视频编解码,所以CPU占用率非常高,尤其是在移动设备上;
在移动设备上获取的视频分辨率有限,最高只能达到640 * 480;
带宽有限时,音视频质量较差,延时明显;
综上所述,虽然webRTC具有不需安装插件或者客户端,开源免费,强大的网络穿透能力,出色的音视频处理技术等等优点,但由于兼容性及性能上的问题,要投入到生产中还需要时间,主要是IOS11的普及以及CPU占用率和延时的问题。

参考文章
WebRTC in the real world: STUN, TURN and signaling
How to Select a Signaling Protocol for Your Next WebRTC Project?
Getting Started with WebRTC
使用WebRTC搭建前端视频聊天室——入门篇
reply agree Against

使用道具 report

creditRule

QQ|wireless surveillance

GMT+8, 2024-9-29 07:09 , Processed in 0.058596 second(s), 19 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

QuickReply backToTop BackToList