webrtc在安卓5.0以上取不到安卓打开摄像头权限限,有什么解决办法

webrtc(4)
过去的几个月中,越来越多的开发者希望获得如何连接WebRTC与IP摄像头的信息。解决这个问题通常需要大量对底层媒体协议细节的深入了解。此外,在创造“Demo”和实际产品之间的距离也很大。我们将在本文中介绍如何利用Kurento的媒体服务器来正确地实现它。
WebRTC Media Gateways for media interoperability
对于集成IP摄像头到WebRTC应用,首先需要实现媒体交互。这意味着摄像头提供的媒体流需要和WebRTC编解码器和浏览器支持的格式兼容。这也意味着将IP摄像头吐出的内容翻译成WebRTC浏览器支持的内容。为了实现这一点,通常需要一个被称为WebRTC 媒体网关的技术。为了理解这样一个网关的工作,来看以下几点:
Most IP cameras available in the market (excluding exotic ones) publish media through any of these mechanisms:
市面上大部分的IP摄像头(国外产品除外)通过以下几种机制来发布media:
RTSP/H.264: 这类型的摄像头通常用于安防场合。它们使用协议来建立一个媒体会话。换句话说,媒体传输时通过RTSP发生的信令基于plain(简单的)RTP。不同的摄像头厂商可能支持不同的RTP规格,但是就我看到的大部分摄像头而言,AVP是唯一可用的选项。在这些摄像头中,同样典型的,H.264是编解码器唯一的选项。
HTTP/MJPEG: 这类型摄像头使用HTTP流来signaling,传输,将一系列的JPEG图像编码为视频。这些摄像头的硬件相对更简单,只需要很少的资源来操作。这就是为什么他们被更多用在电池功耗或者在意负载的场合(如机器人,无人机等)。不足的是,它们的视频质量显著下降。
因此,为了实现WebRTC交互性,媒体网关要求执行如下图所示的媒体管理程序。网关首先要有可以说同一门语言(如RTSP/RTP或HTTP)的能力,其次是解码从摄像头收到的视频流(如H.264或MJPEG),然后重新将它编码成VP8格式(WebRTC最普遍的编码),最后使用WebRTC协议栈将其发送到WebRTC客户端。
图1:WebRTC媒体网关在RSTP/H.264-HTTP/MJPEG摄像头和WebRTC浏览器之间提供媒体交互性的通用方案。媒体信息(暗红线)需要恰当的协议和编解码器适配来将摄像头提供的格式转换成WebRTC客户端支持的格式。但是,这还不足以在真实的网络中工作,因为真实网络需要考虑浏览器提供的RTCP反馈来管理丢包和拥塞。这对于达到令人满意的QoE是非常重要的,因为不是所有的WebRTC网关都有能力对RTCP反馈提供恰当的终止语义。
Dealing with the network: making a production ready application.
媒体适配对于实现可工作的应用是不够的。你还需要管理真实网络是如何工作的。为了实现这一点,WebRTC协议栈使用规格,最后一个’F‘ 表示“Feedback”。这个Feedback组成了图1场景描绘的RTCP包,它包含了可能影响质量的网络条件的信息,从WebRTC客户端发往网关。
如上所述,大部分IP摄像头仅支持AVP(没有’F‘),这意味着网关不能传送反馈给摄像头(如发生在很多架构中的那样),但是需要完全控制它。用术语说就是,网关必须终结RTCP反馈。
这是非常重要的。你必须确信你使用的WebRTC网关是真实的,并且完全终结和为RTCP传输提供语义。当RTCP传输未被终结时,你能感受到的是毁灭性的QoS,基本上视频停滞了。
为了理解视频停滞的原因,让我们分析一下当网关没有终结两种简单的反馈RTCP包:PLI和REMB时发生了什么:
如果网关没有管理包的能力,一旦网络发生丢包时,视频就会停滞。这是由于VP8编码器的工作方式。 它可能不会在长时间周期内(通常是分钟)产生关键帧。Every time a PLI packet is not managed by the gateway by generating a new key frame,WebRTC客户端将不能解码直到一个新周期的关键帧抵达(重申,这可能需要几分钟)。一些网关使用一些技巧来处理这个问题:以很高频率(如每隔两秒钟)产生关键帧,但是这会显著降低VP8 编解码器的视频质量,因为关键帧消耗掉了更多的带宽。
如果网关不管理请求,并且不考虑任何的协商控制机制,网关将不会对VP8编码器要求降低比特率的拥塞控制命令做出响应。这意味着,一旦网关和WebRTC客户端之间的连接被堵塞,WebRTC浏览器将会被视频传输超负荷,相关的丢包也会发生,导致体验质量的进一步下降,然后视频停滞。
Doing it right with Kurento Media Server
Kurento媒体服务器工具箱可以灵活创造丰富的WebRTC媒体网关,编程语言可以使用Java或者JavaScript。对于Kurento媒体服务器的介绍,可以参见 。在Kurento实现WebRTC媒体服务器与IP摄像头的交互是简单且安全的。你只需要考虑三个方面:
Kurento 媒体服务器 PlayerEndpoint 支持从不同来源读取视频流,包括RTSP/RTP和HTTP/MJPEG。换句话说,PlayerEndpoint有能力管理对IP摄像头媒体的捕获。
Kurento 媒体服务器 WebRtcEndpoint 支持发布媒体流到WebRTC浏览器,提供对RTCP反馈的完全终结。这意味着,每次PLI包被收到时,WebRtcEndpoint 应该命令VP8编码器生成一个新的关键帧。这同时也意味着通过命令VP8编码器降低质量,来实现对REMB反馈和拥塞控制的响应。
Kurento 媒体服务器发挥“不可知媒体能力”,当两个不兼容的媒体元素互联时,所有适当的转换对开发者来说都是透明的。因此,连接PlayerEndpoint源到WebRtcEndpointsink,H.264/MJPEG到VP8的转码就会被执行。
图2:Kurento媒体服务器实现了一个WebRTC网关,可以支持RTSP/H.264和HTTP/MJPEG。仅仅几行代码实例化PlayerEndpoint和WebRtcEndpoint元素,然后将它们连接,就可以创建一个网关。Kurento媒体服务器的内部逻辑负责执行必要的编解码适配,以及RTCP反馈的管理,而不需要开发者去关注。
因此,如图2所示,创建WebRTC媒体网关来实现RTSP/H.264,HTTP/MJPEG摄像头与WebRTC的交互是简单的。实现这部分逻辑的JavaScript源代码如下:
var pipeline = ...//Use Kurento Client API for obtaining your pipeline.
//Create the PlayerEndpoint for receiving from the IP camera. HTTP and RTSP uris are supportd
pipeline.create("PlayerEndpoint", {uri: "rtsp://your.rtsp.address"}, function(error, playerEndpoint){
//Create the WebRtcEndpoint
pipeline.create("WebRtcEndpoint", function(error, webRtcEndpoint){
//If working with trickle ice, some code for candidate management is required here.
//Connect playerEndpoint to webRtcEndpoint. This connection activates the agnostic media
//capability and the appropriate transcodings are configured and activated.
playerEndpoint.connect(webRtcEndpoint, function(error){
//Media starts flowing ... enjoy
player.play(function(error){
如果你需要JavaScript的完整可用例程,可以访问 .
所有这些的亮点是向你的网关添加更多的能力,如视频记录甚至是内容分析,它们仍然是非常简单的,你只需要实例化相应的媒体元素并将它们连接到期望的媒体拓扑。这便是使用Kurento的优势:模块化。
你是否有使用Kurento实现WebRTC和IP摄像头交互的经验?欢迎分享给我们。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1895次
排名:千里之外HTML5利用WebRTC的getUserMedia获取摄像头信息模拟拍照及视频(完整示例)
我的图书馆
HTML5利用WebRTC的getUserMedia获取摄像头信息模拟拍照及视频(完整示例)
最近公司做的app涉及摄像头,由于我们使用HTML5开发app,自然了解到getUserMedia接口。
关键是使用的问题,所以直接贴代码(通过互联网搜集资料整理)。
&!DOCTYPE&html&&&&html&xmlns="http://www.w3.org/1999/xhtml"&&&&head&&&&&&&&title&HTML5&GetUserMedia&Demo&/title&&&&&&&&meta&name="viewport"&content="width=device-width,&initial-scale=1.0,&maximum-scale=1.0"&/&&&&/head&&&&body&&&&&&&&input&type="button"&title="开启摄像头"&value="开启摄像头"&onclick="getMedia();"&/&&br&/&&&&&&&&video&height="120px"&autoplay="autoplay"&&/video&&hr&/&&&&&&&&input&type="button"&title="拍照"&value="拍照"&onclick="getPhoto();"&/&&br&/&&&&&&&&canvas&id="canvas1"&height="120px"&&&/canvas&&hr&/&&&&&&&&input&type="button"&title="视频"&value="视频"&onclick="getVedio();"&/&&br&/&&&&&&&&canvas&id="canvas2"&height="120px"&&/canvas&&&&&&&&&&script&type="text/javascript"&&&&&&&&&&&var&video&=&document.querySelector('video');&&&&&&&&&&var&audio,&audioT&&&&&&&&&&&&var&canvas1&=&document.getElementById('canvas1');&&&&&&&&&&var&context1&=&canvas1.getContext('2d');&&&&&&&&&&&&var&canvas2&=&document.getElementById('canvas2');&&&&&&&&&&var&context2&=&canvas2.getContext('2d');&&&&&&&&&&&&navigator.getUserMedia&=&navigator.getUserMedia&||&navigator.webkitGetUserMedia&||&navigator.mozGetUserMedia&||&navigator.msGetUserM&&&&&&&&&&window.URL&=&window.URL&||&window.webkitURL&||&window.mozURL&||&window.msURL;&&&&&&&&&&&&var&exArray&=&[];&//存储设备源ID&&&&&&&&&&MediaStreamTrack.getSources(function&(sourceInfos)&{&&&&&&&&&&&&&&for&(var&i&=&0;&i&!=&sourceInfos.&++i)&{&&&&&&&&&&&&&&&&&&var&sourceInfo&=&sourceInfos[i];&&&&&&&&&&&&&&&&&&//这里会遍历audio,video,所以要加以区分&&&&&&&&&&&&&&&&&&if&(sourceInfo.kind&===&'video')&{&&&&&&&&&&&&&&&&&&&&&&exArray.push(sourceInfo.id);&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&}&&&&&&&&&&});&&&&&&&&&&&&function&getMedia()&{&&&&&&&&&&&&&&if&(navigator.getUserMedia)&{&&&&&&&&&&&&&&&&&&navigator.getUserMedia({&&&&&&&&&&&&&&&&&&&&&&'video':&{&&&&&&&&&&&&&&&&&&&&&&&&&&'optional':&[{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'sourceId':&exArray[1]&//0为前置摄像头,1为后置&&&&&&&&&&&&&&&&&&&&&&&&&&}]&&&&&&&&&&&&&&&&&&&&&&},&&&&&&&&&&&&&&&&&&&&&&'audio':true&&&&&&&&&&&&&&&&&&},&successFunc,&errorFunc);&&&&//success是获取成功的回调函数&&&&&&&&&&&&&&}&&&&&&&&&&&&&&else&{&&&&&&&&&&&&&&&&&&alert('Native&device&media&streaming&(getUserMedia)&not&supported&in&this&browser.');&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&&&function&successFunc(stream)&{&&&&&&&&&&&&&&//alert('Succeed&to&get&media!');&&&&&&&&&&&&&&if&(video.mozSrcObject&!==&undefined)&{&&&&&&&&&&&&&&&&&&//Firefox中,video.mozSrcObject最初为null,而不是未定义的,我们可以靠这个来检测Firefox的支持&&&&&&&&&&&&&&&&&&video.mozSrcObject&=&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&else&{&&&&&&&&&&&&&&&&&&video.src&=&window.URL&&&&window.URL.createObjectURL(stream)&||&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&//video.play();&&&&&&&&&&&&&&&&//&音频&&&&&&&&&&&&&&audio&=&new&Audio();&&&&&&&&&&&&&&audioType&=&getAudioType(audio);&&&&&&&&&&&&&&if&(audioType)&{&&&&&&&&&&&&&&&&&&audio.src&=&'polaroid.'&+&audioT&&&&&&&&&&&&&&&&&&audio.play();&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&function&errorFunc(e)&{&&&&&&&&&&&&&&alert('Error!'+e);&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&//&将视频帧绘制到Canvas对象上,Canvas每60ms切换帧,形成肉眼视频效果&&&&&&&&&&function&drawVideoAtCanvas(video,context)&{&&&&&&&&&&&&&&window.setInterval(function&()&{&&&&&&&&&&&&&&&&&&context.drawImage(video,&0,&0,90,120);&&&&&&&&&&&&&&},&60);&&&&&&&&&&}&&&&&&&&&&&&//获取音频格式&&&&&&&&&&function&getAudioType(element)&{&&&&&&&&&&&&&&if&(element.canPlayType)&{&&&&&&&&&&&&&&&&&&if&(element.canPlayType('audio/mp4;&codecs="mp4a.40.5"')&!==&'')&{&&&&&&&&&&&&&&&&&&&&&&return&('aac');&&&&&&&&&&&&&&&&&&}&else&if&(element.canPlayType('audio/&codecs="vorbis"')&!==&'')&{&&&&&&&&&&&&&&&&&&&&&&return&("ogg");&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&}&&&&&&&&&&&&&&return&&&&&&&&&&&}&&&&&&&&&&&&//&vedio播放时触发,绘制vedio帧图像到canvas&&//&&&&&&&&video.addEventListener('play',&function&()&{&&//&&&&&&&&&&&&drawVideoAtCanvas(video,&context2);&&//&&&&&&&&},&false);&&&&&&&&&&&&//拍照&&&&&&&&&&function&getPhoto()&{&&&&&&&&&&&&&&context1.drawImage(video,&0,&0,90,120);&//将video对象内指定的区域捕捉绘制到画布上指定的区域,实现拍照。&&&&&&&&&&}&&&&&&&&&&&&//视频&&&&&&&&&&function&getVedio()&{&&&&&&&&&&&&&&drawVideoAtCanvas(video,&context2);&&&&&&&&&&}&&&&&&&&&/script&&&&/body&&&&/html&&&
在安卓的Chrome(版本Beta 39.0.2171.44)上测试的效果截图:
现在遇到一个问题:如何实现视频录制效果,也就是以视频文件保存到本地?
将Canvas获取的所有的帧图像组织起来,通过算法转换?
如果高见,望赐教!
TA的推荐TA的最新馆藏
喜欢该文的人也喜欢原文链接 :&
原文作者 :&
译文出自 :&
状态 :完成
WebRTC被誉为是web长期开源开发的一个新启元,是近年来web开发的最重要创新。WebRTC允许Web开发者在其web应用中添加视频聊天或者点对点数据传输,不需要复杂的代码或者昂贵的配置。目前支持Chrome、Firefox和Opera,后续会支持更多的浏览器,它有能力达到数十亿的设备。
然而,WebRTC一直被误解为仅适合于浏览器。事实上,WebRTC最重要的一个特征是允许本地和web应用间的互操作,很少有人使用到这个特性。
本文将探讨如何在自己的Android应用中植入WebRTC,使用&&中提供的本地库。这边文章不会讲解如何使用信号机制建立通话,而是重点探讨Android与浏览器中实现的差异性和相似性。下文将讲解Android中实现对应功能的一些接口。如果想要了解WebRTC的基础知识,强烈推荐&&。
项目中添加WebRTC
下面的讲解基于Android WebRTC库版本9127.
首先要做的是在应用中添加WebRTC库。 WebRTC Initiative 提供了&&,但尽量不要采用那种方式。取而代之,建议使用原始的io编译版本,可以从&&中获取。
添加WebRTC到工程中,需要在你的依赖中添加如下内容:
1 compile 'io.pristine:libjingle:9127@aar'
同步工程后,WebRTC库就准备就绪。
同其他Android应用一样,使用某些 API 需要申请相应权限。WebRTC也不例外。制作的应用不同,或者需要的功能不同,例如音频或者视频,所需要的权限集也是不同的。请确保按需申请!一个好的视频聊天应用权限集如下:
灯光,摄影,工厂
在浏览器中使用WebRTC时,有一些功能完善、说明详细的API可供使用。&和&&包含了可能用到的几乎所有功能。结合&&video&&标签使用,可以显示任何想要显示的本地视频流和远程视频流。
所幸的是Android上也有相同的API,虽然它们的名字有所不同。Android相关的API有&&,&&,&&,&&, 和&。下面我们将逐一讲解。
在开始之前,需要创建PeerConnectionFactory,这是Android上使用WebRTC最核心的API。
PeerConnectionFactory
Android WebRTC最核心的类。理解这个类并了解它如何创建其他任何事情是深入了解Android中WebRTC的关键。它和我们期望的方式还是有所不同的,所以我们开始深入挖掘它。
首先需要初始化PeerConnectionFactory,如下:
为了理解这个方法,需要了解每个参数的意义:
应用上下文,或者上下文相关的,和其他地方传递的一样。
initializeAudio
是否初始化音频的布尔值。
initializeVideo
是否初始化视频的布尔值。跳过这两个就允许跳过请求API的相关权限,例如数据通道应用。
videoCodecHwAcceleration
是否允许硬件加速的布尔值。
renderEGLContext
用来提供支持硬件视频解码,可以在视频解码线程中创建共享EGL上下文。可以为空&&在本文例子中硬件视频解码将产生yuv420帧而非texture帧。
initializeAndroidGlobals也是返回布尔值,true表示一切OK,false表示有失败。如果返回false是最好的练习。更多信息请参考&&。
如果一切ok,可以使用PeerConnectionFactory 的构造函数创建自己的工厂,和其他类一样。
1 PeerConnectionFactory peerConnectionFactory = new PeerConnectionFactory();
行动、获取媒体流、渲染
有了&peerConnectionFactory&实例,就可以从用户设备获取视频和音频,最终将其渲染到屏幕上。web中可以使用&getUserMedia&和&&video&&。在Android中,没有这么简单,但可以有更多选择!在Android中,我们需要了解VideoCapturerAndroid,VideoSource,VideoTrack和VideoRenderer,先从VideoCapturerAndroid开始。
VideoCapturerAndroid
VideoCapturerAndroid其实是一系列Camera API的封装,为访问摄像头设备的流信息提供了方便。它允许获取多个摄像头设备信息,包括前置摄像头,或者后置摄像头。
有了包含摄像流信息的VideoCapturerAndroid实例,就可以创建从本地设备获取到的包含视频流信息的MediaStream,从而发送给另一端。但做这些之前,我们首先研究下如何将自己的视频显示到应用上面。
VideoSource/VideoTrack
从VideoCapturer实例中获取一些有用信息,或者要达到最终目标&&&&为连接端获取合适的媒体流,或者仅仅是将它渲染给用户,我们需要了解VideoSource 和 VideoTrack类。
&允许方法开启、停止设备捕获视频。这在为了延长电池寿命而禁止视频捕获的情况下比较有用。
&是简单的添加VideoSource到MediaStream 对象的一个封装。
我们通过代码看看它们是如何一起工作的。&capturer&是VideoCapturer的实例,videoConstraints&是MediaConstraints的实例。
// First we create a VideoSource
VideoSource videoSource =
peerConnectionFactory.createVideoSource(capturer, videoConstraints);
// Once we have that, we can create our VideoTrack
// Note that VIDEO_TRACK_ID can be any string that uniquely
// identifies that video track in your application
VideoTrack localVideoTrack =
peerConnectionFactory.createVideoTrack(VIDEO_TRACK_ID, videoSource);
AudioSource/AudioTrack
&和&&与VideoSource和VideoTrack相似,只是不需要AudioCapturer 来获取麦克风,&audioConstraints&是 MediaConstraints的一个实例。
// First we create an AudioSource
AudioSource audioSource =
peerConnectionFactory.createAudioSource(audioConstraints);
// Once we have that, we can create our AudioTrack
// Note that AUDIO_TRACK_ID can be any string that uniquely
// identifies that audio track in your application
AudioTrack localAudioTrack =
peerConnectionFactory.createAudioTrack(AUDIO_TRACK_ID, audioSource);
VideoRenderer
通过在浏览器中使用WebRTC,你肯定已经熟悉了使用&&Video&&标签来显示出从 getUserMedia 方法得到的 MediaStream。但在本地Android中,没有类似&&Video&的标签。进入VideoRenderer,WebRTC库允许通过&VideoRenderer.Callbacks&实现自己的渲染。另外,它提供了一种非常好的默认方式VideoRendererGui。简而言之,&&是一个&&,使用它可以绘制自己的视频流。我们通过代码看一下它是如何工作的,以及如何添加renderer 到 VideoTrack。
// To create our VideoRenderer, we can use the
// included VideoRendererGui for simplicity
// First we need to set the GLSurfaceView that it should render to
GLSurfaceView videoView = (GLSurfaceView) findViewById(R.id.glview_call);
// Then we set that view, and pass a Runnable
// to run once the surface is ready
VideoRendererGui.setView(videoView, runnable);
// Now that VideoRendererGui is ready, we can get our VideoRenderer
VideoRenderer renderer = VideoRendererGui.createGui(x, y, width, height);
// And finally, with our VideoRenderer ready, we
// can add our renderer to the VideoTrack.
localVideoTrack.addRenderer(renderer);
这里要说明的一点是createGui 需要四个参数。这样做是使一个单一的GLSurfaceView 渲染所有视频成为可能。但在实际使用中我们使用了多个GLSurfaceViews,这意味为了渲染正常,x、y一直是0。这让我们了解到实现过程中各个参数的意义。
MediaConstraints
MediaConstraints是支持不同约束的WebRTC库方式的类,可以加载到MediaStream中的音频和视频轨道。具体参考&&查看支持列表。对于大多数需要MediaConstraints的方法,一个简单的MediaConstraints实例就可以做到。
MediaConstraints audioConstraints = new MediaConstraints();
要添加实际约束,可以定义&KeyValuePairs&,并将其推送到约束的&mandatory或者&optional&list。
MediaStream
现在可以在本地看见自己了,接下来就要想办法让对方看见自己。在web开发时,对&&已经很熟悉了。&getUserMedia&直接返回MediaStream ,然后将其添加到RTCPeerConnection 传送给对方。在Android上此方法也是通用的,只是我们需要自己创建MediaStream。 接下来我们就研究如何添加本地的VideoTrack 和AudioTrack来创建一个合适的MediaStream。
// We start out with an empty MediaStream object,
// created with help from our PeerConnectionFactory
// Note that LOCAL_MEDIA_STREAM_ID can be any string
MediaStream mediaStream = peerConnectionFactory.createLocalMediaStream(LOCAL_MEDIA_STREAM_ID);
// Now we can add our tracks.
mediaStream.addTrack(localVideoTrack);
mediaStream.addTrack(localAudioTrack);
Hi,有人在那里吗?
我们现在有了包含视频流和音频流的MediaStream实例,而且在屏幕上显示了我们漂亮的脸庞。现在就该把这些信息传送给对方了。这篇文章不会介绍如何建立自己的信号流,我们直接介绍对应的API方法,以及它们如何与web关联的。&&使用&使得WebSocket连接到信号端。我建议下载下来这个项目来仔细研究下如何在Android中建立自己的信号流。
PeerConnection
现在我们有了自己的MediaStream,就可以开始连接远端了。幸运的是这部分和web上的处理很相似,所以如果对浏览器中的WebRTC熟悉的话,这部分就相当简单了。创建PeerConnection很简单,只需要PeerConnectionFactory的协助即可。
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(
iceServers,
constraints,
observer);
参数的作用如下:
iceServers
连接到外部设备或者网络时需要用到这个参数。在这里添加STUN 和 TURN 服务器就允许进行连接,即使在网络条件很差的条件下。
constraints
MediaConstraints的一个实例,应该包含&offerToRecieveAudio&和offerToRecieveVideo
PeerConnectionObserver实现的一个实例。
PeerConnection 和web上的对应API很相似,包含了addStream、addIceCandidate、createOffer、createAnswer、getLocalDescription、setRemoteDescription 和其他类似方法。下载&&来学习如何协调所有工作在两点之间建立起通讯通道,或者&&如何使得一个实时的功能完整的Android WebRTC应用工作的。我们快速浏览一下这几个重要的方法,看它们是如何工作的。
这个是用来将MediaStream 添加到PeerConnection中的,如同它的命名一样。如果你想要对方看到你的视频、听到你的声音,就需要用到这个方法。
addIceCandidate
一旦内部IceFramework发现有candidates允许其他方连接你时,就会创建&。当通过PeerConnectionObserver.onIceCandidate传递数据到对方时,需要通过任何一个你选择的信号通道获取到对方的IceCandidates。使用addIceCandidate 添加它们到PeerConnection,以便PeerConnection可以通过已有信息试图连接对方。
createOffer/createAnswer
这两个方法用于原始通话的建立。如你所知,在WebRTC中,已经有了caller和callee的概念,一个是呼叫,一个是应答。createOffer是caller使用的,它需要一个sdpObserver,它允许获取和传输会话描述协议Session Description Protocol (SDP)给对方,还需要一个MediaConstraint。一旦对方得到了这个请求,它将创建一个应答并将其传输给caller。SDP是用来给对方描述期望格式的数据(如video、formats、codecs、encryption、resolution、 size等)。一旦caller收到这个应答信息,双方就相互建立的通信需求达成了一致,如视频、音频、解码器等。
setLocalDescription/setRemoteDescription
这个是用来设置createOffer和createAnswer产生的SDP数据的,包含从远端获取到的数据。它允许内部PeerConnection 配置链接以便一旦开始传输音频和视频就可以开始真正工作。
PeerConnectionObserver
这个接口提供了一种监测PeerConnection事件的方法,例如收到MediaStream时,或者发现iceCandidates 时,或者需要重新建立通讯时。这些在功能上与web相对应,如果你学习过相关web开发理解这个不会很困难,或者学习&&。这个接口必须被实现,以便你可以有效处理收到的事件,例如当对方变为可见时,向他们发送信号iceCandidates。
如上所述,如果你了解了如何与web相对应,Android上面的API是非常简单易懂的。有了以上这些工具,我们就可以开发出一个WebRTC相关产品,立即部署到数十亿设备上。
WebRTC打开了人与人之间的通讯,对开发者免费,对终端用户免费。 它不仅仅提供了视频聊天,还有其他应用,比如健康服务、低延迟文件传输、种子下载、甚至游戏应用。
想要看到一个真正的WebRTC应用实例,请下载&&或&&版的appear.in。它在浏览器和本地应用间运行的相当完美,在同一个房间内最多可以8个人免费使用。不需要安装和注册。
阅读(...) 评论()

我要回帖

更多关于 安卓摄像头权限 的文章

 

随机推荐