【声网】创建实时音频

[Toc]

快速上手

  1. 安装
1
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) 获取返回值。

1
2
3
4
5
6
7
8
9
// 获取可用的麦克风设备列表。
// 调用时,如果浏览器还没有获得麦克风访问权限,会在界面上提示你是否允许浏览器访问麦克风。
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

1
2
3
4
5
6
7
8
9
<h1>通过麦克风采集并在本地渲染音频</h1>
<form>
<b> 选择你要使用的麦克风 </b>
<select id = "microphoneList" onchange = "getDeviceId()" >
<option> ---选择麦克风--- </option>
</select>
</form>
<p>你选择设备的 deviceId 是:</p>
<p id="deviceId"></p>

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 定义设备 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 将不同来源的音视频轨道进行抽象,定义了摄像头视频轨道、屏幕采集视频轨道及自定义源视频轨道等。

这个步骤只是为了演示麦克风音频轨道的渲染。实际开发通话应用时,本地不需要播放本地麦克风采集的音频。

  1. HTML

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <h1>通过麦克风采集并在本地渲染音频</h1>
    <form>
    <b> 选择你要使用的麦克风 </b>
    <select id="microphoneList" onchange="getDeviceId()">
    <option> ---选择麦克风--- </option>
    </select>
    </form>
    <p>你选择设备的 deviceId 是:</p>
    <p id="deviceId"></p>

    CSS

    1
    2
    body {font-family: system-ui;background: #f06d06;color: white;text-align: center;}
    div {height: 200px;width: 50%;}

    JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    // 全局变量
    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 越大,每次回调的音频数据越多,回调间隔越长。

1
2
3
4
5
6
7
8
9
10
11
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) 属性
2) 方法
3) 例子

以下的例子展示了如何构建一个 AudioBuffer 以及随机用白噪音填充。你可以在 audio-buffer demo库发现完整的源代码;一个running live 的版本也可获得。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 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](https://docs.agora.io/cn/Voice/API Reference/web_ng/interfaces/audioencoderconfiguration.html) 配置。

你可以在以下方法中传入预设值来控制本地音频的编码配置:

下表列出了 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

对接

基于声网 Web SDK 实现视频通话场景 - 专栏 - 声网 Agora RTC 开发者社区


【声网】创建实时音频
https://hodlyounger.github.io/B_Code/TypeScript/【声网】创建实时音频/
作者
mingming
发布于
2023年10月27日
许可协议