Преглед на файлове

feat: display noise detection notification (#4952)

* feat: display noise detection notification

* address code review p1

* Address code review p2

* bump lib-jitsi-meet version
master
Andrei Gavrilescu преди 4 години
родител
ревизия
d2c2919aef

+ 7
- 1
config.js Целия файл

@@ -76,7 +76,13 @@ var config = {
76 76
     // Enabling this will run the lib-jitsi-meet no audio detection module which
77 77
     // will notify the user if the current selected microphone has no audio
78 78
     // input and will suggest another valid device if one is present.
79
-    // enableNoAudioDetection: false
79
+    enableNoAudioDetection: true,
80
+
81
+    // Enabling this will run the lib-jitsi-meet noise detection module which will
82
+    // notify the user if there is noise, other than voice, coming from the current
83
+    // selected microphone. The purpose it to let the user know that the input could
84
+    // be potentially unpleasant for other meeting participants.
85
+    enableNoisyMicDetection: true,
80 86
 
81 87
     // Start the conference in audio only mode (no video is being received nor
82 88
     // sent).

+ 2
- 0
lang/main.json Целия файл

@@ -634,6 +634,8 @@
634 634
         "noAudioSignalTitle": "There is no input coming from your mic!",
635 635
         "noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider changing the device.",
636 636
         "noAudioSignalDescSuggestion": "If you did not purposely mute it from system settings or hardware, consider using the following device:",
637
+        "noisyAudioInputTitle": "Your microphone appears to be noisy!",
638
+        "noisyAudioInputDesc": "Jitsi has detected noise coming from your microphone, please consider muting or changing the device.",
637 639
         "openChat": "Open chat",
638 640
         "pip": "Enter Picture-in-Picture mode",
639 641
         "privateMessage": "Send private message",

+ 2
- 2
package-lock.json Целия файл

@@ -10869,8 +10869,8 @@
10869 10869
       }
10870 10870
     },
