infobip-rtc
Version:
Infobip RTC JavaScript SDK - Infobip WebRTC API Implementation
103 lines • 3.65 kB
JavaScript
import { throttle } from "lodash-es";
const AUDIO_ENERGY_THRESHOLD = 0.12;
const AUDIO_ENERGY_DELAY = 50;
const EVENT_COOLDOWN_MILLIS = 1000;
export class DefaultAudioStreamEnergyMonitor {
constructor(onAudioEnergyDetected, logger, callId) {
this.onAudioEnergyDetected = onAudioEnergyDetected;
this.logger = logger;
this.callId = callId;
this.audioContext = new AudioContext();
this.analyser = this.audioContext.createAnalyser();
this.analyser.fftSize = 512;
this.dataArray = new Float32Array(this.analyser.fftSize);
this.throttledEmitAudioEnergyDetected = throttle(() => this.onAudioEnergyDetected(), EVENT_COOLDOWN_MILLIS, { leading: true, trailing: false });
}
static create(onAudioEnergyDetected, logger, callId) {
if (typeof window.AudioContext === 'undefined') {
logger.warn("Could not initialize energy monitor. Web Audio API is not supported in this browser.", callId);
return null;
}
return new DefaultAudioStreamEnergyMonitor(onAudioEnergyDetected, logger, callId);
}
start(stream) {
const tracks = stream.getAudioTracks();
if (tracks.length < 1) {
this.logger.warn("Could not start energy monitor. There are no audio tracks.", this.callId);
return;
}
this.swapClonedTrack(tracks[0]);
this.source = this.audioContext.createMediaStreamSource(new MediaStream([this.clonedTrack]));
this.source.connect(this.analyser);
this.startAudioEnergyDetection();
}
stop() {
this.removeClonedTrack();
this.clearAnalyserInterval();
}
destroy() {
if (this.analyserInterval) {
clearInterval(this.analyserInterval);
this.analyserInterval = null;
}
if (this.source) {
this.source.disconnect();
this.source = null;
}
if (this.analyser) {
this.analyser.disconnect();
this.analyser = null;
}
if (this.audioContext) {
this.audioContext.close().catch(err => {
this.logger.error(`Failed to close AudioContext: ${err}`, this.callId);
});
this.audioContext = null;
}
this.removeClonedTrack();
this.dataArray = null;
}
swapClonedTrack(track) {
this.removeClonedTrack();
this.addClonedTrack(track);
}
startAudioEnergyDetection() {
this.clearAnalyserInterval();
this.startAnalyserInterval();
}
clearAnalyserInterval() {
if (this.analyserInterval) {
clearInterval(this.analyserInterval);
}
}
startAnalyserInterval() {
this.analyserInterval = setInterval(() => {
const energy = this.checkEnergy();
if (energy > AUDIO_ENERGY_THRESHOLD) {
this.throttledEmitAudioEnergyDetected();
}
}, AUDIO_ENERGY_DELAY);
}
checkEnergy() {
this.analyser.getFloatTimeDomainData(this.dataArray);
return this.rms(this.dataArray);
}
rms(dataArray) {
let sum = 0;
for (let i = 0; i < dataArray.length; i++) {
sum += dataArray[i] * dataArray[i];
}
return Math.sqrt(sum / dataArray.length);
}
removeClonedTrack() {
if (this.clonedTrack) {
this.clonedTrack.stop();
this.clonedTrack = null;
}
}
addClonedTrack(track) {
this.clonedTrack = track.clone();
this.clonedTrack.enabled = true;
}
}
//# sourceMappingURL=AudioStreamEnergyMonitor.js.map