You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NoAudioSignalDetection.js 3.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
  2. // We wait a certain time interval for constant silence input from the current device to account for
  3. // potential abnormalities and for a better use experience i.e. don't generate event the instant
  4. // an audio track is added to the tcr.
  5. // Potential improvement - add this as a configurable parameter.
  6. const SILENCE_PERIOD_MS = 4000;
  7. /**
  8. * Detect if there is no audio input on the current TraceAblePeerConnection selected track. The no audio
  9. * state must be constant for a configured amount of time in order for the event to be triggered.
  10. */
  11. export default class NoAudioSignalDetection {
  12. /**
  13. * @param conference the JitsiConference instance that created us.
  14. * @param callback callback that notifies the conference when no audio event is triggered
  15. * @constructor
  16. */
  17. constructor(conference, callback) {
  18. this._conference = conference;
  19. this._callback = callback;
  20. this._timeoutTrigger = null;
  21. conference.statistics.addAudioLevelListener(this._audioLevel.bind(this));
  22. conference.on(JitsiConferenceEvents.TRACK_ADDED, this._trackAdded.bind(this));
  23. }
  24. /**
  25. * Clear the timeout state.
  26. */
  27. _clearTriggerTimeout() {
  28. clearTimeout(this._timeoutTrigger);
  29. this._timeoutTrigger = null;
  30. }
  31. /**
  32. * Receives audio level events for all send and receive streams on the current TraceablePeerConnection.
  33. *
  34. * @param {TraceablePeerConnection} tpc - TraceablePeerConnection of the owning conference.
  35. * @param {number} ssrc - The synchronization source identifier (SSRC) of the endpoint/participant/stream
  36. * being reported.
  37. * @param {number} audioLevel - The audio level of the ssrc.
  38. * @param {boolean} isLocal - true for local/send streams or false for remote/receive streams.
  39. */
  40. _audioLevel(tpc, ssrc, audioLevel, isLocal) {
  41. // We are interested in the local audio stream if the event was not triggered on this device.
  42. if (!isLocal || !this._audioTrack || this._eventFired) {
  43. return;
  44. }
  45. // Get currently active local tracks from the TraceablePeerConnection
  46. const localSSRCs = tpc.localSSRCs.get(this._audioTrack.rtcId);
  47. // Check that currently selected audio stream has ssrc in the TraceablePeerConnection
  48. if (!localSSRCs) {
  49. return;
  50. }
  51. // Only target the current active track in the tpc. For some reason audio levels for previous
  52. // devices are also picked up from the PeerConnection so we filter them out.
  53. const isCurrentTrack = localSSRCs.ssrcs.includes(ssrc);
  54. if (!isCurrentTrack) {
  55. return;
  56. }
  57. if (audioLevel === 0 && !this._timeoutTrigger) {
  58. this._timeoutTrigger = setTimeout(() => {
  59. this._eventFired = true;
  60. this._callback();
  61. }, SILENCE_PERIOD_MS);
  62. } else if (audioLevel !== 0 && this._timeoutTrigger) {
  63. this._clearTriggerTimeout();
  64. }
  65. }
  66. /**
  67. * Notifies NoAudioSignalDetection that a JitsiTrack was added to the associated JitsiConference.
  68. * Only take into account local audio tracks.
  69. *
  70. * @param {JitsiTrack} track - The added JitsiTrack.
  71. */
  72. _trackAdded(track) {
  73. if (track.isLocalAudioTrack()) {
  74. // Reset state for the new track.
  75. this._audioTrack = track;
  76. this._eventFired = false;
  77. this._clearTriggerTimeout();
  78. }
  79. }
  80. }