我正在参加「掘金·启航计划」
[Toc]
快速上手
- 安装
npm add @netless/fastboard @netless/window-manager white-web-sdk
创建实时音频
采集音视频相关
1. 获取摄像头列表
调用
getMicrophones
获取可用的摄像头列表
getMicrophones
方法会通过 Promise 异步返回一个MediaDeviceInfo
对象的数组。MediaDeviceInfo
对象复用了 WebRTC API 中的 MediaDeviceInfo 对象。因为是异步方法,你可以使用 then/catch (ES6) 或 async/await (ES7) 获取返回值。
// 获取可用的麦克风设备列表。
// 调用时,如果浏览器还没有获得麦克风访问权限,会在界面上提示你是否允许浏览器访问麦克风。
AgoraRTC.getMicrophones()
.then((deviceInfoArray) => {
/* 返回 MediaDeviceInfo 数组对象之后的操作*/
})
.catch((e) => {
console.log("Failed to get microphones!", e);
});
2. 获取摄像头设备信息
在此教程中,我们在 HTML 中创建一个下拉菜单来供用户选择使用的摄像头设备。在用户界面上使用 label
属性显示设备信息。deviceId
属性用于保存设备 ID,用于后续的摄像头访问。
label
,即设备标签,返回一个 DOMString,代表描述对应设备的标签。如果浏览器没有获取设备权限,则返回""
。
deviceId
,即设备 ID,返回一个 DOMString,代表对应设备。设备 ID 对于应用是唯一的,只要浏览器的 cookie 没有被清除,即使你开启了新的浏览器会话(session),设备 ID 也会保持不变。如果你清除了浏览器 cookie,则设备 ID 会重置。同理,如果你开启了浏览器隐私模式,对于同一个设备,每个浏览器会话的设备 ID 都是不同的。因此,建议每次对设备进行操作时重新获取设备 ID。
HTML
<h1>通过麦克风采集并在本地渲染音频</h1>
<form>
<b> 选择你要使用的麦克风 </b>
<select id = "microphoneList" onchange = "getDeviceId()" >
<option> ---选择麦克风--- </option>
</select>
</form>
<p>你选择设备的 deviceId 是:</p>
<p id="deviceId"></p>
JavaScript
// 定义设备 ID 与标签的映射
let dict = {};
// 获取摄像头列表
AgoraRTC.getMicrophones()
.then((deviceInfoArray) => {
for (let deviceInfo of deviceInfoArray) {
let option = document.createElement("option");
document.getElementById("microphoneList").appendChild(option);
option.innerHTML = deviceInfo.label;
dict[deviceInfo.label] = deviceInfo.deviceId;
}
})
.catch((e) => {
console.log("Failed to get microphones!", e);
});
// 根据下拉菜单选择的设备标签,显示相应的设备 ID
function getDeviceId() {
let microphoneList = document.getElementById("microphoneList");
let deviceLabel = microphoneList.options[microphoneList.selectedIndex].text;
document.getElementById("deviceId").innerHTML = dict[deviceLabel];
}
3. 创建麦克风音频轨道并渲染
调用 createMicrophoneAudioTrack
创建麦克风音频轨道并调用成员方法 play
通过系统默认扬声器对视频进行渲染。这里轨道的概念和 WebRTC 中的 track 相似。一个轨道代表一路特定的视频源或音频源。声网 SDK 将不同来源的音视频轨道进行抽象,定义了摄像头视频轨道、屏幕采集视频轨道及自定义源视频轨道等。
这个步骤只是为了演示麦克风音频轨道的渲染。实际开发通话应用时,本地不需要播放本地麦克风采集的音频。
-
HTML
<h1>通过麦克风采集并在本地渲染音频</h1> <form> <b> 选择你要使用的麦克风 </b> <select id="microphoneList" onchange="getDeviceId()"> <option> ---选择麦克风--- </option> </select> </form> <p>你选择设备的 deviceId 是:</p> <p id="deviceId"></p>
CSS
body {font-family: system-ui;background: #f06d06;color: white;text-align: center;} div {height: 200px;width: 50%;}
JavaScript
// 全局变量 let dict = {}; // 使用 dict 映射设备标签和设备 ID let selectedDeviceId = ""; // 下选框选择的设备对应的 ID let microphoneAudioTrack = null; // 麦克风音频轨道对象 // 获取本地麦克风列表 AgoraRTC.getMicrophones() .then((deviceInfoArray) => { for (let deviceInfo of deviceInfoArray) { let option = document.createElement("option"); document.getElementById("microphoneList").appendChild(option); option.innerHTML = deviceInfo.label; dict[deviceInfo.label] = deviceInfo.deviceId; } }) .catch((e) => { console.log("Failed to get microphones!", e); }); // 创建麦克风音频轨道 AgoraRTC.createMicrophoneAudioTrack() .then((microphoneAudioTrack) => { // 渲染音频。SDK 使用系统默认的扬声器播放声音。 microphoneAudioTrack.play(); }) .catch((e) => { console.log("Failed to play audio!", e); }); // 根据选择的设备标签,返回对应的设备 ID 并传给麦克风音频轨道 function getDeviceId() { let microphoneList = document.getElementById("microphoneList"); let deviceLabel = microphoneList.options[microphoneList.selectedIndex].text; selectedDeviceId = dict[deviceLabel]; document.getElementById("deviceId").innerHTML = selectedDeviceId; if (microphoneAudioTrack != null) { microphoneAudioTrack.setDevice(selectedDeviceId); } }
#音频回调
setAudioFrameCallback
setAudioFrameCallback(audioFrameCallback: null | function, frameSize?: undefined | number): void
设置原始音频数据(PCM)回调。
设置成功后,SDK 会不断地将远端音频轨道的音频帧以 AudioBuffer 的形式通过回调返回。
你可以通过
frameSize
来设置每次回调中音频帧的大小。该设置也会影响回调的间隔,frameSize
越大,每次回调的音频数据越多,回调间隔越长。
track.setAudioFrameCallback((buffer) => {
for (let channel = 0; channel < buffer.numberOfChannels; channel += 1) {
// Float32Array with PCM data
const currentChannelData = buffer.getChannelData(channel);
console.log("PCM data in channel", channel, currentChannelData);
}
}, 2048);
// ....
// Stop getting the raw audio data
track.setAudioFrameCallback(null);
音频回调解码
AudioBuffer - Web API 接口参考 | MDN
AudioBuffer 接口表示存在内存里的一段短小的音频资源,利用AudioContext.decodeAudioData()
方法从一个音频文件构建,或者利用 AudioContext.createBuffer()
从原始数据构建。把音频放入 AudioBuffer 后,可以传入到一个 AudioBufferSourceNode
进行播放。
这些类型对象被设计来控制小音频片段,往往短于 45 秒。对于更长的声音,通过 MediaElementAudioSourceNode
来实现更为合适。缓存区(buffer)包含以下数据:不间断的 IEEE754 32 位线性 PCM,从-1 到 1 的范围额定,就是说,32 位的浮点缓存区的每个样本在-1.0 到 1.0 之间。如果AudioBuffer
有不同的频道,他们通常被保存在独立的缓存区。
1) 属性
-
存储在缓存区的 PCM 数据的采样率:浮点数,单位为 sample/s。
-
返回存储在缓存区的 PCM 数据的采样帧数:整形。
-
返回存储在缓存区的 PCM 数据的时长:双精度型(单位为秒)。
-
AudioBuffer.numberOfChannels
只读返回存储在缓存区的 PCM 数据的通道数:整形。
2) 方法
-
返回一个
Float32Array
,包含了带有频道的 PCM 数据,由频道参数定义(有 0 代表第一个频道) -
从 AudioBuffer 的指定频道复制到数组终端。
-
AudioBuffer.copyToChannel()
(en-US)复制样品到原数组的 AudioBuffer 的指定频道
3) 例子
以下的例子展示了如何构建一个 AudioBuffer 以及随机用白噪音填充。你可以在 audio-buffer demo库发现完整的源代码;一个running live 的版本也可获得。
// Stereo
var channels = 2;
// Create an empty two second stereo buffer at the
// sample rate of the AudioContext
var frameCount = audioCtx.sampleRate * 2.0;
var myArrayBuffer = audioCtx.createBuffer(channels, frameCount, audioCtx.sampleRate);
button.onclick = function() {
// Fill the buffer with white noise;
// just random values between -1.0 and 1.0
for (var channel = 0; channel < channels; channel++) {
// This gives us the actual array that contains the data
var nowBuffering = myArrayBuffer.getChannelData(channel);
for (var i = 0; i < frameCount; i++) {
// Math.random() is in [0; 1.0]
// audio needs to be in [-1.0; 1.0]
nowBuffering[i] = Math.random() * 2 - 1;
}
}
// Get an AudioBufferSourceNode.
// This is the AudioNode to use when we want to play an AudioBuffer
var source = audioCtx.createBufferSource();
// set the buffer in the AudioBufferSourceNode
source.buffer = myArrayBuffer;
// connect the AudioBufferSourceNode to the
// destination so we can hear the sound
source.connect(audioCtx.destination);
// start the source playing
source.start();
}
4) 规格参数
Specification |
---|
Web Audio API # AudioBuffer |
录音对象属性
Agora Web API Reference - 语音通话 - 文档中心 - 声网Agora
音频编码
AudioEncoderConfigurationPreset
AudioEncoderConfigurationPreset: keyof typeof AUDIO_ENCODER_CONFIG_SETTINGS
SDK 预设的 [AudioEncoderConfiguration](docs.agora.io/cn/Voice/AP… Reference/web_ng/interfaces/audioencoderconfiguration.html) 配置。
你可以在以下方法中传入预设值来控制本地音频的编码配置:
- [AgoraRTC.createCustomAudioTrack](docs.agora.io/cn/Voice/AP… Reference/web_ng/interfaces/iagorartc.html#createcustomaudiotrack)
- [AgoraRTC.createMicrophoneAudioTrack](docs.agora.io/cn/Voice/AP… Reference/web_ng/interfaces/iagorartc.html#createmicrophoneaudiotrack)
- [AgoraRTC.createBufferSourceAudioTrack](docs.agora.io/cn/Voice/AP… Reference/web_ng/interfaces/iagorartc.html#createbuffersourceaudiotrack)
下表列出了 SDK 所有内置的音频属性配置,SDK 默认使用 "music_standard"
。
音频属性 | 配置 |
---|---|
"speech_low_quality" | 16 kHz 采样率,单声道,编码码率约 24 Kbps |
"speech_standard" | 32 kHz 采样率,单声道,编码码率约 24 Kbps |
"music_standard" | 48 kHz 采样率,单声道,编码码率约 40 Kbps |
"standard_stereo" | 48 kHz 采样率,双声道,编码码率约 64 Kbps |
"high_quality" | 48 kHz 采样率,单声道, 编码码率约 128 Kbps |
"high_quality_stereo" | 48 kHz 采样率,双声道,编码码率约 192 Kbps |
本地音频轨道
Agora Web API Reference - 语音通话 - 文档中心 - 声网Agora