10871 10871
     "lib-jitsi-meet": {
10872
-      "version": "github:jitsi/lib-jitsi-meet#8deeaf6bd2b233ab163303e42febfee87201b2d9",
10873
-      "from": "github:jitsi/lib-jitsi-meet#8deeaf6bd2b233ab163303e42febfee87201b2d9",
10872
+      "version": "github:jitsi/lib-jitsi-meet#e4b523d0fab83a1cf1408abbf41f5d0ca1169900",
10873
+      "from": "github:jitsi/lib-jitsi-meet#e4b523d0fab83a1cf1408abbf41f5d0ca1169900",
10874 10874
       "requires": {
10875 10875
         "@jitsi/sdp-interop": "0.1.14",
10876 10876
         "@jitsi/sdp-simulcast": "0.2.2",

+ 1
- 1
package.json Целия файл

@@ -56,7 +56,7 @@
56 56
     "js-utils": "github:jitsi/js-utils#400ce825d3565019946ee75d86ed773c6f21e117",
57 57
     "jsrsasign": "8.0.12",
58 58
     "jwt-decode": "2.2.0",
59
-    "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#8deeaf6bd2b233ab163303e42febfee87201b2d9",
59
+    "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#e4b523d0fab83a1cf1408abbf41f5d0ca1169900",
60 60
     "libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
61 61
     "lodash": "4.17.13",
62 62
     "moment": "2.19.4",

+ 1
- 0
react/features/app/components/App.web.js Целия файл

@@ -8,6 +8,7 @@ import '../../base/user-interaction';
8 8
 import '../../chat';
9 9
 import '../../external-api';
10 10
 import '../../no-audio-signal';
11
+import '../../noise-detection';
11 12
 import '../../power-monitor';
12 13
 import '../../room-lock';
13 14
 import '../../talk-while-muted';

+ 0
- 12
react/features/no-audio-signal/middleware.js Целия файл

@@ -48,13 +48,10 @@ MiddlewareRegistry.register(store => next => async action => {
48 48
 async function _handleNoAudioSignalNotification({ dispatch, getState }, action) {
49 49
 
50 50
     const { conference } = action;
51
-    let confAudioInputState;
52 51
 
53 52
     conference.on(JitsiConferenceEvents.AUDIO_INPUT_STATE_CHANGE, hasAudioInput => {
54 53
         const { noAudioSignalNotificationUid } = getState()['features/no-audio-signal'];
55 54
 
56
-        confAudioInputState = hasAudioInput;
57
-
58 55
         // In case the notification is displayed but the conference detected audio input signal we hide it.
59 56
         if (noAudioSignalNotificationUid && hasAudioInput) {
60 57
             dispatch(hideNotification(noAudioSignalNotificationUid));
@@ -71,17 +68,8 @@ async function _handleNoAudioSignalNotification({ dispatch, getState }, action)
71 68
             return;
72 69
         }
73 70
 
74
-        // Force the flag to false in case AUDIO_INPUT_STATE_CHANGE is received after the notification is displayed,
75
-        // possibly preventing the notification from displaying because of an outdated state.
76
-        confAudioInputState = false;
77
-
78
-
79 71
         const activeDevice = await JitsiMeetJS.getActiveAudioDevice();
80 72
 
81
-        if (confAudioInputState) {
82
-            return;
83
-        }
84
-
85 73
         // In case there is a previous notification displayed just hide it.
86 74
         const { noAudioSignalNotificationUid } = getState()['features/no-audio-signal'];
87 75
 

+ 11
- 0
react/features/noise-detection/actionTypes.js Целия файл

@@ -0,0 +1,11 @@
1
+/**
2
+ * The type of Redux action which sets the pending notification UID
3
+ * to use it when hiding the notification is necessary, or unset it when
4
+ * undefined (or no param) is passed.
5
+ *
6
+ * {
7
+ *     type: SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID
8
+ *     uid: ?number
9
+ * }
10
+ */
11
+export const SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID = 'SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID';

+ 21
- 0
react/features/noise-detection/actions.js Целия файл

@@ -0,0 +1,21 @@
1
+// @flow
2
+
3
+import { SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID } from './actionTypes';
4
+
5
+/**
6
+ * Sets UID of the the pending notification to use it when hiding
7
+ * the notification is necessary, or unset it when undefined (or no param) is
8
+ * passed.
9
+ *
10
+ * @param {?number} uid - The UID of the notification.
11
+ * @returns {{
12
+ *     type: SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID,
13
+ *     uid: number
14
+ * }}
15
+ */
16
+export function setNoisyAudioInputNotificationUid(uid: ?number) {
17
+    return {
18
+        type: SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID,
19
+        uid
20
+    };
21
+}

+ 6
- 0
react/features/noise-detection/constants.js Целия файл

@@ -0,0 +1,6 @@
1
+/**
2
+ * The identifier of the sound to be played when we display a you are noisy notification.
3
+ *
4
+ * @type {string}
5
+ */
6
+export const NOISY_AUDIO_INPUT_SOUND_ID = 'NOISY_AUDIO_INPUT_SOUND_ID';

+ 4
- 0
react/features/noise-detection/index.js Целия файл

@@ -0,0 +1,4 @@
1
+// @flow
2
+
3
+import './middleware';
4
+import './reducer';

+ 57
- 0
react/features/noise-detection/middleware.js Целия файл

@@ -0,0 +1,57 @@
1
+// @flow
2
+
3
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
4
+import { CONFERENCE_JOINED } from '../base/conference';
5
+import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
6
+import { MiddlewareRegistry } from '../base/redux';
7
+import { playSound, registerSound, unregisterSound } from '../base/sounds';
8
+import { hideNotification, showNotification } from '../notifications';
9
+
10
+import { setNoisyAudioInputNotificationUid } from './actions';
11
+import { NOISY_AUDIO_INPUT_SOUND_ID } from './constants';
12
+import { NOISY_AUDIO_INPUT_SOUND_FILE } from './sounds';
13
+
14
+MiddlewareRegistry.register(store => next => action => {
15
+    const result = next(action);
16
+
17
+    switch (action.type) {
18
+    case APP_WILL_MOUNT:
19
+        store.dispatch(registerSound(NOISY_AUDIO_INPUT_SOUND_ID, NOISY_AUDIO_INPUT_SOUND_FILE));
20
+        break;
21
+    case APP_WILL_UNMOUNT:
22
+        store.dispatch(unregisterSound(NOISY_AUDIO_INPUT_SOUND_ID));
23
+        break;
24
+    case CONFERENCE_JOINED: {
25
+        const { dispatch, getState } = store;
26
+        const { conference } = action;
27
+
28
+        conference.on(
29
+            JitsiConferenceEvents.TRACK_MUTE_CHANGED,
30
+            track => {
31
+                const { noisyAudioInputNotificationUid } = getState()['features/noise-detection'];
32
+
33
+                // Hide the notification in case the user mutes the microphone
34
+                if (noisyAudioInputNotificationUid && track.isAudioTrack() && track.isLocal() && track.isMuted()) {
35
+                    dispatch(hideNotification(noisyAudioInputNotificationUid));
36
+                    dispatch(setNoisyAudioInputNotificationUid());
37
+                }
38
+            });
39
+        conference.on(
40
+            JitsiConferenceEvents.NOISY_MIC, () => {
41
+                const notification = showNotification({
42
+                    titleKey: 'toolbar.noisyAudioInputTitle',
43
+                    descriptionKey: 'toolbar.noisyAudioInputDesc'
44
+                });
45
+
46
+                dispatch(notification);
47
+                dispatch(playSound(NOISY_AUDIO_INPUT_SOUND_ID));
48
+
49
+                // we store the last notification id so we can hide it if the mic is muted
50
+                dispatch(setNoisyAudioInputNotificationUid(notification.uid));
51
+            });
52
+        break;
53
+    }
54
+    }
55
+
56
+    return result;
57
+});

+ 17
- 0
react/features/noise-detection/reducer.js Целия файл

@@ -0,0 +1,17 @@
1
+// @flow
2
+
3
+import { ReducerRegistry, set } from '../base/redux';
4
+
5
+import { SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID } from './actionTypes';
6
+
7
+/**
8
+ * Reduces the redux actions of noise detection feature
9
+ */
10
+ReducerRegistry.register('features/noise-detection', (state = {}, action) => {
11
+    switch (action.type) {
12
+    case SET_NOISY_AUDIO_INPUT_NOTIFICATION_UID:
13
+        return set(state, 'noisyAudioInputNotificationUid', action.uid);
14
+    }
15
+
16
+    return state;
17
+});

+ 6
- 0
react/features/noise-detection/sounds.js Целия файл

@@ -0,0 +1,6 @@
1
+/**
2
+ * The file used for the noisy audio input notification.
3
+ *
4
+ * @type {string}
5
+ */
6
+export const NOISY_AUDIO_INPUT_SOUND_FILE = 'noisyAudioInput.mp3';

Двоични данни
sounds/noisyAudioInput.mp3 Целия файл


Loading…
Отказ
Запис