聲網 SDK 接入以及音視頻通話應用開發指南

1. 簡介

在現在的移動互聯網時代,音視頻相關應用已經深刻到咱們平常生活的方方面面。java

而在它背後的音視頻技術也是很是成熟了,短視頻編輯、帶貨直播、視頻語音通話等應用形式無不體現着音視頻技術給咱們生活帶來的便利。android

而此次就去實際體驗一下,接入聲網的音頻 SDK ,並打造一個音視頻通話應用。git

2. 帳戶註冊與項目建立

首先要作的就是在聲網(https://www.agora.io/cn)上註冊帳號,並完成實名認證。github

登陸以後就進到管理界面了,在左側有一系列選項能夠操做,直接進到項目管理,建立咱們的 VideoChat 項目。後端

在項目建立的安全模式上,選擇 APPID + Token 的方式。爲了提升項目的安全性,Agora 後續會取消對 APP ID 鑑權方案的支持。安全

當項目建立完成後就有了對應的 APP ID ,這個在後續代碼開發中會用到的。微信

除此以外,咱們還須要生成 Token ,在項目管理頁去生成一個臨時 Token 。網絡

這個臨時 Token 是有時效的,僅供測試使用,若是有本身的後端開發,到生產環境再去生成正式 Token。一樣,這個 Token 字符串在後續開發中也會用到的。架構

3. SDK 下載與集成

建立項目並準備好 APP ID 和 Token 以後,就能夠在官網上下載音頻 SDK 了。app

下載解壓後的內容如上所示。libs 文件夾內有對應不一樣 CPU 架構的 so 動態庫,還有動態庫對應的頭文件以及 Java 版本的 Jar 包,可分別進行 C++ 版本和 Java 版本的集成。

這裏就只用到 Java 版原本演示了,其實 Java 版本里面不少方法都是走到 native 調用了,而 native 調用的就是 so 動態庫裏面的方法。用 C++ 版本集成的話,還須要本身寫 JNI 代碼將 Java 與 C++ 鏈接起來,不如直接用 Java 版原本的快。

SDK 集成有兩種方式,一種是直接使用 JCenter 來集成,在 build.gradle 裏面添加一行代碼就行。

dependencies {
    implementation 'io.agora.rtc:full-sdk:3.1.3'
}

版本號能夠在官網上查詢,目前最新版本就是 3.1.3 了。

固然還能夠經過加載 jar 包和 so 動態庫的方式進行集成,把 agora-rtc-sdk.jar 和各版本 so 拷貝到對應目錄下,以下圖所示:

另外別忘了在 app 目錄下的 build.gradle 中添加以下代碼:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

少了這行代碼,可解析不到添加的 jar 包。

以上,就完成了整個 SDK 的工程接入,接下來就是代碼開發環節了。

4. 應用開發

咱們要開發的是一款音視頻通話應用,就像微信視頻同樣,想一想會有哪些內容。

首先要經過 Camera 採集咱們的畫面,而後經過麥克風錄製咱們的聲音,再經過網絡傳輸給到對方,而且可以聽到對方的聲音,在屏幕上顯示畫面。

想想這些內容要是純 Android 開發的話,那涉及的東西可多了,四五我的都不必定能 hold 住,而使用專業的音視頻 SDK ,一我的就能搞定大部分工做了。

接下來就要去完成這樣的開發工做,具體代碼能夠在 Github 上獲取:

https://github.com/glumes/ago...

4.1 權限申請

首先是權限申請,涉及到 Camera、網絡、存儲、錄製等等內容,在官網上也有給出具體權限列表,以下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="io.agora.tutorials1v1acall">

   <uses-permission android:name="android.permission.READ_PHONE_STATE" />   
   <uses-permission android:name="android.permission.INTERNET" />
   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   <uses-permission android:name="android.permission.CAMERA" />
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
   <uses-permission android:name="android.permission.BLUETOOTH" />
   <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   // 若是你的場景中涉及讀取外部存儲,需添加以下權限:
   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
   // 若是你使用的是 Android 10.0 及以上設備,還須要添加以下權限:
   <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
...
</manifest>

具體代碼可見 Github :

https://github.com/glumes/agora-sdk-demo/blob/main/app/src/main/java/com/glumes/videochat/MainActivity.kt

4.2 引擎建立

接下來就是建立 RtcEngine ,SDK 的不少方法都是經過 RtcEngine 來調用的。

// 聲明 RtcEngine 
private RtcEngine mRtcEngine;
// 建立 RtcEngine
private void initializeEngine() {
    try {
        mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
    } catch (Exception e) {
        Log.e(TAG, Log.getStackTraceString(e));
        throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
    }
}

在建立 RtcEngine 的時候須要用到 APP ID ,前面已經提過,在建立項目時就已經有了。

最後一個參數是 mRtcEventHandler ,它是一個 IRtcEngineEventHandler 類型的抽象類,類裏面定義了不少方法,去響應 RtcEngine 不一樣狀態的回調,好比鏈接成功,鏈接失敗、加入頻道、離開頻道、網絡狀態改變等等。若是有須要對應用的性能作一些監視,那麼就能夠在 IRtcEngineEventHandler 的回調方法作相關統計和埋點。

4.3 實現 Camera 畫面預覽

RtcEngine 把 Camera 相關操做都封裝在 SDK 內了,經過幾行代碼就能實現 Camera 畫面預覽。

4.3.1 建立 Camera 畫面預覽控件 View

首先要有一個控件去承接顯示 Camera 的畫面輸出內容,能夠用 SurfaceView 也能夠用 TextureView ,但並不須要咱們去建立控件,而是用 Agora SDK 提供的方法。

// 使用 SurfaceView 的場景
SurfaceView mLocalView = RtcEngine.CreateRendererView(getBaseContext());
// 使用 TextureView 的場景
TextureView mLocalView = RtcEngine.CreateTextureView(getBaseContext());

TextureView 是 Agora SDK 在 3.1.0 版本才提供的,它與 SurfaceView 的區別在於 TextureView 能夠對畫面進行縮放、旋轉和平移,而 SurfaceView 更適合在視頻通話和直播場景使用。

有了顯示的 View 以後,要把它添加到當前 Activity 的控件樹上,後面 Camera 畫面就會輸出到這裏。

4.3.2 配置 Camera 輸出並開啓預覽

接下來就是讓 Camera 輸出畫面了,可實際上不用寫一行關於 Camera 的代碼,三行代碼就能夠搞定。

// 開啓視頻
mRtcEngine.enableVideo();
// 初始化本地視圖
mRtcEngine.setupLocalVideo(new VideoCanvas(mLocalView, VideoCanvas.RENDER_MODE_HIDDEN, 0));
// 開啓預覽
mRtcEngine.startPreview();

經過以上代碼就能在屏幕上顯示咱們的畫面了,默認是前置攝像頭的內容。

具體代碼可見 Github :

https://github.com/glumes/agora-sdk-demo/blob/main/app/src/main/java/com/glumes/videochat/CameraPreviewActivity.kt

在代碼開發中,首先要啓用視頻模塊,默認是關閉的,經過 disableVideo 也能夠關閉。而音頻模塊默認就是開啓的,也能夠經過 enableAudio 和 disableAudio 來開啓關閉音頻模塊。

以後就是經過 setupLocalVideo 方法來初始化本地視圖,主要是設置本地用戶視頻信息的,也就是咱們的畫面要在 SurfaceView 中如何顯示,配置信息都是經過 VideoCanvas 類下發的,它有多種參數類型。

// VideoCanvas 構造函數類型
VideoCanvas (View view)
VideoCanvas (View view, int renderMode, int uid)
VideoCanvas (View view, int renderMode, String channelId, int uid)
VideoCanvas (View view, int renderMode, int uid, int mirrorMode)
VideoCanvas (View view, int renderMode, String channelId, int uid, int mirrorMode)

其中 renderMode 就是指定咱們的畫面在 SurfaceView 如何顯示,有以下類型:

  • RENDER_MODE_HIDDEN

    • 優先保證視窗被填滿。視頻尺寸等比縮放,直至整個視窗被視頻填滿。若是視頻長寬與顯示窗口不一樣,多出的視頻將被截掉。
  • RENDER_MODE_FIT

    • 優先保證視頻內容所有顯示。視頻尺寸等比縮放,直至視頻窗口的一邊與視窗邊框對齊。若是視頻長寬與顯示窗口不一樣,視窗上未被填滿的區域將被塗黑
  • RENDER_MODE_FILL

    • 視頻尺寸進行縮放和拉伸以充滿顯示視窗

默認狀況下都是使用 RENDER_MODE_HIDDEN 模式的。另外還有 mirrorMode 這樣的屬性來設置是否要畫面鏡像。

完成了畫面顯示配置以後,直接調用 startPreview 就能在屏幕上看到畫面啦,是否是很簡單!

4.3.3 Camera 更多的配置操做

簡單的背後實際上是 Agora SDK 作了不少封裝工做,好比 Camera1 和 Camera2 的調用邏輯、Camera 輸出的分辨率策略、先後攝像頭選擇等等。

咱們能夠在開啓預覽前經過 setCameraCapturerConfiguration 方法來配置本身想要的 Camera 信息。

// 配置 Camera 信息
mRtcEngine.setCameraCapturerConfiguration(new CameraCapturerConfiguration(CAPTURER_OUTPUT_PREFERENCE_AUTO,CAMERA_FRONT));

Camera 參數信息主要是在 CameraCapturerConfiguration 類中,它的兩個參數都是枚舉類型,其中第二個參數指定了使用前置仍是後置攝像頭。

第一個參數就是關於 Camera 輸出分辨率的一些策略,Agora SDK 並無給出接口讓咱們指定 Camera 輸出寬是多少,長是多少,並且根據使用場景組合了三個策略,更方面咱們去調用了。

  • CAPTURER_OUTPUT_PREFERENCE_AUTO

    • (默認)自動調整採集參數。
  • CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE

    • 優先保證設備性能。
  • CAPTURER_OUTPUT_PREFERENCE_PREVIEW

    • 優先保證視頻預覽質量。

經過以上操做,就完成了 Camera 畫面預覽顯示。

4.4 加入通話頻道

接下來就要去加入一個頻道,並和同一頻道內的朋友進行通訊。

// 函數原型
joinChannel    (    String     token,String channelName,String optionalInfo,int optionalUid) 

// 具體調用
private void joinChannel() {
    // 獲得 Token
    String token = getString(R.string.agora_access_token);
    // Token 和 頻道名要匹配
    mRtcEngine.joinChannel(token, "demoChannel1", "", 0);
}

經過 joinChannel 方法加入,其中 token 就是咱們以前建立好的,而頻道名稱也是建立 token 時指定的,這二者要匹配起來。optionalInfo 是可選的字符串。optionalUid 是用戶 ID,也是可選項,若是不指定(設爲 0),SDK 會自動分配一個,並在 onJoinChannelSuccess 回調方法中返回。

當咱們加入頻道成功後,會回調 IRtcEngineEventHandler 中的 onJoinChannelSuccess 方法。

經過 leaveChannel 方法,咱們能夠離開當前頻道,一樣會回調 IRtcEngineEventHandler 中的 onLeaveChannel 方法。

4.5 音視頻數據編碼格式參數設置

加入頻道後,咱們就要和頻道內的朋友們通訊。要把咱們的畫面和聲音發送給對方,那確定要將數據進行編碼,而後通過網絡傳輸送給對方。

注意:音頻和視頻的參數都必定要在加入頻道前設定好,也就是 joinChannel 方法調用以前,在其以後調用是不生效的。

4.5.1 視頻編碼參數設置

這裏咱們要指定視頻編碼的分辨率、幀率、碼率、視頻等信息,經過 setVideoEncoderConfiguration 方法。

mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
        // 視頻分辨率
       VideoEncoderConfiguration.VD_640x360,
        // 幀率
       VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
        // 碼率
       VideoEncoderConfiguration.STANDARD_BITRATE,
        // 視頻方向
       VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT));

