Android之WebRTC介紹


參考自:
Introduction to WebRTC on Android
Android之WebRTC介紹

WebRTC被譽為是web長期開源開發的一個新啟元,是近年來web開發的最重要創新。WebRTC允許Web開發者在其web應用中添加視頻聊天或者點對點數據傳輸,不需要復雜的代碼或者昂貴的配置。目前支持Chrome、Firefox和Opera,后續會支持更多的瀏覽器,它有能力達到數十億的設備。

然而,WebRTC一直被誤解為僅適合於瀏覽器。事實上,WebRTC最重要的一個特征是允許本地和web應用間的互操作,很少有人使用到這個特性。

本文將探討如何在自己的Android應用中植入WebRTC,使用 WebRTC Initiative 中提供的本地庫。這邊文章不會講解如何使用信號機制建立通話,而是重點探討Android與瀏覽器中實現的差異性和相似性。下文將講解Android中實現對應功能的一些接口。如果想要了解WebRTC的基礎知識,強烈推薦 Sam Dutton’s Getting started with WebRTC 。

項目中添加WebRTC

下面的講解基於Android WebRTC庫版本9127.

首先要做的是在應用中添加WebRTC庫。 WebRTC Initiative 提供了 一種簡潔的方式來編譯 ,但盡量不要采用那種方式。取而代之,建議使用原始的io編譯版本,可以從 maven central repository 中獲取。

添加WebRTC到工程中,需要在你的依賴中添加如下內容:

compile ‘io.pristine:libjingle:9127@aar’

同步工程后,WebRTC庫就准備就緒。

權限

同其他Android應用一樣,使用某些 API 需要申請相應權限。WebRTC也不例外。制作的應用不同,或者需要的功能不同,例如音頻或者視頻,所需要的權限集也是不同的。請確保按需申請!一個好的視頻聊天應用權限集如下:

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" />
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

燈光,攝影,工廠

在瀏覽器中使用WebRTC時,有一些功能完善、說明詳細的API可供使用。 navigator.getUserMedia 和 RTCPeerConnection 包含了可能用到的幾乎所有功能。結合 標簽使用,可以顯示任何想要顯示的本地視頻流和遠程視頻流。

所幸的是Android上也有相同的API,雖然它們的名字有所不同。Android相關的API有 VideoCapturerAndroid , VideoRenderer , MediaStream , PeerConnection , 和 PeerConnectionFactory 。下面我們將逐一講解。

在開始之前,需要創建PeerConnectionFactory,這是Android上使用WebRTC最核心的API。

PeerConnectionFactory

Android WebRTC最核心的類。理解這個類並了解它如何創建其他任何事情是深入了解Android中WebRTC的關鍵。它和我們期望的方式還是有所不同的,所以我們開始深入挖掘它。

首先需要初始化PeerConnectionFactory,如下:

// First, we initiate the PeerConnectionFactory with // our application context and some options. PeerConnectionFactory.initializeAndroidGlobals(     context,     initializeAudio,     initializeVideo,     videoCodecHwAcceleration,     renderEGLContext);
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

為了理解這個方法,需要了解每個參數的意義:

  • context:應用上下文,或者上下文相關的,和其他地方傳遞的一樣。
  • initializeAudio:是否初始化音頻的布爾值。
  • initializeVideo:是否初始化視頻的布爾值。跳過這兩個就允許跳過請求API的相關權限,例如數據通道應用。
  • videoCodecHwAcceleration:是否允許硬件加速的布爾值。
  • renderEGLContext:用來提供支持硬件視頻解碼,可以在視頻解碼線程中創建共享EGL上下文。可以為空——在本文例子中硬件視頻解碼將產生yuv420幀而非texture幀。
  • initializeAndroidGlobals也是返回布爾值,true表示一切OK,false表示有失敗。如果返回false是最好的練習。更多信息請參考 源碼 。

如果一切ok,可以使用PeerConnectionFactory 的構造函數創建自己的工廠,和其他類一樣。

PeerConnectionFactory peerConnectionFactory = new PeerConnectionFactory();
 
 
 
         
  • 1

行動、獲取媒體流、渲染

有了 peerConnectionFactory 實例,就可以從用戶設備獲取視頻和音頻,最終將其渲染到屏幕上。web中可以使用 getUserMedia 和 。在Android中,沒有這么簡單,但可以有更多選擇!在Android中,我們需要了解VideoCapturerAndroid,VideoSource,VideoTrack和VideoRenderer,先從VideoCapturerAndroid開始。

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);
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

