0
0
Fork 0
mirror of https://github.com/Flexpair/mumbling-mole.git synced 2026-05-14 11:17:35 +00:00
An HTML5 Mumble client for Chrome, Firefox, Edge and now also Safari
  • JavaScript 74%
  • Vue 14.1%
  • Shell 3.6%
  • SCSS 3.4%
  • Python 3.2%
  • Other 1.7%
Find a file
Flexpair.com ca6e6f75d8 docs: add SECURITY.md with vulnerability reporting policy (#309)
* docs: add SECURITY.md with vulnerability reporting policy

* docs: move SECURITY.md to .github/ and allow it in markdown validator

* chore(deps): npm audit fix — postcss XSS (GHSA-qx2v-qp2m-jg93)

---------

Co-authored-by: Jens Fielenbach <mail@flexpair.com>
2026-04-28 23:01:56 +02:00
.codacy Feature/python-auth-server (#265) 2025-12-19 23:03:39 +01:00
.devcontainer fix: disable nginx proxy buffering for Murmur WebSocket (#301) 2026-04-28 23:01:45 +02:00
.github docs: add SECURITY.md with vulnerability reporting policy (#309) 2026-04-28 23:01:56 +02:00
.semgrep feat(security): implement server-side credential distribution (#254) 2025-12-19 18:08:27 +01:00
__mocks__ Code quality improvement (#240) 2025-11-30 12:21:08 +01:00
__tests__ fix: add hysteresis to jitter buffer auto-adjustment (#297) 2026-04-28 23:01:45 +02:00
app fix: add hysteresis to jitter buffer auto-adjustment (#297) 2026-04-28 23:01:45 +02:00
auth-server Feature/python-auth-server (#265) 2025-12-19 23:03:39 +01:00
backups Optimize/image compression (#109) 2025-09-23 14:58:52 +02:00
localize feat(ui): add logout button to connect dialog (#284) 2026-04-28 23:01:45 +02:00
scripts docs: add SECURITY.md with vulnerability reporting policy (#309) 2026-04-28 23:01:56 +02:00
tests fix: resolve test failures and code quality issues (#244) 2025-11-30 18:16:44 +01:00
themes/MetroMumbleLight feat(ui): add logout button to connect dialog (#284) 2026-04-28 23:01:45 +02:00
upstream Refactor licensing structure: remove old LICENSE, add upstream/LICENSE, and update README for clarity on licensing status 2025-09-23 22:27:21 +00:00
.codacy.yml feat(security): implement server-side credential distribution (#254) 2025-12-19 18:08:27 +01:00
.depcheckrc Feature/proto-generator-optimization (#238) 2025-11-30 02:40:59 +01:00
.dockerignore fix: Improve audio quality settings and connection info dialogs (#206) 2025-11-14 00:31:48 +01:00
.env.test.example feat(security): implement server-side credential distribution (#254) 2025-12-19 18:08:27 +01:00
.gitattributes chore: exclude test files from GitHub language statistics 2025-11-14 00:39:56 +00:00
.gitconfig feat(dev): overhaul local dev 2025-09-09 16:27:21 +02:00
.gitignore feat(security): implement server-side credential distribution (#254) 2025-12-19 18:08:27 +01:00
.nvmrc Upgrade to node 22 2025-09-21 01:48:43 +00:00
.sonarignore SonarQube Code Quality Improvements (#184) 2025-11-02 00:10:04 +01:00
audit-baseline.json Improve security posture by running npm audit fix --force (#71) 2025-09-09 23:16:10 +02:00
build-esbuild.mjs feat(security): implement server-side credential distribution (#254) 2025-12-19 18:08:27 +01:00
docker-entrypoint.sh Feature/python-auth-server (#265) 2025-12-19 23:03:39 +01:00
Dockerfile fix(docker): create auth-server directory with proper permissions (#266) 2025-12-20 00:24:23 +01:00
jest.config.js Feature/proto-generator-optimization (#238) 2025-11-30 02:40:59 +01:00
jest.setup.js Feature/proto-generator-optimization (#238) 2025-11-30 02:40:59 +01:00
jest.text-transformer.cjs refactor: Update fs module imports to use node: prefix and improve error handling in mocks 2025-11-11 21:51:53 +00:00
LICENSE docs(license): adopt AGPL-3.0 with ISC attribution for upstream mumble-web (#305) 2026-04-28 23:01:13 +02:00
NOTICE docs(license): adopt AGPL-3.0 with ISC attribution for upstream mumble-web (#305) 2026-04-28 23:01:13 +02:00
package-lock.json docs: add SECURITY.md with vulnerability reporting policy (#309) 2026-04-28 23:01:56 +02:00
package.json build(deps-dev): bump dotenv from 17.4.1 to 17.4.2 (#304) 2026-04-28 23:01:45 +02:00
playwright.config.js feat(security): route all traffic through nginx reverse proxy (#253) 2025-12-13 11:09:56 +01:00
README.md docs(license): adopt AGPL-3.0 with ISC attribution for upstream mumble-web (#305) 2026-04-28 23:01:13 +02:00
rebuild-and-restart.sh fix: prevent decoder 'push after EOF' errors + build system cleanup 2025-10-18 21:58:30 +02:00
sonar-project.properties fix: Exclude test files from SonarQube analysis 2025-11-05 00:10:45 +00:00
start-dev-server.sh feat(security): implement server-side credential distribution (#254) 2025-12-19 18:08:27 +01:00
stop-dev-server.sh feat(security): implement server-side credential distribution (#254) 2025-12-19 18:08:27 +01:00

🎤 Mumbling Mole

Browser-first Mumble voice chat client no native dependencies required

Node.js Version

Mumbling Mole brings Mumble voice communication to modern browsers via Vue.js 3, Web Audio API with AudioWorklet, and WebSocket tunneling (NOT WebRTC). Built on mumble-web.

v4.0.3 · Vue.js 3.5.25 · esbuild 0.27.0 · 1,477 unit tests

Features

  • 🎙️ Browser-native audio AudioWorklet + Opus via WASM
  • 🔌 WebSocket tunneling TCP over WebSocket (no WebRTC)
  • Vue.js 3 + Pinia Modern reactive UI with 7 state stores
  • 📦 Fast builds esbuild compiles in ~0.3s
  • 🐳 Docker-ready Containerized dev and production
  • 🔊 Audio loopback Built-in 440Hz test for validation

🚀 Quick Start

git clone https://github.com/Flexpair/mumbling-mole.git
cd mumbling-mole && npm install

# Development
./start-dev-server.sh          # Build + serve at http://local.flexpair.app
npm run build:local            # Rebuild + restart server

# Testing  
npm test                       # Full suite: unit + E2E + audit
npm run test:unit              # Jest (1,477 tests)
npm run test:loopback:headed   # Playwright with visible browser

# Production
npm run build                  # Clean build (~0.3s)

Test audio: Connect → Click Test → Speak into mic → Hear echo


🏗️ Architecture

┌─────────────────────────────────────────────────────────────┐
│  Main Thread                   │    Web Worker               │
│  • Vue.js 3 + Pinia stores     │    • Mumble protocol        │
│  • AppState coordinator        │    • Opus encoding (WASM)   │
│  • AudioContext singleton      │    • Channel/user trees     │
└────────────────────────────────┴─────────────────────────────┘
              │                              │
         AudioWorklet                   WebSocket
        (48kHz capture)                     │
              └────────────websockify───────┘
                               ↓
                     Mumble Server (TCP:64738)

Key Files

Concern Files
Entry/UI app/index.jsapp/components/App.vue
State app/stores/*.js (7 Pinia stores)
Audio voice.jsrecorder-worker.jsencode-worker.js
Network worker-client.jsworker.jsmumble-websocket.js

Audio Pipeline

  • Send: recorder-worker.js (960 samples @ 48kHz) → Opus WASM → WebSocket
  • Receive: WebSocket → decoder pool → jitter buffer → speakers
  • ⚠️ Critical: Sender MUST output 960-sample frames (20ms @ 48kHz)

🐳 Docker

# Production
docker build --target prod -t mumbling-mole:prod \
  --build-arg GIT_COMMIT=$(git rev-parse HEAD) .

# Development  
docker build --target dev -t mumbling-mole:dev .
Variable Description Default
MUMBLE_SERVER Target host:port Required
PORT HTTP server port 80
SKIP_TUNNEL Disable websockify false

🔧 Configuration

Runtime config: app/config.js (defaults) + app/config.local.js (overrides)

window.mumbleWebConfig = {
  defaults: { address: 'voice.example.com', port: '443' }
}

Theming: ?theme=MetroMumbleLight or MetroMumbleDark


🐛 Troubleshooting

# Tunnel logs
tail -f /tmp/entrypoint.log

# Audio state (browser console)  
audioContextManager.getStats()
  • No audio? Check mic permissions (HTTPS required)
  • Worker errors? Update BOTH _dispatchEvent AND registerEventProxy
  • AudioWorklet? Must be ES5 no imports/requires

📁 Project Structure

app/
├── index.js              # Entry (Pinia + Vue mount)
├── components/           # Vue.js components
├── stores/               # Pinia stores (7 modules)
├── audio/                # AudioWorklet + codec workers
├── worker.js             # Web Worker (Mumble protocol)
├── worker-client.js      # Main↔Worker bridge
└── mumble-client/        # Vendored protocol client

📚 Documentation

Document Purpose
.github/copilot-instructions.md AI coding agent guide
tests/README.md Testing strategy
app/audio/README.md Audio debugging
app/stores/README.md Pinia architecture
app/auth/README.md Auth abstraction

⚠️ Known Issues

  • #201: Unbounded playback queue (memory leak risk)
  • #202: No configurable jitter buffer
  • #203: Missing Opus PLC (packet loss → clicks)

🤝 Contributing

  1. Fork → git checkout -b feature/name
  2. Follow conventions: Pinia stores, Vue 3 Composition API, useXStore() pattern
  3. Test: npm test
  4. PR with conventional commits (feat:, fix:, refactor:)

Critical rules:

  • Always ensureAudioContext(), never new AudioContext()
  • Worker events: update BOTH _dispatchEvent AND registerEventProxy
  • Never commit dist/ it's generated

📄 License

mumbling-mole is licensed under the GNU Affero General Public License, version 3 only (AGPL-3.0-only). See the LICENSE file for the full text and the NOTICE file for copyright and attribution details.

Portions of this project are derived from the mumble-web project by Jonas Herzig, licensed under the ISC License. The original ISC license text is preserved in upstream/LICENSE.

Contributing

By submitting a pull request, you agree that your contribution is provided under the same license terms as this project: AGPL-3.0-only.

🙏 Acknowledgments


Made with ❤️ for the Flexpair community