async function ensureAudioPlaying(audioTrack) {
const result = await ensureSilenceOrPlayingForAudioTrack(
audioTrack, true);
assertTrue(result);
}
async function ensureSilence(audioTrack) {
const result = await ensureSilenceOrPlayingForAudioTrack(
audioTrack, false);
assertTrue(result);
}
async function isSilentAudioBlob(blob) {
console.log('Blob size:' + blob.size);
const arrayBuffer = await blob.arrayBuffer();
const audioCtx = new AudioContext();
const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
let silent = true;
for (let ch = 0; ch < audioBuffer.numberOfChannels; ch++) {
const channelData = audioBuffer.getChannelData(ch);
for (let i = 0; i < channelData.length; i++) {
if (Math.abs(channelData[i]) >
1e-5) {
silent = false;
break;
}
}
if (!silent)
break;
}
return silent;
}
* @private
*/
function ensureSilenceOrPlaying(peerConnection, checkPlaying) {
const remoteAudioTrack = getRemoteAudioTrack(peerConnection);
assertTrue(remoteAudioTrack);
return ensureSilenceOrPlayingForAudioTrack(remoteAudioTrack, checkPlaying);
}
* @private
*/
async function ensureSilenceOrPlayingForAudioTrack(audioTrack, checkPlaying) {
const threshold = -50;
const checkInterval = 100;
const maxAttempts = 20;
const audioContext = new AudioContext();
const mediaStreamSource =
audioContext.createMediaStreamSource(new MediaStream([audioTrack]));
const analyser = audioContext.createAnalyser();
console.log('checkPlaying: ' + checkPlaying);
assertEquals(audioTrack.readyState, 'live');
analyser.fftSize = 512;
const dataArray = new Uint8Array(analyser.frequencyBinCount);
mediaStreamSource.connect(analyser);
return new Promise((resolve) => {
let attempts = 0;
let silentCount = 0;
const checkSilence = () => {
analyser.getByteFrequencyData(dataArray);
const sum = dataArray.reduce((acc, value) => acc + value, 0);
const average = sum / dataArray.length;
const decibels = 20 * Math.log10(average / 255);
if (decibels < threshold) {
silentCount++;
}
attempts++;
console.log(
'decibels: ' + decibels + ' silentCount: ' + silentCount,
'attempts: ' + attempts);
if (silentCount === maxAttempts) {
console.log('Silence detected consistently.');
close(!checkPlaying);
} else if (attempts >= maxAttempts) {
console.log('Playing detected consistently.');
close(checkPlaying);
}
};
const intervalId = setInterval(checkSilence, checkInterval);
audioTrack.onended = () => {
console.log('Audio track ended.');
clearInterval(intervalId);
resolve(false);
};
function close(result) {
audioContext.close().then(() => {
console.log('AudioContext closed.');
clearInterval(intervalId);
resolve(result);
});
}
});
}