feat: display noise detection notification (#4952)
* feat: display noise detection notification * address code review p1 * Address code review p2 * bump lib-jitsi-meet version
This commit is contained in:
parent
a18ed3a779
commit
d2c2919aef
|
@ -76,7 +76,13 @@ var config = {
|
||||||
// Enabling this will run the lib-jitsi-meet no audio detection module which
|
// Enabling this will run the lib-jitsi-meet no audio detection module which
|
||||||
// will notify the user if the current selected microphone has no audio
|
// will notify the user if the current selected microphone has no audio
|
||||||
// input and will suggest another valid device if one is present.
|
// input and will suggest another valid device if one is present.
|
||||||
// enableNoAudioDetection: false
|
enableNoAudioDetection: true,
|
||||||
|
|
||||||
|
// Enabling this will run the lib-jitsi-meet noise detection module which will
|
||||||
|
// notify the user if there is noise, other than voice, coming from the current
|
||||||
|
// selected microphone. The purpose it to let the user know that the input could
|
||||||
|
// be potentially unpleasant for other meeting participants.
|
||||||
|
enableNoisyMicDetection: true,
|
||||||
|
|
||||||
// Start the conference in audio only mode (no video is being received nor
|
// Start the conference in audio only mode (no video is being received nor
|
||||||
// sent).
|
// sent).
|
||||||
|
|
|
@ -634,6 +634,8 @@
|
||||||
"noAudioSignalTitle": "There is no input coming from your mic!",
|
"noAudioSignalTitle": "There is no input coming from your mic!",
|
||||||
"noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider changing the device.",
|
"noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider changing the device.",
|
||||||
"noAudioSignalDescSuggestion": "If you did not purposely mute it from system settings or hardware, consider using the following device:",
|
"noAudioSignalDescSuggestion": "If you did not purposely mute it from system settings or hardware, consider using the following device:",
|
||||||
|
"noisyAudioInputTitle": "Your microphone appears to be noisy!",
|
||||||
|
"noisyAudioInputDesc": "Jitsi has detected noise coming from your microphone, please consider muting or changing the device.",
|
||||||
"openChat": "Open chat",
|
"openChat": "Open chat",
|
||||||
"pip": "Enter Picture-in-Picture mode",
|
"pip": "Enter Picture-in-Picture mode",
|
||||||
"privateMessage": "Send private message",
|
"privateMessage": "Send private message",
|
||||||
|
|
|
@ -10869,8 +10869,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib-jitsi-meet": {
|
"lib-jitsi-meet": {
|
||||||
"version": "github:jitsi/lib-jitsi-meet#8deeaf6bd2b233ab163303e42febfee87201b2d9",
|
"version": "github:jitsi/lib-jitsi-meet#e4b523d0fab83a1cf1408abbf41f5d0ca1169900",
|
||||||
"from": "github:jitsi/lib-jitsi-meet#8deeaf6bd2b233ab163303e42febfee87201b2d9",
|
"from": "github:jitsi/lib-jitsi-meet#e4b523d0fab83a1cf1408abbf41f5d0ca1169900",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@jitsi/sdp-interop": "0.1.14",
|
"@jitsi/sdp-interop": "0.1.14",
|
||||||
"@jitsi/sdp-simulcast": "0.2.2",
|
"@jitsi/sdp-simulcast": "0.2.2",
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"js-utils": "github:jitsi/js-utils#400ce825d3565019946ee75d86ed773c6f21e117",
|
"js-utils": "github:jitsi/js-utils#400ce825d3565019946ee75d86ed773c6f21e117",
|
||||||
"jsrsasign": "8.0.12",
|
"jsrsasign": "8.0.12",
|
||||||
"jwt-decode": "2.2.0",
|
"jwt-decode": "2.2.0",
|
||||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#8deeaf6bd2b233ab163303e42febfee87201b2d9",
|
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#e4b523d0fab83a1cf1408abbf41f5d0ca1169900",
|
||||||
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
||||||
"lodash": "4.17.13",
|
"lodash": "4.17.13",
|
||||||
"moment": "2.19.4",
|
"moment": "2.19.4",
|
||||||
|
|
|
@ -8,6 +8,7 @@ import '../../base/user-interaction';
|
||||||
import '../../chat';
|
import '../../chat';
|
||||||
import '../../external-api';
|
import '../../external-api';
|
||||||
import '../../no-audio-signal';
|
import '../../no-audio-signal';
|
||||||
|
import '../../noise-detection';
|
||||||
import '../../power-monitor';
|
import '../../power-monitor';
|
||||||
import '../../room-lock';
|
import '../../room-lock';
|
||||||
import '../../talk-while-muted';
|
import '../../talk-while-muted';
|
||||||
|
|
|
@ -48,13 +48,10 @@ MiddlewareRegistry.register(store => next => async action => {
|
||||||
async function _handleNoAudioSignalNotification({ dispatch, getState }, action) {
|
async function _handleNoAudioSignalNotification({ dispatch, getState }, action) {
|
||||||
|
|
||||||
const { conference } = action;
|
const { conference } = action;
|
||||||
let confAudioInputState;
|
|
||||||
|
|
||||||
conference.on(JitsiConferenceEvents.AUDIO_INPUT_STATE_CHANGE, hasAudioInput => {
|
conference.on(JitsiConferenceEvents.AUDIO_INPUT_STATE_CHANGE, hasAudioInput => {
|
||||||
const { noAudioSignalNotificationUid } = getState()['features/no-audio-signal'];
|
const { noAudioSignalNotificationUid } = getState()['features/no-audio-signal'];
|
||||||
|
|
||||||
confAudioInputState = hasAudioInput;
|
|
||||||
|
|
||||||
// In case the notification is displayed but the conference detected audio input signal we hide it.
|
// In case the notification is displayed but the conference detected audio input signal we hide it.
|
||||||
if (noAudioSignalNotificationUid && hasAudioInput) {
|
if (noAudioSignalNotificationUid && hasAudioInput) {
|
||||||
dispatch(hideNotification(noAudioSignalNotificationUid));
|
dispatch(hideNotification(noAudioSignalNotificationUid));
|
||||||
|
@ -71,17 +68,8 @@ async function _handleNoAudioSignalNotification({ dispatch, getState }, action)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force the flag to false in case AUDIO_INPUT_STATE_CHANGE is received after the notification is displayed,
|
|
||||||
// possibly preventing the notification from displaying because of an outdated state.
|
|
||||||
confAudioInputState = false;
|
|
||||||
|
|
||||||
|
|
||||||
const activeDevice = await JitsiMeetJS.getActiveAudioDevice();
|
const activeDevice = await JitsiMeetJS.getActiveAudioDevice();
|
||||||
|
|
||||||
if (confAudioInputState) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case there is a previous notification displayed just hide it.
|
// In case there is a previous notification displayed just hide it.
|
||||||
const { noAudioSignalNotificationUid } = getState()['features/no-audio-signal'];
|
const { noAudioSignalNotificationUid } = getState()['features/no-audio-signal'];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/**
|
||||||
|
* The type of Redux action which sets the pending notification UID
|
||||||
|
* to use it when hiding the notification is necessary, or unset it when
|
||||||
|
* undefined (or no param) is passed.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID
|
||||||
|
* uid: ?number
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID = 'SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID';
|
|
@ -0,0 +1,21 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID } from './actionTypes';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets UID of the the pending notification to use it when hiding
|
||||||
|
* the notification is necessary, or unset it when undefined (or no param) is
|
||||||
|
* passed.
|
||||||
|
*
|
||||||
|
* @param {?number} uid - The UID of the notification.
|
||||||
|
* @returns {{
|
||||||
|
* type: SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID,
|
||||||
|
* uid: number
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function setNoisyAudioInputNotificationUid(uid: ?number) {
|
||||||
|
return {
|
||||||
|
type: SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID,
|
||||||
|
uid
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* The identifier of the sound to be played when we display a you are noisy notification.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const NOISY_AUDIO_INPUT_SOUND_ID = 'NOISY_AUDIO_INPUT_SOUND_ID';
|
|
@ -0,0 +1,4 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import './middleware';
|
||||||
|
import './reducer';
|
|
@ -0,0 +1,57 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
|
||||||
|
import { CONFERENCE_JOINED } from '../base/conference';
|
||||||
|
import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
|
||||||
|
import { MiddlewareRegistry } from '../base/redux';
|
||||||
|
import { playSound, registerSound, unregisterSound } from '../base/sounds';
|
||||||
|
import { hideNotification, showNotification } from '../notifications';
|
||||||
|
|
||||||
|
import { setNoisyAudioInputNotificationUid } from './actions';
|
||||||
|
import { NOISY_AUDIO_INPUT_SOUND_ID } from './constants';
|
||||||
|
import { NOISY_AUDIO_INPUT_SOUND_FILE } from './sounds';
|
||||||
|
|
||||||
|
MiddlewareRegistry.register(store => next => action => {
|
||||||
|
const result = next(action);
|
||||||
|
|
||||||
|
switch (action.type) {
|
||||||
|
case APP_WILL_MOUNT:
|
||||||
|
store.dispatch(registerSound(NOISY_AUDIO_INPUT_SOUND_ID, NOISY_AUDIO_INPUT_SOUND_FILE));
|
||||||
|
break;
|
||||||
|
case APP_WILL_UNMOUNT:
|
||||||
|
store.dispatch(unregisterSound(NOISY_AUDIO_INPUT_SOUND_ID));
|
||||||
|
break;
|
||||||
|
case CONFERENCE_JOINED: {
|
||||||
|
const { dispatch, getState } = store;
|
||||||
|
const { conference } = action;
|
||||||
|
|
||||||
|
conference.on(
|
||||||
|
JitsiConferenceEvents.TRACK_MUTE_CHANGED,
|
||||||
|
track => {
|
||||||
|
const { noisyAudioInputNotificationUid } = getState()['features/noise-detection'];
|
||||||
|
|
||||||
|
// Hide the notification in case the user mutes the microphone
|
||||||
|
if (noisyAudioInputNotificationUid && track.isAudioTrack() && track.isLocal() && track.isMuted()) {
|
||||||
|
dispatch(hideNotification(noisyAudioInputNotificationUid));
|
||||||
|
dispatch(setNoisyAudioInputNotificationUid());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
conference.on(
|
||||||
|
JitsiConferenceEvents.NOISY_MIC, () => {
|
||||||
|
const notification = showNotification({
|
||||||
|
titleKey: 'toolbar.noisyAudioInputTitle',
|
||||||
|
descriptionKey: 'toolbar.noisyAudioInputDesc'
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch(notification);
|
||||||
|
dispatch(playSound(NOISY_AUDIO_INPUT_SOUND_ID));
|
||||||
|
|
||||||
|
// we store the last notification id so we can hide it if the mic is muted
|
||||||
|
dispatch(setNoisyAudioInputNotificationUid(notification.uid));
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
|
@ -0,0 +1,17 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { ReducerRegistry, set } from '../base/redux';
|
||||||
|
|
||||||
|
import { SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID } from './actionTypes';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the redux actions of noise detection feature
|
||||||
|
*/
|
||||||
|
ReducerRegistry.register('features/noise-detection', (state = {}, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID:
|
||||||
|
return set(state, 'noisyAudioInputNotificationUid', action.uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
});
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* The file used for the noisy audio input notification.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const NOISY_AUDIO_INPUT_SOUND_FILE = 'noisyAudioInput.mp3';
|
Binary file not shown.
Loading…
Reference in New Issue