# soundclarity

![Node.js](https://img.shields.io/badge/node-%3E%3D20-339933?logo=nodedotjs&logoColor=white)
![FFmpeg](https://img.shields.io/badge/FFmpeg-required-007808?logo=ffmpeg&logoColor=white)
![Privacy](https://img.shields.io/badge/privacy-local--first-0A7A3E)
![License](https://img.shields.io/badge/license-MIT-blue)

Local CLI that cleans up old, noisy, or poorly encoded audio on your machine. It aims for clearer, more consistent playback while keeping the voice, melody, timing, and stereo feel intact. Audio never leaves your computer: no cloud APIs, uploads, accounts, or telemetry.

<br>

![Guided mode](https://cdn.jsdelivr.net/npm/@technway/soundclarity/media/screenshots/wizard.png)

## Install

Needs Node.js 20+ and FFmpeg on your `PATH`.

```bash
npm install -g @technway/soundclarity
```

Then:

```bash
soundclarity
```

Or run once without installing globally:

```bash
npx @technway/soundclarity
```

<br>

![Help](https://cdn.jsdelivr.net/npm/@technway/soundclarity/media/screenshots/help.png)

### Dependencies

| Tool | Required when | Get it |
| --- | --- | --- |
| FFmpeg + FFprobe | Always | [Download FFmpeg](https://ffmpeg.org/download.html) |
| yt-dlp | YouTube / http(s) URL inputs | [Download yt-dlp](https://github.com/yt-dlp/yt-dlp#installation) |
| Demucs (Python) | `vocal` and `restore --vocal-aware` | [Install Demucs](https://github.com/facebookresearch/demucs#installation) |

Put FFmpeg (and yt-dlp when you use URLs) on your `PATH` so `ffmpeg`, `ffprobe`, and `yt-dlp` work in the terminal.

> **Note:** Demucs model weights download on first use. They are not bundled with soundclarity.

## Guided mode

Run `soundclarity` alone. Pick what you want to do, point at a file or URL, choose strength and format. No flags required.

Power users can still pass commands and options as usual.

## What you can do

| Command | Purpose |
| --- | --- |
| `soundclarity` | Guided mode |
| `soundclarity smart <input>` | Pick preset and strength from the file |
| `soundclarity analyze <input>` | Inspect only (no changes) |
| `soundclarity clean <input>` | Everyday cleanup (default path) |
| `soundclarity heritage <input>` | Worn archival recordings |
| `soundclarity denoise <input>` | Noise down only (no EQ / punch / loudness change) |
| `soundclarity scrub <input>` | Maximum noise scrub |
| `soundclarity restore <input>` | Stronger than clean |
| `soundclarity vocal <input>` | Vocal clarity (needs Demucs) |
| `soundclarity compare <a> <b>` | Before vs after metrics |

Shorthand: `soundclarity <input>` runs `clean`.

Input can be a local file, a glob, or an `http(s)` URL (YouTube and other yt-dlp sources).

<br>

![Analyze](https://cdn.jsdelivr.net/npm/@technway/soundclarity/media/screenshots/analyze.png)

## Defaults

By default, cleanup makes tracks louder and clearer: **balanced** preset, strength **75**, target loudness **-12 LUFS**.

| Want | Use |
| --- | --- |
| Keep original volume | `--preserve-loudness` |
| Different loudness | `--target-lufs -14` (example) |
| Auto preset + strength | `soundclarity smart …` or `--smart` |
| Overwrite without asking | `--overwrite` |

<br>

![Clean](https://cdn.jsdelivr.net/npm/@technway/soundclarity/media/screenshots/clean.png)

## Presets

| Preset | Best for |
| --- | --- |
| `gentle` | Light touch |
| `balanced` | Most tracks (default) |
| `strong` | Heavier cleanup |
| `heritage` | Severely degraded archival transfers |
| `denoise` | Noise only; leaves level and tone alone |
| `scrub` | Extremely noisy material; no punch EQ |

<br>

```bash
soundclarity clean song.mp3
soundclarity clean song.mp3 out.flac --preset strong --strength 90
soundclarity heritage worn-transfer.mp4
soundclarity denoise noisy-track.mp4
soundclarity scrub very-noisy.mp4
soundclarity smart song.mp3
```

## Useful flags

| Flag | Meaning |
| --- | --- |
| `--preset <name>` | `gentle` \| `balanced` \| `strong` \| `heritage` \| `denoise` \| `scrub` |
| `--strength <0-100>` | How hard to push within the preset |
| `--smart` | Auto choose preset and strength |
| `--format <fmt>` | `wav` \| `flac` \| `mp3` \| `aac` (default `flac`) |
| `--preserve-loudness` | Do not raise integrated loudness |
| `--target-lufs <n>` | Loudness target (default `-12`) |
| `--overwrite` | Replace existing output |
| `--audio-only` | Drop the picture track from video inputs |
| `--noise-profile start:end` | Point at a quiet passage for denoising |
| `--keep-diagnostics` | Write a diagnostics folder next to the output |

## Video files

Music videos stay videos. The picture is copied through untouched; only the audio is restored. Sync is preserved.

| Input | Format | Output |
| --- | --- | --- |
| `.mp4` / `.mov` | `aac` or `mp3` | `.mp4` with picture |
| `.mp4` / `.mov` | `flac` or `wav` | `.mkv` with picture (MP4 cannot hold lossless audio) |
| `.webm` / `.mkv` | any | `.mkv` with picture |
| audio only | any | audio file |

<br>

```bash
soundclarity clean video.mp4
soundclarity clean video.mp4 --format aac
soundclarity clean video.mp4 --audio-only
```

> **Tip:** Naming an audio extension (like `.flac`) also means audio only.

## YouTube and other URLs

Install yt-dlp first (see [Dependencies](#dependencies)).

```bash
soundclarity clean "https://www.youtube.com/watch?v=VIDEO_ID"
soundclarity analyze "https://www.youtube.com/watch?v=VIDEO_ID"
```

Downloads stay local. soundclarity never uploads them.

> **Warning:** You are responsible for respecting copyrights and the site’s terms of use.

## Vocals

```bash
soundclarity vocal song.mp3
soundclarity restore song.mp3 --vocal-aware
```

Use this when the voice is buried and full-mix cleanup is not enough. Install Demucs first (see [Dependencies](#dependencies)).

## Honest limits

> **Caution:** Turning MP3 into FLAC does not bring back detail the lossy encode already threw away. Outputs can be lossless encodings of the *processed* waveform. Missing highs are not invented, tempo and key are not changed, and voices are not replaced or auto-tuned.

## Troubleshooting

| Problem | What to try |
| --- | --- |
| `ffmpeg: command not found` | Install FFmpeg and reopen the terminal |
| Extension does not match format | Use `.flac` with `--format flac`, or change `--format` |
| Denoise seems skipped | Pass `--noise-profile start:end` on a quiet stretch |
| Want original loudness | Add `--preserve-loudness` |
| Vocal command fails | Install Demucs and confirm `python3` works |
| Output already exists | Confirm the prompt, or pass `--overwrite` |

## License

[MIT](LICENSE)
