123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
-
- // We wait a certain time interval for constant silence input from the current device to account for
- // potential abnormalities and for a better use experience i.e. don't generate event the instant
- // an audio track is added to the tcr.
- // Potential improvement - add this as a configurable parameter.
- const SILENCE_PERIOD_SEC = 4;
-
- /**
- * Detect if there is no audio input on the current TraceAblePeerConnection selected track. The no audio
- * state must be constant for a configured amount of time in order for the event to be triggered.
- */
- export default class NoAudioSignalDetection {
- /**
- * @param conference the JitsiConference instance that created us.
- * @param callback callback that notifies the conference when no audio event is triggered
- * @constructor
- */
- constructor(conference, callback) {
- this._conference = conference;
- this._callback = callback;
- this._firstSilentSignalDate = null;
-
- conference.statistics.addAudioLevelListener(this._audioLevel.bind(this));
- conference.on(JitsiConferenceEvents.TRACK_ADDED, this._trackAdded.bind(this));
- }
-
- /**
- * Checks if the configured period in which no audio was received has elapsed.
- *
- * @returns {boolean}
- */
- _hasSilencePeriodElapsed() {
- const currentDate = new Date();
- const elapsedSec = (currentDate.getTime() - this._firstSilentSignalDate.getTime()) / 1000;
-
- if (elapsedSec > SILENCE_PERIOD_SEC) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Trigger the set callback for no audio input if expected conditions are met.
- */
- _triggerNoAudioCallback() {
- // In case this is the first time 0 audio level was detected initialize the interval check start
- // date
- if (!this._firstSilentSignalDate) {
- this._firstSilentSignalDate = new Date();
-
- // If the configured interval has elapsed trigger the callback
- } else if (this._hasSilencePeriodElapsed()) {
- this._eventFired = true;
- this._callback();
- }
- }
-
- /**
- * Receives audio level events for all send and receive streams on the current TraceablePeerConnection.
- *
- * @param {TraceablePeerConnection} tpc - TraceablePeerConnection of the owning conference.
- * @param {number} ssrc - The synchronization source identifier (SSRC) of the endpoint/participant/stream
- * being reported.
- * @param {number} audioLevel - The audio level of the ssrc.
- * @param {boolean} isLocal - true for local/send streams or false for remote/receive streams.
- */
- _audioLevel(tpc, ssrc, audioLevel, isLocal) {
- // We are interested in the local audio stream if the event was not triggered on this device.
- if (!isLocal || !this._audioTrack || this._eventFired) {
- return;
- }
-
- // Get currently active local tracks from the TraceablePeerConnection
- const localSSRCs = tpc.localSSRCs.get(this._audioTrack.rtcId);
-
- // Check that currently selected audio stream has ssrc in the TraceablePeerConnection
- if (!localSSRCs) {
- return;
- }
-
- // Only target the current active track in the tpc. For some reason audio levels for previous
- // devices are also picked up from the PeerConnection so we filter them out.
- const isCurrentTrack = localSSRCs.ssrcs.includes(ssrc);
-
- if (!isCurrentTrack) {
- return;
- }
-
- if (audioLevel === 0) {
- this._triggerNoAudioCallback();
- } else {
- // Reset the period start date in order to check for consistent silence over the configured
- // time interval.
- this._firstSilentSignalDate = null;
- }
- }
-
- /**
- * Determines if a specific JitsiTrack is a local audio track.
- *
- * @param {JitsiTrack} track - The JitsiTrack to be checked whether it represents a local audio track.
- * @return {boolean} - true if track represents a local audio track, false otherwise.
- */
- _isLocalAudioTrack(track) {
- return track.isAudioTrack() && track.isLocal();
- }
-
- /**
- * Notifies NoAudioSignalDetection that a JitsiTrack was added to the associated JitsiConference.
- * Only take into account local audio tracks.
- *
- * @param {JitsiTrack} track - The added JitsiTrack.
- */
- _trackAdded(track) {
- if (this._isLocalAudioTrack(track)) {
- // Reset state for the new track.
- this._firstSilentSignalDate = null;
- this._audioTrack = track;
- this._eventFired = false;
- }
- }
- }
|