本文主要介绍如何做音量大小的判定。 音量大小的判定主要应用在:
- 检查麦克风的通话质量
- 获取音视频通话中用户的说话音量
实现方法
通过调用 getAudioLevel() 方法获取当前音量大小。
setInterval(() => {
const volume = stream.getAudioLevel();
if (volume > 0.1) {
console.log(`${stream.getUserId()} is speaking`);
}
}, 1000);
如果需要在页面中渲染用户音量大小,建议使用 requestAnimationFrame
替换 setInterval
进行性能优化
// 设置AnimationFrame
function setAnimationFrame(render) {
// 计时器
let timer = {};
function animeLoop() {
render();
timer.id = requestAnimationFrame(animeLoop);
}
animeLoop();
return timer;
}
// 清除AnimationFrame
function clearAnimationFrame(timer) {
cancelAnimationFrame(timer.id);
}
最佳实践
以下提供两种页面中渲染用户音量的实践方案,接入者可根据业务场景选择合适的方案:
方案一用更简便的逻辑实现监听和取消监听用户音量功能,优先推荐给接入方使用
方案二更加详细的梳理了监听音量和取消监听音量的时机,供接入方参考
方案一
第一步:创建远端流数组 remoteStreamList
let remoteStreamList = [];
client.on('stream-subscribed', { stream: remoteStream } => {
remoteStreamList.push(remoteStream);
})
client.on('stream-removed', { stream: remoteStream } => {
remoteStreamList = remoteStreamList.filter(stream => {
return stream.getId() !== remoteStream.getId();
});
})
第二步:封装开始获取音量 startGetAudioLevel
和停止获取音量 stopGetAudioLevel
的方法
// 开始获取流音量
let getAudioLevelTimer = -1;
function startGetAudioLevel() {
getAudioLevelTimer = setAnimationFrame(() => {
if (localStream) {
const level = localStream.getAudioLevel();
if (level >= 0.1) {
console.warn(`user ${localStream.getUserId()} is speaking, volume: ${level}`);
// 在页面中渲染用户音量大小
}
}
remoteStreamList.forEach(stream => {
const level = stream.getAudioLevel();
if (level >= 0.1) {
console.warn(`user ${stream.getUserId()} is speaking, volume: ${level}`);
// 在页面中渲染用户音量大小
}
});
});
}
// 停止获取流音量
function stopGetAudioLevel() {
if (getAudioLevelTimer !== -1) {
clearAnimationFrame(getAudioLevelTimer);
getAudioLevelTimer = -1;
}
}
第三步:在本地用户进房和退房时执行 startGetAudioLevel
和 stopGetAudioLevel
方法
开始获取所有流音量:本地用户执行 client.join
之后开始获取所有流的音量
client.join();
startGetAudioLevel();
停止获取所有流音量:本地用户执行 client.leave
之后停止获取所有流的音量
client.leave();
stopGetAudioLevel();
方案二
第一步:封装开始获取音量 startGetAudioLevel
和停止获取音量 stopGetAudioLevel
的方法
const audioLevelTimerMap = new Map();
// 开始获取指定流音量
function startGetAudioLevel(stream) {
let timer = setAnimationFrame(() => {
const volume = stream.getAudioLevel();
if (volume > 0.1) {
console.log(`user ${stream.getUserId()} is speaking, volume: ${volume}`);
// 在页面中渲染用户音量大小
}
});
audioLevelTimerMap.set(stream.getId(), timer);
}
// 停止获取指定流音量
function stopGetAudioLevel(stream) {
let timer = audioLevelTimerMap.get(stream.getId());
clearAnimationFrame(timer);
}
// 停止获取所有流的音量
function clearGetAudioLevelTimer() {
audioLevelTimerMap.forEach(audioLevelTimer => {
audioLevelTimer && clearAnimationFrame(audioLevelTimer);
});
audioLevelTimerMap.clear();
}
第二步:分别执行本地流和远端流的 startGetAudioLevel
和 stopGetAudioLevel
方法
开始获取本地流音量:本地用户执行 client.publish
之后开始获取本地音量
client.publish(localStream);
startGetAudioLevel(localStream);
停止获取本地流音量:本地用户执行 client.unpublish
之后停止获取本地音量
client.unpublish(localStream);
stopGetAudioLevel(localStream);
开始获取远端流音量:监听到远端流 stream-subscribed
事件时开始获取远端流音量
client.on('stream-subscribed', { stream: remoteStream } => {
startGetAudioLevel(remoteStream);
})
停止获取远端流音量:监听到远端流 stream-removed
事件时停止获取远端流音量
client.on('stream-removed', { stream: remoteStream } => {
stopGetAudioLevel(remoteStream);
})
停止获取所有流音量:本地用户执行 client.leave
之后停止获取所有流的音量
client.leave();
clearGetAudioLevelTimer();