声网为电子竞技、在线会议等场景提供空间音效功能,让用户拥有沉浸式的音频体验。
音频路由 | 是否支持真双声道播放 |
---|---|
有线耳机 | 支持 |
蓝牙耳机 | 用户闭麦时支持,用户上麦时不支持 |
扬声器 | 不支持 |
为了让本地用户听到远端用户的空间音效,你需要自行计算本地用户与远端用户的相对位置,然后分别调用 updateSelfPosition
和 updateRemotePosition
更新本地和远端用户的空间坐标。
为了让用户听到本地播放音频文件的空间音效,你需要分别调用 updateSelfPosition
和 updatePlayerPositionInfo
更新本地用户和媒体播放器的空间坐标。
参考快速开始文档,将 Web SDK(v4.13.0 或以上)集成到你的项目中并实现基本的实时音视频功能。
通过 npm 将空间音效插件(agora-extension-spatial-audio)集成到你的项目中。
npm install agora-extension-spatial-audio
.js
文件中加入以下代码导入空间音效模块:import {SpatialAudioExtension} from "agora-extension-spatial-audio";
动态加载 Wasm 和 JS 文件依赖:空间音效插件依赖一些 Wasm 和 JS 文件。为保证浏览器可以正常加载和运行这些文件,你需要完成以下步骤:
node_modules/agora-extension-spatial-audio/external
目录下的 Wasm 和 JS 文件发布至 CDN 或者静态资源服务器中,并且处于同一个公共路径下。后续创建 SpatialAudioExtension
对象时,需要传入上述公共路径的 URL,插件会动态加载这些依赖文件。script-src
选项中添加 'wasm-unsafe-eval'
。 例如:<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'wasm-unsafe-eval'">
script-src
选项中添加 'unsafe-eval'
。注册空间音效插件:调用 AgoraRTC.registerExtensions
方法并传入创建的 SpatialAudioExtension
实例。
const extension = new SpatialAudioExtension({
assetsPath: yourDeployPath, // for example, yourDeployPath = './resources/external/'
});
AgoraRTC.registerExtensions([extension]);
订阅远端用户时,实现该用户的空间音效:
创建 SpatialAudioProcessor
实例:调用 createProcessor
方法创建。
将插件注入远端用户的音频轨道:调用 pipe
方法并指定 processorDestination
属性。
async function subscribe(user, mediaType) {
await client.subscribe(user, mediaType);
console.log("subscribe success");
if (mediaType === "audio") {
const processor = extension.createProcessor();
const track = user.audioTrack;
track.pipe(processor).pipe(track.processorDestination);
track.play();
}
}
完整的 API 调用时序如下:
本地播放背景音、伴奏、NPC 语音等音频文件时,实现该音频文件的空间音效:
创建 SpatialAudioProcessor
实例:调用 createProcessor
方法创建。
将插件注入本地音频文件的音频轨道:调用 pipe
方法并指定 processorDestination
属性。
var localPlayerSound = [
// './resources/1.mp3',
"./resources/2.mp3",
// './resources/3.mp3',
// './resources/4.mp3',
];
async function localPlayerStart() {
for (let i = 0; i < localPlayerSound.length; i++) {
const processor = extension.createProcessor();
const track = await AgoraRTC.createBufferSourceAudioTrack({source: localPlayerSound[i]});
track.startProcessAudioBuffer({loop: true});
track.pipe(processor).pipe(track.processorDestination);
track.play();
}
}
完整的 API 调用时序如下:
createProcessor(): SpatialAudioProcessor;
创建一个 SpatialAudioProcessor
实例。
public updateSelfPosition(position: position, forward: forward, right: right, up: up): SpatialAudioErrorCode
更新本地用户的空间位置。
成功调用该方法后,SDK 会根据本地用户、所有远端用户、以及媒体播放器(如有)的相对位置变化,更新空间音效参数。
参数:
position
:在世界坐标系中的坐标。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。forward
:在世界坐标系前轴的单位向量。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。right
:在世界坐标系右轴的单位向量。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。up
:在世界坐标系上轴的单位向量。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。返回值:
详见 SpatialAudioErrorCode。
const mockLocalUserNewPosition = {
// For example, mockLocalUserNewPosition can be produced by dragging the local user's avatar to walk in a 3D scene
position: [1, 1, 1],
forward: [1, 0, 0],
right: [0, 1, 0],
up: [0, 0, 1],
};
extension.updateSelfPosition(
mockLocalUserNewPosition.position,
mockLocalUserNewPosition.forward,
mockLocalUserNewPosition.right,
mockLocalUserNewPosition.up,
);
public clearRemotePositions(): SpatialAudioErrorCode
删除所有远端用户以及媒体播放器的空间位置信息。
成功调用该方法后,所有远端用户以及媒体播放器的空间音频效果会消除,但本地用户仍然可以听到远端用户和媒体播放器的声音。
离开频道后,为避免计算资源的浪费,你也可以调用该方法删除所有远端用户和媒体播放器的空间位置信息。
返回值:
详见 SpatialAudioErrorCode。
public updateSpatialBlur(enable: boolean): void
更新声音模糊处理的设置。
成功调用该方法后,会更新该远端用户或媒体播放器的声音模糊处理的设置。
参数:
enable
:是否开启声音模糊处理。true
: 开启模糊处理。false
: (默认)关闭模糊处理。public updateSpatialAirAbsorb(enable: boolean): void
更新空气传播模拟的设置。
成功调用该方法后,会更新该远端用户或媒体播放器的空气传播模拟设置。空气传播模拟是指模拟声音在空气中传播时,音色随着距离增加而改变的效果。
参数:
enable
:是否开启空气传播模拟。true
: (默认)开启空气传播模拟。false
: 关闭空气传播模拟。public updatePlayerPositionInfo(info: RemoteVoicePositionInfo): SpatialAudioErrorCode;
更新指定媒体播放器的空间位置。
成功调用该方法后,SDK 会根据本地用户和该播放器的相对位置变化更新空间音效参数。
参数:
info
:播放器的空间位置信息。详见 RemoteVoicePositionInfo。返回值:
详见 SpatialAudioErrorCode。
const mockLocalPlayerNewPosition = {
position: [1, 1, 1],
forward: [1, 0, 0],
};
processor.updatePlayerPositionInfo(mockLocalPlayerNewPosition);
public updateRemotePosition(info: RemoteVoicePositionInfo): SpatialAudioErrorCode;
更新指定远端用户的空间位置信息。
成功调用该方法后,SDK 会根据本地用户和该远端用户的相对位置计算空间音效参数。
参数:
info
:远端用户的空间位置信息。详见 RemoteVoicePositionInfo。返回值:
详见 SpatialAudioErrorCode。
const processors = new Map();
client.on("user-published", async (user, mediaType) => {
await client.subscribe(user, mediaType);
console.log("subscribe success");
if (mediaType === "audio") {
const processor = extension.createProcessor();
processors.set(user.uid, processor);
const track = user.audioTrack;
track.pipe(processor).pipe(track.processorDestination);
track.play();
}
});
// The following code mocks the case of receiving the remote user's position change message from your server
yourOwnEventHandler.on("updatePosition", (uid, data) => {
const processor = processors.get(uid);
processor.updateRemotePosition({
position: data.position,
forward: data.forward,
});
});
public removeRemotePosition(): SpatialAudioErrorCode
删除指定远端用户或媒体播放器的空间位置信息。
成功调用该方法后,指定远端用户或媒体播放器的空间音频效果会消除,但本地用户仍然可以听到指定远端用户或媒体播放器。
离开频道后,为避免计算资源的浪费,你也可以调用该方法删除指定远端用户或媒体播放器的空间位置信息。
返回值:
详见 SpatialAudioErrorCode。
yourOwnEventHandler.on("removePosition", uid => {
const processor = processors.get(uid);
processor.removeRemotePosition();
});
public setZones(set: ZoneSet): SpatialAudioErrorCode
设置隔声区域。
在虚拟互动场景下,你可以通过该方法设置隔声区域及其声音衰减系数。当音源(可以为用户或媒体播放器)跟听声者分属于隔声区域内部和外部时,会体验到类似真实环境中声音在遇到建筑隔断时的衰减效果。
音源 | 听声者 | 声音衰减系数 |
---|---|---|
隔声区域 A 内部 | 隔声区域 A 外部 | 以 setZones 的设置为准 |
隔声区域 A 内部 | 隔声区域 A 内部 | forceSet 设为 true :以 updateSpatialAttenuation 的设置为准。如果没有调用 updateSpatialAttenuation ,则 SDK 默认声音的衰减系数为 0.5,即模拟声音在真实环境下的衰减。forceSet 设为 false :以 setZones 的设置为准。 |
隔声区域 A 内部 | 隔声区域 B 内部 | 听声者无法听到音源 |
不在任何一个隔声区域内 | 不在任何一个隔声区域内 | 以 updateSpatialAttenuation 的设置为准。如果没有调用 updateSpatialAttenuation ,则 SDK 默认声音的衰减系数为 0.5,即模拟声音在真实环境下的衰减。 |
参数:
set
:隔声区域的设置。该参数是由 ZoneParams
对象组成的数组。详见 ZoneParams。返回值:
详见 SpatialAudioErrorCode。
public updateSpatialAttenuation(factor: number, forceSet: boolean): SpatialAudioErrorCode
更新远端用户或媒体播放器的声音衰减效果。
参数:
factor
:远端用户或媒体播放器的声音衰减系数,取值范围为[0,1],默认值为 0.5。其中:factor
参数。forceSet
:是否强制设定远端用户或媒体播放器的的声音衰减效果:
返回值:
详见 SpatialAudioErrorCode。
public setDistanceUnit(unit: number): SpatialAudioErrorCode
设置游戏引擎单位距离的长度(米)。
游戏引擎里的距离单位是游戏引擎自定义的,而声网空间音效算法的距离单位为米。默认情况下,SDK 会将每单位的游戏引擎距离换算为一米。你可以调用该方法,将游戏引擎里的单位距离换算为指定的米数。
参数:
unit
:每单位游戏引擎距离转换后的米数,取值需大于 0。例如,将 unit
设为 2,表示每单位的游戏引擎距离等于 2 米。该值越大,当远端用户远离本地用户时,本地用户听到的声音衰减速度越快。返回值:
详见 SpatialAudioErrorCode。
export interface RemoteVoicePositionInfo {
position: position;
forward: forward;
};
远端用户或媒体播放器的空间位置信息。用于 updatePlayerPositionInfo 和 updateRemotePosition 方法。
属性:
position
:在世界坐标系中的坐标。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。forward
:在世界坐标系前轴的单位向量。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。export interface ZoneParams {
id: number;
position: position;
forward: forward;
right: right;
up: up;
forwardLength: number;
rightLength: number;
upLength: number;
attenuation: number;
}
隔声区域的设置参数。用于 setZones 方法。
属性:
id
:隔声区域的 ID。position
:隔声区域的空间中心点。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。forward
:以 position
为起点,向前的单位向量。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。right
:以 position
为起点,向右的单位向量。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。up
:以 position
为起点,向上的单位向量。该参数是长度为 3 的数组,三个值依次表示前、右、上的坐标值。forwardLength
:将整个隔声区域看做一个立方体,表示向前的边长,单位为游戏引擎的单位长度。rightLength
:将整个隔声区域看做一个立方体,表示向右的边长,单位为游戏引擎的单位长度。upLength
:将整个隔声区域看做一个立方体,表示向上的边长,单位为游戏引擎的单位长度。attenuation
:隔声区域以内的用户和外部用户互通时的声音衰减系数,取值范围为 [0,1]。其中:attenuation
参数。空间音频相关错误码:
SUCCESS
:方法调用成功。EXTENSION_NOT_REG
:插件未注册。PROCESSOR_NOT_CREATE
:未创建 Processor 实例。PROCESSOR_NOT_ENABLED
:Processor 未开启。INVALID_PARMS
:参数无效。UNKNOWN_ERROR
:未知错误。