The project is in a healthy, maintained state
Vendors the large binary browser assets used by Discourse voice/video chat so they stay out of the main repository: RNNoise, DTLN, and DeepFilterNet3 noise-suppression AudioWorklet bundles (wasm + models), the onnxruntime-web/Silero VAD/parakeet.js speech-to-text runtime, the MediaPipe selfie-segmentation runtime for background blur, and a self-contained livekit-client SDK bundle. Includes the pinned, reproducible build scripts that produce every artifact.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

 Project Readme

DiscourseVoiceAssets

Prebuilt browser media assets for Discourse voice/video chat (the resenha plugin). The plugin's client features depend on ~75 MB of WebAssembly binaries, ML models, and vendored SDK bundles; this gem carries those blobs so they stay out of the main Discourse repository, along with the pinned, reproducible build scripts that produce every artifact.

What's vendored

Directory Contents Source License
vendor/rnnoise RNNoise noise-suppression worklet + wasm (~130 KB) xiph/rnnoise @ v0.1.1 BSD-3-Clause
vendor/dtln DTLN noise-suppression worklet + wasm (~6 MB) DataDog/dtln-rs Apache-2.0
vendor/dfn3 DeepFilterNet3 worklet + wasm (~9.5 MB) + model (~8 MB) Rikorose/DeepFilterNet MIT/Apache-2.0
vendor/stt Live-subtitles runtime: parakeet.js worker, Silero VAD, onnxruntime-web (~30 MB) parakeet.js, @ricky0123/vad-web, onnxruntime-web Apache-2.0 / MIT
vendor/mediapipe Background-blur segmentation: tasks-vision runtime + selfie_segmenter.tflite (~22 MB) MediaPipe, © Google Apache-2.0
vendor/livekit Self-contained livekit-client ESM bundle (~530 KB) livekit-client Apache-2.0

The speech-to-text model weights (~200–400 MB per model) are not vendored — they download at runtime from HuggingFace (or a self-hosted mirror).

How the plugin consumes it

require "discourse_voice_assets"

DiscourseVoiceAssets::DIRECTORIES # => %w[dfn3 dtln livekit mediapipe rnnoise stt]
DiscourseVoiceAssets.vendor_path("stt") # absolute path to the vendored dir

At plugin activation the vendor tree is symlinked into the plugin's public/javascripts/<gem version>/, and the server exposes that base path to the client, so assets are served at /plugins/resenha/javascripts/<version>/<dir>/.... Filenames are stable across releases — the version-stamped URL provides the cache busting that content hashes otherwise would (the /plugins/ prefix is served with long-lived immutable caching) — so bumping the gem requires no other plugin change.

Rebuilding assets

Everything under vendor/ is generated. Upstreams are pinned (git SHA or npm version); build scripts clone into the gitignored upstream/ directory and apply patches from src/<engine>-worklet/patches/ where needed.

pnpm install

bash scripts/build-rnnoise-worklet.sh   # emcc (standalone wasm)
bash scripts/build-dtln-worklet.sh      # Rust + Emscripten
bash scripts/build-dfn3-worklet.sh      # Rust + wasm-pack
bash scripts/build-stt-assets.sh        # esbuild (parakeet.js, vad-web, ort)
bash scripts/build-livekit-bundle.sh    # esbuild (livekit-client)
bash scripts/fetch-mediapipe-assets.sh  # npm tarball + Google model repo (SHA-256 pinned)

# Verify built engines end-to-end in headless Chromium:
node scripts/smoke-ns-worklet.mjs <rnnoise|dtln|dfn3>
node scripts/smoke-stt-worker.mjs

Releasing a new version

  1. Rebuild the affected assets (above) and commit vendor/.
  2. Bump lib/discourse_voice_assets/version.rb, tag, and release the gem.
  3. In Discourse: bump the gem version. Nothing else — the plugin references the stable filenames and derives the versioned URL at runtime. Renaming or removing a vendored file (see the spec's stable-path list) is a breaking change needing a coordinated plugin update.

Development

bundle install
bundle exec rspec  # vendor tree / manifest integrity
pnpm test:js       # worklet source unit tests (node --test)