From 534e8625730bf3fc4e839c64983ab509f6777179 Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Thu, 14 May 2020 04:02:52 +0200 Subject: [PATCH 1/6] First working noiseThreshold setting + voiceActivatedUnmute --- app/public/config/config.example.js | 15 +- app/src/RoomClient.js | 47 +++-- app/src/actions/settingsActions.js | 12 ++ app/src/components/Containers/Volume.js | 9 +- app/src/components/Settings/MediaSettings.js | 173 +++++++++++++------ app/src/reducers/peerVolumes.js | 5 +- app/src/reducers/settings.js | 50 ++++-- 7 files changed, 209 insertions(+), 102 deletions(-) diff --git a/app/public/config/config.example.js b/app/public/config/config.example.js index b591c16..9ee5e37 100644 --- a/app/public/config/config.example.js +++ b/app/public/config/config.example.js @@ -44,13 +44,14 @@ var config = }, defaultAudio : { - sampleRate : 48000, - channelCount : 1, - volume : 1.0, - autoGainControl : true, - echoCancellation : true, - noiseSuppression : true, - sampleSize : 16 + sampleRate : 48000, + channelCount : 1, + volume : 1.0, + autoGainControl : true, + echoCancellation : true, + noiseSuppression : true, + voiceActivityMute : false, + sampleSize : 16 }, background : 'images/background.jpg', defaultLayout : 'democratic', // democratic, filmstrip diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index df276ae..9fece61 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -980,21 +980,11 @@ export default class RoomClient if (!this._harkStream.getAudioTracks()[0]) throw new Error('getMicStream():something went wrong with hark'); - this._hark = hark(this._harkStream, { play: false }); + this._hark = hark(this._harkStream, { play: false, interval: 5 }); // eslint-disable-next-line no-unused-vars - this._hark.on('volume_change', (dBs, threshold) => + this._hark.on('volume_change', (volume, threshold) => { - // The exact formula to convert from dBs (-100..0) to linear (0..1) is: - // Math.pow(10, dBs / 20) - // However it does not produce a visually useful output, so let exagerate - // it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to - // minimize component renderings. - let volume = Math.round(Math.pow(10, dBs / 85) * 10); - - if (volume === 1) - volume = 0; - volume = Math.round(volume); if (this._micProducer && volume !== this._micProducer.volume) @@ -1004,13 +994,23 @@ export default class RoomClient store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume)); } }); - this._hark.on('speaking', function() + this._hark.on('speaking', () => { + this._hark.setInterval(300); store.dispatch(meActions.setIsSpeaking(true)); + if (store.getState().settings.voiceActivatedUnmute && this._micProducer.paused) + { + this.unmuteMic(); + } }); - this._hark.on('stopped_speaking', function() + this._hark.on('stopped_speaking', () => { store.dispatch(meActions.setIsSpeaking(false)); + if (store.getState().settings.voiceActivatedUnmute && !this._micProducer.paused) + { + this.muteMic(); + } + this._hark.setInterval(5); }); } @@ -1856,23 +1856,12 @@ export default class RoomClient producerPaused } = request.data; - let codecOptions; - - if (kind === 'audio') - { - codecOptions = - { - opusStereo : 1 - }; - } - const consumer = await this._recvTransport.consume( { id, producerId, kind, rtpParameters, - codecOptions, appData : { ...appData, peerId } // Trick. }); @@ -3760,6 +3749,14 @@ export default class RoomClient store.dispatch(meActions.setWebcamInProgress(false)); } + async _setNoiseThreshold(threshold) + { + logger.debug('_setNoiseThreshold:%s', threshold); + this._hark.setThreshold(threshold); + store.dispatch( + settingsActions.setNoiseThreshold(threshold)); + } + async _updateAudioDevices() { logger.debug('_updateAudioDevices()'); diff --git a/app/src/actions/settingsActions.js b/app/src/actions/settingsActions.js index 63c12bf..f168ac3 100644 --- a/app/src/actions/settingsActions.js +++ b/app/src/actions/settingsActions.js @@ -61,6 +61,18 @@ export const setNoiseSuppression = (noiseSuppression) => payload : { noiseSuppression } }); +export const setVoiceActivatedUnmute = (voiceActivatedUnmute) => + ({ + type: 'SET_VOICE_ACTIVATED_UNMUTE', + payload: { voiceActivatedUnmute } + }); + +export const setNoiseThreshold = (noiseThreshold) => + ({ + type: 'SET_NOISE_THRESHOLD', + payload: { noiseThreshold } + }); + export const setDefaultAudio = (audio) => ({ type : 'SET_DEFAULT_AUDIO', diff --git a/app/src/components/Containers/Volume.js b/app/src/components/Containers/Volume.js index 3c13a39..14d9d5d 100644 --- a/app/src/components/Containers/Volume.js +++ b/app/src/components/Containers/Volume.js @@ -149,9 +149,16 @@ const makeMapStateToProps = (initialState, props) => { const mapStateToProps = (state) => { + if (state.peerVolumes[props.id]>state.settings.noiseThreshold) + { return { - volume : state.peerVolumes[props.id] + volume : Math.round((state.peerVolumes[props.id]+100) / 10) }; + } + else + { + return { volume: 0 }; + } }; return mapStateToProps; diff --git a/app/src/components/Settings/MediaSettings.js b/app/src/components/Settings/MediaSettings.js index d215181..334b93f 100644 --- a/app/src/components/Settings/MediaSettings.js +++ b/app/src/components/Settings/MediaSettings.js @@ -6,31 +6,66 @@ import { withRoomContext } from '../../RoomContext'; import * as settingsActions from '../../actions/settingsActions'; import PropTypes from 'prop-types'; import { useIntl, FormattedMessage } from 'react-intl'; +import classnames from 'classnames'; import MenuItem from '@material-ui/core/MenuItem'; import FormHelperText from '@material-ui/core/FormHelperText'; import FormControl from '@material-ui/core/FormControl'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Select from '@material-ui/core/Select'; import Checkbox from '@material-ui/core/Checkbox'; +import Slider from '@material-ui/core/Slider'; +import Typography from '@material-ui/core/Typography'; -const styles = (theme) => - ({ - setting : +const NoiseSlider = withStyles( + { + root : { - padding : theme.spacing(2) + color : '#3880ff', + height : 2, + padding : '15px 0' }, - formControl : - { - display : 'flex' + track : { + height : 2 + }, + rail : { + height : 2, + opacity : 0.2, + }, + mark : { + backgroundColor : '#bfbfbf', + height : 10, + width : 3, + marginTop : -3 + }, + markActive : { + opacity : 1, + backgroundColor : 'currentColor' } - }); + })(Slider); + +const styles = (theme) => ({ + setting : + { + padding : theme.spacing(2) + }, + margin : + { + height : theme.spacing(3), + }, + formControl : + { + display : 'flex' + } +}); const MediaSettings = ({ setEchoCancellation, setAutoGainControl, setNoiseSuppression, + setVoiceActivatedUnmute, roomClient, me, + volume, settings, classes }) => @@ -135,6 +170,32 @@ const MediaSettings = ({ } + + + + + +
@@ -148,7 +209,7 @@ const MediaSettings = ({ displayEmpty name={intl.formatMessage({ id : 'settings.audio', - defaultMessage : 'Audio device' + defaultMessage : 'Audio input device' })} autoWidth className={classes.selectEmpty} @@ -165,12 +226,12 @@ const MediaSettings = ({ { audioDevices.length > 0 ? intl.formatMessage({ id : 'settings.selectAudio', - defaultMessage : 'Select audio device' + defaultMessage : 'Select audio input device' }) : intl.formatMessage({ id : 'settings.cantSelectAudio', - defaultMessage : 'Unable to select audio device' + defaultMessage : 'Unable to select audio input device' }) } @@ -225,34 +286,6 @@ const MediaSettings = ({ }
- - - - - - + + { + setVoiceActivatedUnmute(event.target.checked); + }} + />} + label={intl.formatMessage({ + id : 'settings.voiceActivatedUnmute', + defaultMessage : 'Voice activated unmute' + })} + /> +
+ + { + intl.formatMessage({ + id : 'settings.noiseThreshold', + defaultMessage : 'Noise threshold' + }) + } + + { + roomClient._setNoiseThreshold(value); + }} + marks={[{ value: volume, label: 'level' }]} valueLabelDisplay='on' + /> +
); @@ -305,27 +373,31 @@ const MediaSettings = ({ MediaSettings.propTypes = { - roomClient : PropTypes.any.isRequired, - setEchoCancellation : PropTypes.func.isRequired, - setAutoGainControl : PropTypes.func.isRequired, - setNoiseSuppression : PropTypes.func.isRequired, - me : appPropTypes.Me.isRequired, - settings : PropTypes.object.isRequired, - classes : PropTypes.object.isRequired + roomClient : PropTypes.any.isRequired, + setEchoCancellation : PropTypes.func.isRequired, + setAutoGainControl : PropTypes.func.isRequired, + setNoiseSuppression : PropTypes.func.isRequired, + setVoiceActivatedUnmute : PropTypes.func.isRequired, + me : appPropTypes.Me.isRequired, + volume : PropTypes.number, + settings : PropTypes.object.isRequired, + classes : PropTypes.object.isRequired }; const mapStateToProps = (state) => { return { me : state.me, + volume : state.peerVolumes[state.me.id], settings : state.settings }; }; const mapDispatchToProps = { - setEchoCancellation : settingsActions.setEchoCancellation, - setAutoGainControl : settingsActions.toggleAutoGainControl, - setNoiseSuppression : settingsActions.toggleNoiseSuppression + setEchoCancellation : settingsActions.setEchoCancellation, + setAutoGainControl : settingsActions.toggleAutoGainControl, + setNoiseSuppression : settingsActions.toggleNoiseSuppression, + setVoiceActivatedUnmute : settingsActions.setVoiceActivatedUnmute }; export default withRoomContext(connect( @@ -337,7 +409,8 @@ export default withRoomContext(connect( { return ( prev.me === next.me && - prev.settings === next.settings + prev.settings === next.settings && + prev.peerVolumes[prev.me.id] === next[next.me.id] ); } } diff --git a/app/src/reducers/peerVolumes.js b/app/src/reducers/peerVolumes.js index fafe739..cd5032f 100644 --- a/app/src/reducers/peerVolumes.js +++ b/app/src/reducers/peerVolumes.js @@ -31,9 +31,10 @@ const peerVolumes = (state = initialState, action) => case 'SET_PEER_VOLUME': { - const { peerId, volume } = action.payload; + const { peerId } = action.payload; + const dBs = action.payload.volume; - return { ...state, [peerId]: volume }; + return { ...state, [peerId]: Math.round(dBs) }; } default: diff --git a/app/src/reducers/settings.js b/app/src/reducers/settings.js index 7186fdc..cee3d88 100644 --- a/app/src/reducers/settings.js +++ b/app/src/reducers/settings.js @@ -1,23 +1,25 @@ const initialState = { - displayName : 'Guest', - selectedWebcam : null, - selectedAudioDevice : null, - advancedMode : false, - sampleRate : 48000, - channelCount : 1, - volume : 1.0, - autoGainControl : true, - echoCancellation : true, - noiseSuppression : true, - sampleSize : 16, + displayName : 'Guest', + selectedWebcam : null, + selectedAudioDevice : null, + advancedMode : false, + sampleRate : 48000, + channelCount : 1, + volume : 1.0, + autoGainControl : false, + echoCancellation : true, + noiseSuppression : true, + voiceActivatedUnmute : false, + noiseThreshold : -50, + sampleSize : 16, // low, medium, high, veryhigh, ultra - resolution : window.config.defaultResolution || 'medium', - lastN : 4, - permanentTopBar : true, - hiddenControls : false, - showNotifications : true, - notificationSounds : true, + resolution : window.config.defaultResolution || 'medium', + lastN : 4, + permanentTopBar : true, + hiddenControls : false, + showNotifications : true, + notificationSounds : true, ...window.config.defaultAudio }; @@ -96,6 +98,20 @@ const settings = (state = initialState, action) => return { ...state, noiseSuppression }; } + case 'SET_VOICE_ACTIVATED_UNMUTE': + { + const { voiceActivatedUnmute } = action.payload; + + return { ...state, voiceActivatedUnmute }; + } + + case 'SET_NOISE_THRESHOLD': + { + const { noiseThreshold } = action.payload; + + return { ...state, noiseThreshold }; + } + case 'SET_DEFAULT_AUDIO': { const { audio } = action.payload; From 46174b414ff2990ce2ef65c8461cf8b1ae2852cc Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Thu, 14 May 2020 04:04:11 +0200 Subject: [PATCH 2/6] Fix small audiobar to middle --- app/src/components/Containers/Volume.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/components/Containers/Volume.js b/app/src/components/Containers/Volume.js index 14d9d5d..81a050b 100644 --- a/app/src/components/Containers/Volume.js +++ b/app/src/components/Containers/Volume.js @@ -94,17 +94,17 @@ const styles = () => smallBar : { flex : '0 0 auto', - margin : '0.3rem', backgroundSize : '75%', backgroundRepeat : 'no-repeat', backgroundColor : 'rgba(0, 0, 0, 1)', cursor : 'pointer', transitionProperty : 'opacity, background-color', width : 3, - borderRadius : 6, + borderRadius : 2, transitionDuration : '0.25s', position : 'absolute', - bottom : 0, + top : '50%', + transform : 'translateY(-50%)', '&.level0' : { height: 0 }, '&.level1' : { height: '0.2vh' }, '&.level2' : { height: '0.4vh' }, @@ -151,9 +151,9 @@ const makeMapStateToProps = (initialState, props) => { if (state.peerVolumes[props.id]>state.settings.noiseThreshold) { - return { + return { volume : Math.round((state.peerVolumes[props.id]+100) / 10) - }; + }; } else { From 75912c71c212ad58ffce9e164949d43d81c9c47f Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Thu, 14 May 2020 22:39:02 +0200 Subject: [PATCH 3/6] ptt bar styles: same color as FAB-mute, z-index on top of drawer --- app/src/components/Containers/Me.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/components/Containers/Me.js b/app/src/components/Containers/Me.js index 8d45473..b4de8b4 100644 --- a/app/src/components/Containers/Me.js +++ b/app/src/components/Containers/Me.js @@ -137,10 +137,10 @@ const styles = (theme) => transform : 'translate(-50%, 0%)', color : 'rgba(255, 255, 255, 0.7)', fontSize : '1.3em', - backgroundColor : 'rgba(255, 0, 0, 0.9)', + backgroundColor : 'rgba(245, 0, 87, 0.70)', margin : '4px', padding : theme.spacing(2), - zIndex : 31, + zIndex : 1200, borderRadius : '20px', textAlign : 'center', opacity : 0, From 6331bb18b4b3124ac8b805dfdf167d0c65dce05a Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Mon, 18 May 2020 23:38:17 +0200 Subject: [PATCH 4/6] mic indicator for autoMute with noiseThreshold --- app/src/RoomClient.js | 22 +++++++++++---- app/src/actions/meActions.js | 6 ++++ app/src/components/Containers/Me.js | 43 +++++++++++++++++++++++++---- app/src/reducers/me.js | 10 ++++++- app/src/reducers/peerVolumes.js | 2 +- 5 files changed, 70 insertions(+), 13 deletions(-) diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index 9527d9a..7cfd626 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -997,7 +997,11 @@ export default class RoomClient if (!this._harkStream.getAudioTracks()[0]) throw new Error('getMicStream():something went wrong with hark'); - this._hark = hark(this._harkStream, { play: false, interval: 5 }); + this._hark = hark(this._harkStream, + { + play : false, + interval : 5, + threshold : store.getState().settings.noiseThreshold }); // eslint-disable-next-line no-unused-vars this._hark.on('volume_change', (volume, threshold) => @@ -1013,19 +1017,25 @@ export default class RoomClient }); this._hark.on('speaking', () => { - this._hark.setInterval(300); + this._hark.setInterval(5); store.dispatch(meActions.setIsSpeaking(true)); - if (store.getState().settings.voiceActivatedUnmute && this._micProducer.paused) + if (store.getState().settings.voiceActivatedUnmute && + this._micProducer && + this._micProducer.paused) { - this.unmuteMic(); + this._micProducer.resume(); + store.dispatch(meActions.setAutoMuted(false)); } }); this._hark.on('stopped_speaking', () => { store.dispatch(meActions.setIsSpeaking(false)); - if (store.getState().settings.voiceActivatedUnmute && !this._micProducer.paused) + if (store.getState().settings.voiceActivatedUnmute && + this._micProducer && + !this._micProducer.paused) { - this.muteMic(); + this._micProducer.pause(); + store.dispatch(meActions.setAutoMuted(true)); } this._hark.setInterval(5); }); diff --git a/app/src/actions/meActions.js b/app/src/actions/meActions.js index 7fb34ea..be7c1ee 100644 --- a/app/src/actions/meActions.js +++ b/app/src/actions/meActions.js @@ -110,3 +110,9 @@ export const setIsSpeaking = (flag) => type : 'SET_IS_SPEAKING', payload : { flag } }); + +export const setAutoMuted = (flag) => + ({ + type : 'SET_AUTO_MUTED', + payload : { flag } + }); diff --git a/app/src/components/Containers/Me.js b/app/src/components/Containers/Me.js index b4de8b4..0ec1142 100644 --- a/app/src/components/Containers/Me.js +++ b/app/src/components/Containers/Me.js @@ -175,6 +175,7 @@ const Me = (props) => screenProducer, extraVideoProducers, canShareScreen, + noiseVolume, classes } = props; @@ -408,7 +409,12 @@ const Me = (props) => })} className={classes.smallContainer} disabled={!me.canSendMic || me.audioInProgress} - color={micState === 'on' ? 'primary' : 'secondary'} + color={ + micState === 'on' ? + settings.voiceActivatedUnmute && !me.isAutoMuted ? + 'primary' + : 'default' + : 'secondary'} size='small' onClick={() => { @@ -421,7 +427,10 @@ const Me = (props) => }} > { micState === 'on' ? - + : } @@ -436,7 +445,10 @@ const Me = (props) => })} className={classes.fab} disabled={!me.canSendMic || me.audioInProgress} - color={micState === 'on' ? 'default' : 'secondary'} + color={micState === 'on' ? + settings.voiceActivatedUnmute && !me.isAutoMuted? 'primary' + : 'default' + : 'secondary'} size='large' onClick={() => { @@ -449,7 +461,11 @@ const Me = (props) => }} > { micState === 'on' ? - + : } @@ -832,6 +848,7 @@ Me.propTypes = style : PropTypes.object, smallContainer : PropTypes.bool, canShareScreen : PropTypes.bool.isRequired, + noiseVolume : PropTypes.number, classes : PropTypes.object.isRequired, theme : PropTypes.object.isRequired }; @@ -842,12 +859,26 @@ const makeMapStateToProps = () => const mapStateToProps = (state) => { + let volume; + + // noiseVolume under threshold + if (state.peerVolumes[state.me.id] < state.settings.noiseThreshold) + { + // noiseVolume mapped to range 0.5 ... 1 (threshold switch) + volume = 1 + (Math.abs(state.peerVolumes[state.me.id] - + state.settings.noiseThreshold) / + state.settings.noiseThreshold) / 2; + } + // noiseVolume over threshold: no noise but voice + else { volume = 0; } + return { me : state.me, ...meProducersSelector(state), settings : state.settings, activeSpeaker : state.me.id === state.room.activeSpeakerId, - canShareScreen : hasPermission(state) + canShareScreen : hasPermission(state), + noiseVolume : volume }; }; @@ -864,6 +895,8 @@ export default withRoomContext(connect( return ( prev.room === next.room && prev.me === next.me && + Math.round(prev.peerVolumes[prev.me.id]) === + Math.round(next.peerVolumes[next.me.id]) && prev.peers === next.peers && prev.producers === next.producers && prev.settings === next.settings diff --git a/app/src/reducers/me.js b/app/src/reducers/me.js index f3fff66..35336a6 100644 --- a/app/src/reducers/me.js +++ b/app/src/reducers/me.js @@ -18,7 +18,8 @@ const initialState = raisedHand : false, raisedHandInProgress : false, loggedIn : false, - isSpeaking : false + isSpeaking : false, + isAutoMuted : true }; const me = (state = initialState, action) => @@ -162,6 +163,13 @@ const me = (state = initialState, action) => return { ...state, isSpeaking: flag }; } + case 'SET_AUTO_MUTED': + { + const { flag } = action.payload; + + return { ...state, isAutoMuted: flag }; + } + default: return state; } diff --git a/app/src/reducers/peerVolumes.js b/app/src/reducers/peerVolumes.js index cd5032f..826a038 100644 --- a/app/src/reducers/peerVolumes.js +++ b/app/src/reducers/peerVolumes.js @@ -32,7 +32,7 @@ const peerVolumes = (state = initialState, action) => case 'SET_PEER_VOLUME': { const { peerId } = action.payload; - const dBs = action.payload.volume; + const dBs = action.payload.volume < -100 ? -100 : action.payload.volume; return { ...state, [peerId]: Math.round(dBs) }; } From ea84fc75c62cc0c2152dd05ec5828728a859d3d8 Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Tue, 19 May 2020 01:45:09 +0200 Subject: [PATCH 5/6] hark clean up; some state fixes for autoMute; fix remote hark audiolevel --- app/src/RoomClient.js | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index 7cfd626..66c5f22 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -1001,31 +1001,35 @@ export default class RoomClient { play : false, interval : 5, - threshold : store.getState().settings.noiseThreshold }); + threshold : store.getState().settings.noiseThreshold, + history : 30 + }); + this._hark.lastVolume = -100; - // eslint-disable-next-line no-unused-vars - this._hark.on('volume_change', (volume, threshold) => + this._hark.on('volume_change', (volume) => { - volume = Math.round(volume); - - if (this._micProducer && volume !== this._micProducer.volume) + volume = Math.round(volume) + if (this._micProducer && volume !== Math.round(this._hark.lastVolume)) { - this._micProducer.volume = volume; - + if (volume < this._hark.lastVolume * 1.02) + { + volume = this._hark.lastVolume * 1.02; + } + this._hark.lastVolume = volume; store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume)); } }); this._hark.on('speaking', () => { - this._hark.setInterval(5); store.dispatch(meActions.setIsSpeaking(true)); - if (store.getState().settings.voiceActivatedUnmute && + if ((store.getState().settings.voiceActivatedUnmute || + store.getState().me.isAutoMuted) && this._micProducer && this._micProducer.paused) { this._micProducer.resume(); - store.dispatch(meActions.setAutoMuted(false)); } + store.dispatch(meActions.setAutoMuted(false)); // sanity action }); this._hark.on('stopped_speaking', () => { @@ -1037,7 +1041,6 @@ export default class RoomClient this._micProducer.pause(); store.dispatch(meActions.setAutoMuted(true)); } - this._hark.setInterval(5); }); } @@ -1984,19 +1987,8 @@ export default class RoomClient consumer.hark = hark(stream, { play: false }); - // eslint-disable-next-line no-unused-vars - consumer.hark.on('volume_change', (dBs, threshold) => + consumer.hark.on('volume_change', (volume) => { - // The exact formula to convert from dBs (-100..0) to linear (0..1) is: - // Math.pow(10, dBs / 20) - // However it does not produce a visually useful output, so let exaggerate - // it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to - // minimize component renderings. - let volume = Math.round(Math.pow(10, dBs / 85) * 10); - - if (volume === 1) - volume = 0; - volume = Math.round(volume); if (consumer && volume !== consumer.volume) From 0164312f30645d15480b6ea13727bc30c2d7be6f Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Tue, 19 May 2020 01:51:38 +0200 Subject: [PATCH 6/6] lint --- app/src/RoomClient.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index 66c5f22..5635d5b 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -1008,7 +1008,7 @@ export default class RoomClient this._hark.on('volume_change', (volume) => { - volume = Math.round(volume) + volume = Math.round(volume); if (this._micProducer && volume !== Math.round(this._hark.lastVolume)) { if (volume < this._hark.lastVolume * 1.02)