sound-check
Private browser microphone check for meeting calls: test input, volume, clipping, and room noise before you join.
Readme
Loading readme…
Private browser microphone check for meeting calls: test input, volume, clipping, and room noise before you join.
Loading readme…
Sound Check answers the question behind "microphone not working in meetings", "mic check before call", and "am I too quiet on calls": is the microphone signal itself ready before the call starts? It is a private, browser-only microphone check that gives a plain PASS or CHECK verdict before Zoom, Meet, Teams, or another call app gets involved.
Start the check, allow microphone access, choose an input when the browser exposes one, and follow a brief quiet period and speaking period. The browser measures:
PASS means each measurement is within the tool's conservative operating range. CHECK means one or more measurements need attention: no input, a quiet signal, clipping, excessive room noise, or browser processing. A PASS does not guarantee that a meeting app will not apply its own processing or have its own device setting.
Audio is processed entirely in the browser. It is never uploaded, stored, or retained by the site. Sound Check uses no analytics, cookies, accounts, advertising, forms, or third-party requests.
Use a current Chrome, Edge, Firefox, or Safari browser with microphone permission, getUserMedia, Web Audio, and MediaRecorder support. Desktop browsers can expose an input selector; mobile browsers commonly use the operating system's default input.
Requires Node 22+ and pnpm.
pnpm install
pnpm run check
pnpm run build
pnpm run verify:preview
| Command | What it does |
|---|---|
pnpm dev | Starts the local development server. |
pnpm run build | Type-checks and creates the static dist/ bundle. |
pnpm run preview | Serves the built bundle locally. |
pnpm run verify:preview | Starts preview, verifies the built app and strict Pages CSP, then exits. |
pnpm run lint | Runs oxlint. |
pnpm run format | Checks formatting with oxfmt. |
pnpm run typecheck | Type-checks without emitting files. |
pnpm run test | Runs the test suite. |
pnpm run check | Runs lint, format, typecheck, tests, and the llms.txt consistency check. |
The app has no server-side audio processing. Agents can run pnpm run check for the full quality gate and pnpm run verify:preview after a build to exercise the generated static bundle without leaving a server running. scripts/package_release.py creates stable zip and tarball release archives using the release tag commit time. llms.txt and public/llms.txt are intentionally identical; pnpm run check:llms verifies that contract.
The public app deploys continuously from main to sound-check.jishnuteegala.com through Cloudflare Pages. The one-time dashboard connection is documented in docs/agents/deploy.md. No Cloudflare credentials are stored in this repository.
Use a tagged GitHub Release rather than an arbitrary commit. Every release includes prebuilt sound-check-<version>.zip and .tar.gz static bundles plus SHA256SUMS.
VERSION=0.1.0
curl -fLO "https://github.com/jishnuteegala/sound-check/releases/download/v$VERSION/sound-check-$VERSION.tar.gz"
curl -fLO "https://github.com/jishnuteegala/sound-check/releases/download/v$VERSION/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS
mkdir -p sound-check && tar -xzf "sound-check-$VERSION.tar.gz" -C sound-check
The extracted archive is a static site with hash-based navigation. It needs no SPA fallback or rewrite rule.
_headers is applied automatically only by Cloudflare Pages and Netlify; configure equivalent headers explicitly for other hosts.
Cloudflare Pages
Create a Pages project in the Cloudflare dashboard and direct-upload the extracted sound-check/ directory. For Git integration, use build command pnpm run build and output directory dist; public/_headers is included automatically. Add your custom domain in Pages after the first deploy.
Vercel
Create a new Vercel project and upload the extracted directory as a static deployment, or connect the repository with build command pnpm run build and output directory dist.
Netlify
Create a Netlify site by dragging the extracted directory into the deploy dropzone, or connect the repository with build command pnpm run build and publish directory dist.
GitHub Pages
Publish the extracted directory from a gh-pages branch:
git checkout --orphan gh-pages
git rm -rf .
cp -R sound-check/. .
git add -A
git commit -m "deploy sound-check"
git push origin gh-pages
Enable Pages for the gh-pages branch in repository settings. Use a custom domain or a root site because the bundle is built with base /; a project-path URL requires rebuilding with a matching Vite base value.
VPS with nginx
server {
listen 80;
server_name sound-check.example.com;
root /var/www/sound-check;
index index.html;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; media-src 'self' blob:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Permissions-Policy "camera=(), geolocation=(), microphone=(self), payment=(), usb=()" always;
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
}
Copy the extracted files to /var/www/sound-check and reload nginx.
VPS with Caddy
sound-check.example.com {
root * /var/www/sound-check
header {
Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; media-src 'self' blob:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'"
Referrer-Policy "no-referrer"
X-Content-Type-Options "nosniff"
Permissions-Policy "camera=(), geolocation=(), microphone=(self), payment=(), usb=()"
}
file_server
}
Docker
FROM nginx:alpine
COPY sound-check/ /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; media-src 'self' blob:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Permissions-Policy "camera=(), geolocation=(), microphone=(self), payment=(), usb=()" always;
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
}
docker build -t sound-check .
docker run --rm -p 8080:80 sound-check
Or run the extracted bundle directly with the same nginx configuration:
docker run --rm -p 8080:80 -v "$PWD/sound-check:/usr/share/nginx/html:ro" -v "$PWD/nginx.conf:/etc/nginx/conf.d/default.conf:ro" nginx:alpine
Release Please maintains a reviewed release PR from Conventional Commits. Merging that PR creates a version tag and draft GitHub Release. The release workflow builds, checksums, uploads, and then publishes the static archives. It uses the repository's built-in GITHUB_TOKEN; release PRs are never auto-merged.
MIT - see LICENSE.