Skip to content

Commit 2711b13

Browse files
committed
[wip] feat: use noise-suppressor for voice messages
Signed-off-by: Maksim Sukharev <[email protected]>
1 parent 54aee4d commit 2711b13

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

rspack.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ module.exports = defineConfig((env) => {
182182
resourceQuery: /raw/,
183183
type: 'asset/source',
184184
},
185+
{
186+
resourceQuery: /url$/,
187+
type: 'asset/resource',
188+
},
185189
],
186190
},
187191

src/components/NewMessage/NewMessageAudioRecorder.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import IconMicrophoneOutline from 'vue-material-design-icons/MicrophoneOutline.v
5656
import { useAudioEncoder } from '../../composables/useAudioEncoder.ts'
5757
import { useGetToken } from '../../composables/useGetToken.ts'
5858
import { mediaDevicesManager } from '../../utils/webrtc/index.js'
59+
import { processNoiseSuppression } from '../../utils/supressNoise.ts'
5960
6061
export default {
6162
name: 'NewMessageAudioRecorder',
@@ -173,7 +174,11 @@ export default {
173174
// Create new audio stream
174175
try {
175176
this.audioStream = await mediaDevicesManager.getUserMedia({
176-
audio: true,
177+
audio: {
178+
noiseSuppression: false,
179+
echoCancellation: false,
180+
autoGainControl: false
181+
},
177182
video: false,
178183
})
179184
} catch (exception) {
@@ -189,7 +194,10 @@ export default {
189194
190195
// Create a media recorder to capture the stream
191196
try {
192-
this.mediaRecorder = new this.MediaRecorder(this.audioStream, {
197+
// const audioStreamProcessed = await processNoiseSuppression(this.audioStream, 'none')
198+
const audioStreamProcessed = await processNoiseSuppression(this.audioStream, 'rnnoise')
199+
200+
this.mediaRecorder = new this.MediaRecorder(audioStreamProcessed, {
193201
mimeType: 'audio/wav',
194202
})
195203
} catch (exception) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
declare module '@sapphi-red/web-noise-suppressor/rnnoiseWorklet.js?url'
7+
declare module '@sapphi-red/web-noise-suppressor/rnnoise.wasm?url'
8+
declare module '@sapphi-red/web-noise-suppressor/rnnoise_simd.wasm?url'

src/utils/supressNoise.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {
2+
RnnoiseWorkletNode,
3+
loadRnnoise,
4+
} from '@sapphi-red/web-noise-suppressor'
5+
6+
import rnnoiseWorkletPath from '@sapphi-red/web-noise-suppressor/rnnoiseWorklet.js?url'
7+
import rnnoiseWasmPath from '@sapphi-red/web-noise-suppressor/rnnoise.wasm?url'
8+
import rnnoiseWasmSimdPath from '@sapphi-red/web-noise-suppressor/rnnoise_simd.wasm?url'
9+
10+
type NoiseSuppressorModel = 'rnnoise' | 'none'
11+
12+
export async function processNoiseSuppression(stream: MediaStream, model: NoiseSuppressorModel): Promise<MediaStream> {
13+
if (model === 'rnnoise') {
14+
const audioContext = new AudioContext()
15+
const rnnoiseWasmBinary = await loadRnnoise({
16+
url: rnnoiseWasmPath,
17+
simdUrl: rnnoiseWasmSimdPath
18+
})
19+
await audioContext.audioWorklet.addModule(rnnoiseWorkletPath)
20+
const mediaStreamAudioSource = audioContext.createMediaStreamSource(stream)
21+
const mediaStreamAudioDestinationNode = audioContext.createMediaStreamDestination()
22+
const rnnoise = new RnnoiseWorkletNode(audioContext, {
23+
wasmBinary: rnnoiseWasmBinary,
24+
maxChannels: 2
25+
})
26+
mediaStreamAudioSource.connect(rnnoise)
27+
rnnoise.connect(mediaStreamAudioDestinationNode)
28+
return mediaStreamAudioDestinationNode.stream
29+
}
30+
31+
return stream
32+
}

0 commit comments

Comments
 (0)