android音頻採集
⑴ Android WebRTC 音頻採集揚聲器聲音
webrtc 默認情況下,採集的視頻和音頻,大部分採集的是麥克風和攝像頭的內容,
但有的時候,需要採集屏幕的內容和揚聲器的聲音,並將其發送出去。
關於屏幕的採集不做陳述,github上的例子很多,本文主要講隱頌解如何採集揚聲器的聲音。
對於Android系統來說,漏裂如果你要進行錄制揚聲器的聲音,是需要系統許可權的。
所以,如果你沒有系統許可權的話,(也就是system用戶),那本文是無法實現的。
具體實現步驟:
1.
在 AndroidManifest.xml 中
android:sharedUserId="android.uid.system" //用戶許可權
<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
2.
在創建peerconnection的時候,需灶搜鄭要添加setAudioDeviceMole(admbuilder.createAudioDeviceDole());
admbuilder 默認情況下使用麥克風的聲音,所以我們把麥克風的聲音修改掉:
admbuilder.setAudioSource( MediaRecorder.AudioSource.REMOTE_SUBMIX);
這里的揚聲器就是MediaRecorder.AudioSource.REMOTE_SUBMIX。
⑵ 如何採集一幀音頻
本文重點關注如何在Android平台上採集一幀音頻數據。閱讀本文之前,建議先讀一下我的上一篇文章《Android音頻開發(1):基礎知識》,因為音頻開發過程中,經常要涉及到這些基礎知識,掌握了這些重要的概念後,開發過程中的很多參數和流程就會更加容易理解。
Android SDK 提供了兩套音頻採集的API,分別是:MediaRecorder 和 AudioRecord,前者是一個更加上層一點的API,它可以直接把手機麥克風錄入的音頻數據進行編碼壓縮(如AMR、MP3等)並存成文件,而後者則更接近底層,能夠更加自由靈活地控制,可以得到原始的一幀幀PCM音頻數據。
如果想簡單地做一個錄音機,錄製成音頻文件,則推薦使用 MediaRecorder,而如果需要對音頻做進一步的演算法處理、或者採用第三方的編碼庫進行壓縮、以及網路傳輸等應用,則建議使用 AudioRecord,其實 MediaRecorder 底層也是調用了 AudioRecord 與 Android Framework 層的 AudioFlinger 進行交互的。
音頻的開發,更廣泛地應用不僅僅局限於本地錄音,因此,我們需要重點掌握如何利用更加底層的 AudioRecord API 來採集音頻數據(注意,使用它採集到的音頻數據是原始的PCM格式,想壓縮為mp3,aac等格式的話,還需要專門調用編碼器進行編碼)。
1. AudioRecord 的工作流程
首先,我們了解一下 AudioRecord 的工作流程:
(1) 配置參數,初始化內部的音頻緩沖區
(2) 開始採集
(3) 需要一個線程,不斷地從 AudioRecord 的緩沖區將音頻數據逗讀地出來,注意,這個過程一定要及時,否則就會出現逗overrun地的錯誤,該錯誤在音頻開發中比較常見,意味著應用層沒有及時地逗取走地音頻數據,導致內部的音頻緩沖區溢出。
(4) 停止採集,釋放資源
2. AudioRecord 的參數配置
上面是 AudioRecord 的構造函數,我們可以發現,它主要是靠構造函數來配置採集參數的,下面我們來一一解釋這些參數的含義(建議對照著我的上一篇文章來理解):
(1) audioSource
該參數指的是音頻採集的輸入源,可選的值以常量的形式定義在 MediaRecorder.AudioSource 類中,常用的值包括:DEFAULT(默認),VOICE_RECOGNITION(用於語音識別,等同於DEFAULT),MIC(由手機麥克風輸入),VOICE_COMMUNICATION(用於VoIP應用)等等。
(2) sampleRateInHz
采樣率,注意,目前44100Hz是唯一可以保證兼容所有Android手機的采樣率。
(3) channelConfig
通道數的配置,可選的值以常量的形式定義在 AudioFormat 類中,常用的是 CHANNEL_IN_MONO(單通道),CHANNEL_IN_STEREO(雙通道)
(4) audioFormat
這個參數是用來配置逗數據位寬地的,可選的值也是以常量的形式定義在 AudioFormat 類中,常用的是 ENCODING_PCM_16BIT(16bit),ENCODING_PCM_8BIT(8bit),注意,前者是可以保證兼容所有Android手機的。
(5) bufferSizeInBytes
這個是最難理解又最重要的一個參數,它配置的是 AudioRecord 內部的音頻緩沖區的大小,該緩沖區的值不能低於一幀逗音頻幀地(Frame)的大小,而前一篇文章介紹過,一幀音頻幀的大小計算如下:
int size = 采樣率 x 位寬 x 采樣時間 x 通道數
采樣時間一般取 2.5ms~120ms 之間,由廠商或者具體的應用決定,我們其實可以推斷,每一幀的采樣時間取得越短,產生的延時就應該會越小,當然,碎片化的數據也就會越多。
在Android開發中,AudioRecord 類提供了一個幫助你確定這個 bufferSizeInBytes 的函數,原型如下:
int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat);
不同的廠商的底層實現是不一樣的,但無外乎就是根據上面的計算公式得到一幀的大小,音頻緩沖區的大小則必須是一幀大小的2~N倍,有興趣的朋友可以繼續深入源碼探究探究。
實際開發中,強烈建議由該函數計算出需要傳入的 bufferSizeInBytes,而不是自己手動計算。
3. 音頻的採集線程
當創建好了 AudioRecord 對象之後,就可以開始進行音頻數據的採集了,通過下面兩個函數控制採集的開始/停止:
AudioRecord.startRecording();
AudioRecord.stop();
一旦開始採集,必須通過線程循環盡快取走音頻,否則系統會出現 overrun,調用的讀取數據的介面是:
AudioRecord.read(byte[] audioData, int offsetInBytes, int sizeInBytes);
⑶ Android音視頻【十三】OpenSL ES介紹&基於OpenSL ES實現音頻採集
Android音視頻開發中,通常使用AudioRecord進行音頻採集,但OpenSL ES提供了C/C++性能優勢,避免了Java層的復雜性和性能消耗。本文著重介紹如何在JNI層通過OpenSL ES進行音頻採集。OpenSL ES,作為無授權、跨平台的音頻加速API,旨在提升嵌入式設備應用的音頻處理性能。它支持C語言介面,運行於native層,允許直接處理PCM數據,降低數據傳輸和通信成本。
與Android的關系是,Android實現的OpenSL ES基於OpenSL 1.0.1,擴展了一些功能。在使用時需注意Android特有的API限制。OpenSL ES支持16000Hz采樣率的單通道PCM數據採集和播放,且兼容多種配置,但不支持所有平台。相較於Java API,OpenSL ES能提供更靈活的控制和深度優化,但對設備版本有要求,不支持MIDI和加密內容播放。
在實際開發中,首先在AndroidManifest.xml中添加錄音許可權,然後在項目中鏈接OpenSLES庫。OpenSL ES的開發基於Objects和Interfaces概念,通過創建和管理對象來實現音頻功能。創建SLEngineItf對象後,設置輸入輸出配置,創建錄音器並開始錄音,通過SLRecordItf介面控制錄音狀態。採集到的音頻數據通過回調函數處理,並在完成後釋放資源。
一個簡單的示例展示了如何在JNI層使用OpenSL ES進行錄音,並提供了測試方法。通過學習OpenSL ES,開發者可以構建高效、低延遲的音頻應用。相關學習資源可進一步深化理解。更多詳情可參考Android中文官網,以及GitHub項目。