feat(audio): add post-processing noise reduction with RNNoise#374
feat(audio): add post-processing noise reduction with RNNoise#374mehmetnadir wants to merge 1 commit intosiddharthvaddem:mainfrom
Conversation
Add AI-powered noise reduction that can be applied during video playback in the editor. Uses RNNoise (xiph.org neural network) via WebAssembly for real-time audio processing with three configurable levels. Features: - Post-processing approach: raw audio is preserved during recording, noise reduction is applied in the editor during playback - Three levels: Light, Moderate, Aggressive with distinct filter chains - 2-stage highpass + lowpass filters for steep frequency rolloff - RNNoise neural network for intelligent noise suppression - Noise gate to suppress residual noise below threshold - DynamicsCompressor for volume normalization - Settings panel toggle and level selector in editor - Smooth transitions when changing levels (no audio interruption) - Fix: use "floating" alwaysOnTop level for HUD/source selector so macOS permission dialogs appear above the app - i18n: noise reduction labels in en, es, zh-CN New dependency: @sapphi-red/web-noise-suppressor (MIT, ~674KB) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f12bcf5172
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (workletRegistered) return; | ||
|
|
||
| await audioContext.audioWorklet.addModule(rnnoiseWorkletPath); | ||
| workletRegistered = true; |
There was a problem hiding this comment.
Register RNNoise worklet per AudioContext
registerRnnoiseWorklet is guarded by a single global workletRegistered flag, but AudioWorklet registrations are scoped to each AudioContext. After useAudioEnhancement closes a context and a new one is created (e.g., reopening/remounting editor playback), this guard skips addModule, so new RnnoiseWorkletNode(...) fails and the code falls back to the non-RNNoise path, silently disabling the AI denoiser for subsequent sessions.
Useful? React with 👍 / 👎.
| destroy: () => { | ||
| gate.destroy(); | ||
| rnnoiseNode?.destroy(); |
There was a problem hiding this comment.
Disconnect enhancement graph during teardown
destroy() only stops the gate loop and RNNoise node, but never disconnects the filter/compressor nodes that were connected to ctx.destination. Because useAudioEnhancement rebuilds the chain on toggles/level changes, old chains remain attached in the audio graph, which can accumulate nodes over time and increase memory/CPU usage in long editing sessions.
Useful? React with 👍 / 👎.
Summary
"floating"alwaysOnTop level for HUD/source selector so macOS permission dialogs appear above the appNew dependency
@sapphi-red/web-noise-suppressor— MIT license, ~674KB, zero dependenciesTest plan
npm run i18n:check— all locales should pass🤖 Generated with Claude Code