在更早的 Agora SDK 版本中是經過 setVideoProfile 來設定的,還能夠指定具體的寬高、幀率數值。

最新版本換成了 VideoEncoderConfiguration 來配置,而且配置的參數是都已經定義好了相關的常量,不用本身寫 720、1280 這樣的 Magic Number 了。

參數的設置並非一成不變的,由於網絡或者性能等因素會有一些波動,但仍是會取最接近咱們設定的值。

4.5.2 音頻編碼參數設置

而音頻相關的參數,則是經過 setAudioProfile 方法來設置。

mRtcEngine.setAudioProfile(
        // 設置音頻採樣率、碼率、編碼模式和聲道數
        Constants.AudioProfile.DEFAULT.ordinal(),
        // 設置音頻的應用場景
        Constants.AudioScenario.DEFAULT.ordinal());

音頻咱們能夠設置採樣率、碼率、編碼模式以及聲道數。和視頻參數設置同樣,咱們不用指定具體的數值,Agora SDK 都根據業務使用場景作了封裝,根據須要來設置就好啦。

音頻 AudioProfile 有以下的配置:

  • DEFAULT

    • 通訊場景下,該選項表明指定 32 kHz 採樣率,語音編碼,單聲道,編碼碼率最大值爲 18 Kbps。
    • 直播場景下,該選項表明指定 48 kHz 採樣率,音樂編碼,單聲道,編碼碼率最大值爲 64 Kbps。
  • SPEECH_STANDARD

    • 指定 32 kHz 採樣率,語音編碼, 單聲道,編碼碼率最大值爲 18 Kbps。
  • MUSIC_STANDARD_STEREO

    • 指定 48 kHz 採樣率,音樂編碼, 單聲道,編碼碼率最大值爲 64 Kbps。
  • MUSIC_HIGH_QUALITY

    • 指定 48 kHz 採樣率,音樂編碼, 單聲道,編碼碼率最大值爲 96 Kbps。
  • MUSIC_HIGH_QUALITY_STEREO

    • 指定 48 kHz 採樣率,音樂編碼, 雙聲道,編碼碼率最大值爲 128 Kbps。

音頻的應用場景也有以下:

  • DEFAULT

    • 默認的音頻應用場景
  • CHATROOM_ENTERTAINMENT

    • 娛樂應用,須要頻繁上下麥的場景
  • EDUCATION

    • 教育應用,流暢度和穩定性優先
  • GAME_STREAMING

    • 高音質語聊房應用
  • SHOWROOM

    • 秀場應用,音質優先和更好的專業外設支持
  • CHATROOM_GAMING

    • 遊戲開黑

通常來講,咱們使用默認的配置 DEFAULT 就行了。

4.6 用戶加入並顯示對方畫面

當設置好了本身的數據編碼參數,而且也成功加入了頻道,接下來就是去接收頻道內其餘人的畫面和信息了。

具體代碼可見 Github:

https://github.com/glumes/agora-sdk-demo/blob/main/app/src/main/java/com/glumes/videochat/VideoChatActivity.kt

4.6.1 判斷是否有用戶加入頻道

當 IRtcEngineEventHandler 中的 onUserJoined 方法回調時,表明有人加入了當前頻道,此時就能夠創建並初始化遠端用戶視圖了。

若是啓用了視頻錄製功能,視頻錄製服務也會回調 onUserJoined 方法,至關於有個機器人加入該頻道,此時要區分開來,不能爲機器人創建遠端視頻,而後它不會發送視頻流的,創建了也是黑屏的。

爲了不機器人加入帶來的誤判,在 2.9.0 版本後更建議在 onRemoteVideoStateChanged 方法回調中去創建遠端用戶視圖。

onRemoteVideoStateChanged 方法顧名思義就是當遠端用戶狀態發生改變時就會調用,其中定義了以下幾個狀態:

  • REMOTE_VIDEO_STATE_STARTING

    • 本地用戶已接收遠端視頻首包
  • REMOTE_VIDEO_STATE_DECODING

    • 遠端視頻流正在解碼,正常播放
  • REMOTE_VIDEO_STATE_STOPPED

    • 遠端視頻默認初始狀態
  • REMOTE_VIDEO_STATE_FROZEN

    • 遠端視頻流卡頓
  • REMOTE_VIDEO_STATE_FAILED

    • 遠端視頻流播放失敗

當狀態是 REMOTE_VIDEO_STATE_STARTING 或者 REMOTE_VIDEO_STATE_DECODING 時,咱們認定有朋友加入頻道了,此時創建遠端用戶視圖。

@Override
public void onRemoteVideoStateChanged(final int uid, int state, int reason, int elapsed) {
      if (state == Constants.REMOTE_VIDEO_STATE_STARTING){
           runOnUiThread(new Runnable() {
               @Override
               public void run() {
                    setupRemoteVideo(uid);
               }
           });
      }
}