有了包含攝像流信息的VideoCapturerAndroid實例,就可以創建從本地設備獲取到的包含視頻流信息的MediaStream,從而發送給另一端。但做這些之前,我們首先研究下如何將自己的視頻顯示到應用上面。

VideoSource/VideoTrack

從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);
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

AudioSource/AudioTrack

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);
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

VideoRenderer

通過在瀏覽器中使用WebRTC,你肯定已經熟悉了使用 標簽來顯示出從 getUserMedia 方法得到的 MediaStream。但在本地Android中,沒有類似 的標簽。進入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);
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

這里要說明的一點是createGui 需要四個參數。這樣做是使一個單一的GLSurfaceView 渲染所有視頻成為可能。但在實際使用中我們使用了多個GLSurfaceViews,這意味為了渲染正常,x、y一直是0。這讓我們了解到實現過程中各個參數的意義。

MediaConstraints

MediaConstraints是支持不同約束的WebRTC庫方式的類,可以加載到MediaStream中的音頻和視頻軌道。具體參考 規范 查看支持列表。對於大多數需要MediaConstraints的方法,一個簡單的MediaConstraints實例就可以做到。

MediaConstraints audioConstraints = new MediaConstraints();
 
 
 
         
  • 1

要添加實際約束,可以定義 KeyValuePairs ,並將其推送到約束的 mandatory 或者 optional list。

MediaStream

現在可以在本地看見自己了,接下來就要想辦法讓對方看見自己。在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);
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Hi,有人在那里嗎?

我們現在有了包含視頻流和音頻流的MediaStream實例,而且在屏幕上顯示了我們漂亮的臉龐。現在就該把這些信息傳送給對方了。這篇文章不會介紹如何建立自己的信號流,我們直接介紹對應的API方法,以及它們如何與web關聯的。 AppRTC 使用 autobahn 使得WebSocket連接到信號端。我建議下載下來這個項目來仔細研究下如何在Android中建立自己的信號流。

PeerConnection

現在我們有了自己的MediaStream,就可以開始連接遠端了。幸運的是這部分和web上的處理很相似,所以如果對瀏覽器中的WebRTC熟悉的話,這部分就相當簡單了。創建PeerConnection很簡單,只需要PeerConnectionFactory的協助即可。

1 PeerConnection peerConnection = peerConnectionFactory.createPeerConnection( 2 iceServers, 3 constraints, 4 observer);
 
 
 
         
  • 1
  • 2
  • 3
  • 4

參數的作用如下:

  • iceServers:連接到外部設備或者網絡時需要用到這個參數。在這里添加STUN 和 TURN 服務器就允許進行連接,即使在網絡條件很差的條件下。

  • constraints:MediaConstraints的一個實例,應該包含 offerToRecieveAudio 和 offerToRecieveVideo

  • observer:PeerConnectionObserver實現的一個實例。

PeerConnection 和web上的對應API很相似,包含了addStream、addIceCandidate、createOffer、createAnswer、getLocalDescription、setRemoteDescription 和其他類似方法。下載 WebRTC入門 來學習如何協調所有工作在兩點之間建立起通訊通道,或者 AppRTC 如何使得一個實時的功能完整的Android WebRTC應用工作的。我們快速瀏覽一下這幾個重要的方法,看它們是如何工作的。

addStream

這個是用來將MediaStream 添加到PeerConnection中的,如同它的命名一樣。如果你想要對方看到你的視頻、聽到你的聲音,就需要用到這個方法。

addIceCandidate

一旦內部IceFramework發現有candidates允許其他方連接你時,就會創建 IceCandidates 。當通過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開發理解這個不會很困難,或者學習 WebRTC入門 。這個接口必須被實現,以便你可以有效處理收到的事件,例如當對方變為可見時,向他們發送信號iceCandidates。


結束語

如上所述,如果你了解了如何與web相對應,Android上面的API是非常簡單易懂的。有了以上這些工具,我們就可以開發出一個WebRTC相關產品,立即部署到數十億設備上。

WebRTC打開了人與人之間的通訊,對開發者免費,對終端用戶免費。 它不僅僅提供了視頻聊天,還有其他應用,比如健康服務、低延遲文件傳輸、種子下載、甚至游戲應用。

想要看到一個真正的WebRTC應用實例,請下載 Android 或 ios 版的appear.in。它在瀏覽器和本地應用間運行的相當完美,在同一個房間內最多可以8個人免費使用。不需要安裝和注冊。

現在就發揮你們的潛力,開發出更多新的應用!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM