WebRTC被譽爲是web長期開源開發的一個新啓元,是近年來web開發的最重要創新。WebRTC容許Web開發者在其web應用中添加視頻聊天或者點對點數據傳輸,不須要複雜的代碼或者昂貴的配置。目前支持Chrome、Firefox和Opera,後續會支持更多的瀏覽器,它有能力達到數十億的設備。html
然而,WebRTC一直被誤解爲僅適合於瀏覽器。事實上,WebRTC最重要的一個特徵是容許本地和web應用間的互操做,不多有人使用到這個特性。html5
本文將探討如何在本身的Android應用中植入WebRTC,使用 WebRTC Initiative 中提供的本地庫。這邊文章不會講解如何使用信號機制創建通話,而是重點探討Android與瀏覽器中實現的差別性和類似性。下文將講解Android中實現對應功能的一些接口。若是想要了解WebRTC的基礎知識,強烈推薦 Sam Dutton’s Getting started with WebRTC 。java
下面的講解基於Android WebRTC庫版本9127.android
首先要作的是在應用中添加WebRTC庫。 WebRTC Initiative 提供了 一種簡潔的方式來編譯 ,但儘可能不要採用那種方式。取而代之,建議使用原始的io編譯版本,能夠從 maven central repository 中獲取。ios
添加WebRTC到工程中,須要在你的依賴中添加以下內容:git
1 compile 'io.pristine:libjingle:9127@aar'
同步工程後,WebRTC庫就準備就緒。github
同其餘Android應用同樣,使用某些 API 須要申請相應權限。WebRTC也不例外。製做的應用不一樣,或者須要的功能不一樣,例如音頻或者視頻,所須要的權限集也是不一樣的。請確保按需申請!一個好的視頻聊天應用權限集以下:web
1 <uses-feature android:name="android.hardware.camera" /> 2 <uses-feature android:name="android.hardware.camera.autofocus" /> 3 <uses-feature android:glEsVersion="0x00020000" android:required="true" /> 4 5 <uses-permission android:name="android.permission.CAMERA" /> 6 <uses-permission android:name="android.permission.RECORD_AUDIO" /> 7 <uses-permission android:name="android.permission.INTERNET" /> 8 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 9 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
在瀏覽器中使用WebRTC時,有一些功能完善、說明詳細的API可供使用。navigator.getUserMedia 和 RTCPeerConnection 包含了可能用到的幾乎全部功能。結合 <video>
標籤使用,能夠顯示任何想要顯示的本地視頻流和遠程視頻流。sql
所幸的是Android上也有相同的API,雖然它們的名字有所不一樣。Android相關的API有 VideoCapturerAndroid , VideoRenderer , MediaStream , PeerConnection , 和PeerConnectionFactory 。下面咱們將逐一講解。瀏覽器
在開始以前,須要建立PeerConnectionFactory,這是Android上使用WebRTC最核心的API。
Android WebRTC最核心的類。理解這個類並瞭解它如何建立其餘任何事情是深刻了解Android中WebRTC的關鍵。它和咱們指望的方式仍是有所不一樣的,因此咱們開始深刻挖掘它。
首先須要初始化PeerConnectionFactory,以下:
// First, we initiate the PeerConnectionFactory with
// our application context and some options. PeerConnectionFactory.initializeAndroidGlobals( context, initializeAudio, initializeVideo, videoCodecHwAcceleration, renderEGLContext);
爲了理解這個方法,須要瞭解每一個參數的意義:
context
應用上下文,或者上下文相關的,和其餘地方傳遞的同樣。
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實際上是一系列Camera API的封裝,爲訪問攝像頭設備的流信息提供了方便。它容許獲取多個攝像頭設備信息,包括前置攝像頭,或者後置攝像頭。
1 // Returns the number of camera devices 2 VideoCapturerAndroid.getDeviceCount(); 3 4 // Returns the front face device name 5 VideoCapturerAndroid.getNameOfFrontFacingDevice(); 6 // Returns the back facing device name 7 VideoCapturerAndroid.getNameOfBackFacingDevice(); 8 9 // Creates a VideoCapturerAndroid instance for the device name 10 VideoCapturerAndroid.create(name);
有了包含攝像流信息的VideoCapturerAndroid實例,就能夠建立從本地設備獲取到的包含視頻流信息的MediaStream,從而發送給另外一端。但作這些以前,咱們首先研究下如何將本身的視頻顯示到應用上面。
從VideoCapturer實例中獲取一些有用信息,或者要達到最終目標————爲鏈接端獲取合適的媒體流,或者僅僅是將它渲染給用戶,咱們須要瞭解VideoSource 和 VideoTrack類。
VideoSource 容許方法開啓、中止設備捕獲視頻。這在爲了延長電池壽命而禁止視頻捕獲的狀況下比較有用。
VideoTrack 是簡單的添加VideoSource到MediaStream 對象的一個封裝。
咱們經過代碼看看它們是如何一塊兒工做的。 capturer
是VideoCapturer的實例,videoConstraints
是MediaConstraints的實例。
1 // First we create a VideoSource 2 VideoSource videoSource = 3 peerConnectionFactory.createVideoSource(capturer, videoConstraints); 4 5 // Once we have that, we can create our VideoTrack 6 // Note that VIDEO_TRACK_ID can be any string that uniquely 7 // identifies that video track in your application 8 VideoTrack localVideoTrack = 9 peerConnectionFactory.createVideoTrack(VIDEO_TRACK_ID, videoSource);
AudioSource 和 AudioTrack 與VideoSource和VideoTrack類似,只是不須要AudioCapturer 來獲取麥克風, audioConstraints
是 MediaConstraints的一個實例。
1 // First we create an AudioSource 2 AudioSource audioSource = 3 peerConnectionFactory.createAudioSource(audioConstraints); 4 5 // Once we have that, we can create our AudioTrack 6 // Note that AUDIO_TRACK_ID can be any string that uniquely 7 // identifies that audio track in your application 8 AudioTrack localAudioTrack = 9 peerConnectionFactory.createAudioTrack(AUDIO_TRACK_ID, audioSource);
經過在瀏覽器中使用WebRTC,你確定已經熟悉了使用 <Video>
標籤來顯示出從 getUserMedia 方法獲得的 MediaStream。但在本地Android中,沒有相似 <Video>
的標籤。進入VideoRenderer,WebRTC庫容許經過 VideoRenderer.Callbacks
實現本身的渲染。另外,它提供了一種很是好的默認方式VideoRendererGui。簡而言之, VideoRendererGui 是一個 GLSurfaceView ,使用它能夠繪製本身的視頻流。咱們經過代碼看一下它是如何工做的,以及如何添加renderer 到 VideoTrack。
1 // To create our VideoRenderer, we can use the 2 // included VideoRendererGui for simplicity 3 // First we need to set the GLSurfaceView that it should render to 4 GLSurfaceView videoView = (GLSurfaceView) findViewById(R.id.glview_call); 5 6 // Then we set that view, and pass a Runnable 7 // to run once the surface is ready 8 VideoRendererGui.setView(videoView, runnable); 9 10 // Now that VideoRendererGui is ready, we can get our VideoRenderer 11 VideoRenderer renderer = VideoRendererGui.createGui(x, y, width, height); 12 13 // And finally, with our VideoRenderer ready, we 14 // can add our renderer to the VideoTrack. 15 localVideoTrack.addRenderer(renderer);
這裏要說明的一點是createGui 須要四個參數。這樣作是使一個單一的GLSurfaceView 渲染全部視頻成爲可能。但在實際使用中咱們使用了多個GLSurfaceViews,這意味爲了渲染正常,x、y一直是0。這讓咱們瞭解到實現過程當中各個參數的意義。
MediaConstraints是支持不一樣約束的WebRTC庫方式的類,能夠加載到MediaStream中的音頻和視頻軌道。具體參考 規範 查看支持列表。對於大多數須要MediaConstraints的方法,一個簡單的MediaConstraints實例就能夠作到。
1 MediaConstraints audioConstraints = new MediaConstraints();
要添加實際約束,能夠定義 KeyValuePairs
,並將其推送到約束的 mandatory
或者 optional
list。
如今能夠在本地看見本身了,接下來就要想辦法讓對方看見本身。在web開發時,對 MediaStream 已經很熟悉了。 getUserMedia
直接返回MediaStream ,而後將其添加到RTCPeerConnection 傳送給對方。在Android上此方法也是通用的,只是咱們須要本身建立MediaStream。 接下來咱們就研究如何添加本地的VideoTrack 和AudioTrack來建立一個合適的MediaStream。
1 // We start out with an empty MediaStream object, 2 // created with help from our PeerConnectionFactory 3 // Note that LOCAL_MEDIA_STREAM_ID can be any string 4 MediaStream mediaStream = peerConnectionFactory.createLocalMediaStream(LOCAL_MEDIA_STREAM_ID); 5 6 // Now we can add our tracks. 7 mediaStream.addTrack(localVideoTrack); 8 mediaStream.addTrack(localAudioTrack);
咱們如今有了包含視頻流和音頻流的MediaStream實例,並且在屏幕上顯示了咱們漂亮的臉龐。如今就該把這些信息傳送給對方了。這篇文章不會介紹如何創建本身的信號流,咱們直接介紹對應的API方法,以及它們如何與web關聯的。 AppRTC 使用autobahn 使得WebSocket鏈接到信號端。我建議下載下來這個項目來仔細研究下如何在Android中創建本身的信號流。
如今咱們有了本身的MediaStream,就能夠開始鏈接遠端了。幸運的是這部分和web上的處理很類似,因此若是對瀏覽器中的WebRTC熟悉的話,這部分就至關簡單了。建立PeerConnection很簡單,只須要PeerConnectionFactory的協助便可。
1 PeerConnection peerConnection = peerConnectionFactory.createPeerConnection( 2 iceServers, 3 constraints, 4 observer);
參數的做用以下:
iceServers
鏈接到外部設備或者網絡時須要用到這個參數。在這裏添加STUN 和 TURN 服務器就容許進行鏈接,即便在網絡條件不好的條件下。
constraints
MediaConstraints的一個實例,應該包含 offerToRecieveAudio
和offerToRecieveVideo
observer
PeerConnectionObserver實現的一個實例。
PeerConnection 和web上的對應API很類似,包含了addStream、addIceCandidate、createOffer、createAnswer、getLocalDescription、setRemoteDescription 和其餘相似方法。下載 WebRTC入門 來學習如何協調全部工做在兩點之間創建起通信通道,或者 AppRTC 如何使得一個實時的功能完整的Android WebRTC應用工做的。咱們快速瀏覽一下這幾個重要的方法,看它們是如何工做的。
這個是用來將MediaStream 添加到PeerConnection中的,如同它的命名同樣。若是你想要對方看到你的視頻、聽到你的聲音,就須要用到這個方法。
一旦內部IceFramework發現有candidates容許其餘方鏈接你時,就會建立IceCandidates 。當經過PeerConnectionObserver.onIceCandidate傳遞數據到對方時,須要經過任何一個你選擇的信號通道獲取到對方的IceCandidates。使用addIceCandidate 添加它們到PeerConnection,以便PeerConnection能夠經過已有信息試圖鏈接對方。
這兩個方法用於原始通話的創建。如你所知,在WebRTC中,已經有了caller和callee的概念,一個是呼叫,一個是應答。createOffer是caller使用的,它須要一個sdpObserver,它容許獲取和傳輸會話描述協議Session Description Protocol (SDP)給對方,還須要一個MediaConstraint。一旦對方獲得了這個請求,它將建立一個應答並將其傳輸給caller。SDP是用來給對方描述指望格式的數據(如video、formats、codecs、encryption、resolution、 size等)。一旦caller收到這個應答信息,雙方就相互創建的通訊需求達成了一致,如視頻、音頻、解碼器等。
這個是用來設置createOffer和createAnswer產生的SDP數據的,包含從遠端獲取到的數據。它容許內部PeerConnection 配置連接以便一旦開始傳輸音頻和視頻就能夠開始真正工做。
這個接口提供了一種監測PeerConnection事件的方法,例如收到MediaStream時,或者發現iceCandidates 時,或者須要從新創建通信時。這些在功能上與web相對應,若是你學習過相關web開發理解這個不會很困難,或者學習 WebRTC入門 。這個接口必須被實現,以便你能夠有效處理收到的事件,例如當對方變爲可見時,向他們發送信號iceCandidates。
如上所述,若是你瞭解瞭如何與web相對應,Android上面的API是很是簡單易懂的。有了以上這些工具,咱們就能夠開發出一個WebRTC相關產品,當即部署到數十億設備上。
WebRTC打開了人與人之間的通信,對開發者免費,對終端用戶免費。 它不只僅提供了視頻聊天,還有其餘應用,好比健康服務、低延遲文件傳輸、種子下載、甚至遊戲應用。
想要看到一個真正的WebRTC應用實例,請下載 Android 或 ios 版的appear.in。它在瀏覽器和本地應用間運行的至關完美,在同一個房間內最多能夠8我的無償使用。不須要安裝和註冊。