其中 onRemoteVideoStateChanged 回調方法中 state 參數表明狀態,uid 用來標識遠端用戶 id,若是有多個朋友加入了該頻道,咱們就要用 uid 來區分一下用戶,避免漏了或者重複創建遠端用戶視圖。

4.6.2 創建遠端用戶視圖

接下來創建遠端用戶視圖,和創建 Camera 預覽視圖方法基本一致。

// 由 Agora SDK 建立 SurfaceView
mRemoteView = RtcEngine.CreateRendererView(getBaseContext());
// 把 SurfaceView 添加到當前 Activity 的佈局控件樹上
mRemoteContainer.addView(mRemoteView);
// Camera 畫面預覽就用 setupLocalVideo 方法,遠端用戶就用 setupRemoteVideo 方法
mRtcEngine.setupRemoteVideo(new VideoCanvas(mRemoteView, VideoCanvas.RENDER_MODE_HIDDEN, uid));

一樣是由 Agora SDK 去建立 SurfaceView ,把它添加到控件容器上,最後經過 setupRemoteVideo 方法完成創建,整個邏輯和 Camera 視圖創建是相似的,就是最後調用的方法不同了。

4.7 應用運行並視頻通話

當創建好了遠端用戶視圖,理論上如今就能夠顯示本身和對方的畫面了,並互相聽到聲音了。

用兩臺手機分別運行程序,能夠驗證效果以下:

另外在官網上還能夠查看當前項目的流量使用狀況:

每月有 10000 分鐘的流量贈送,能夠放心使用

5. 項目開發總結

經過以上的 SDK 接入和代碼示例就已經完成了一個簡單的雙人音視頻通話。

而 Agora SDK 提供的功能遠非如此。

咱們還能夠對當前頻道的音視頻進行控制,選擇是否靜音、是否關閉畫面等等;咱們還能夠切換頻道,參與頻道的通話;咱們還能夠將項目打形成多人的音視頻通話,爲每一個加入頻道的用戶創建遠端視圖。

更多的音視頻相關功能均可以經過 Agora SDK 來實現了。

總結一下總體的接入流程也是很是方便的:

SDK 集成 -> 權限設置 -> Camera 預覽 -> 加入頻道 -> 顯示畫面 -> 在線通話

以上的每一個步驟在文章中都有講解,但願在你的使用過程當中會有一些幫助!!!

「本文爲我的原創,首發於 聲網開發者社區」

詳情: https://rtcdeveloper.com/t/topic/20054

相關文章
相關標籤/搜索