A Claude Code skill that cleans up and masters the audio track of a video or audio file. The skill diagnoses the source, removes mains hum (50 Hz / 60 Hz) and rumble, reduces broadband noise, shapes the voice with gentle EQ and compression, and normalizes loudness to a broadcast target. Video streams are stream-copied — bit-for-bit identical to the source.
Built to turn raw talking-head recordings into clear, warm, podcast-grade sound with one instruction.
- Diagnoses the source: measures loudness (EBU R128), peak/mean volume, noise floor, DC offset, and probes narrow bands at 50 Hz / 60 Hz to detect mains hum.
- Builds a filter chain from the measurements — narrow-Q hum notches per detected mains frequency + harmonics, 80 Hz highpass,
afftdndenoise sized to the measured noise floor, de-essing, presence EQ at 3 kHz, warmth EQ at 200 Hz, 14 kHz lowpass, 3:1 compression, two-passloudnorm. - Processes the file: re-encodes audio only, copies video untouched, preserves channel layout, writes
<name>_cleaned.<ext>next to the input. - Verifies the result: re-measures loudness/peak/hum and prints a before-and-after summary.
Five presets: podcast (default, -16 LUFS), broadcast (-23 LUFS, EBU R128), streaming (-14 LUFS, Spotify), light (gentle pass for already-clean audio), aggressive (deep denoise for rough sources).
- ffmpeg 4.0+ on your PATH, with
loudnorm,afftdn,acompressor,deesser,equalizer,highpass,lowpass,astats, andvolumedetect(all in the standard build). - Python 3.8+ — uses only the standard library.
Check:
ffmpeg -version
python3 --versionInstall ffmpeg if missing:
# macOS
brew install ffmpeg
# Debian / Ubuntu
sudo apt install ffmpeg
# Windows (winget)
winget install Gyan.FFmpegUses the skills CLI from vercel-labs/skills:
npx skills add nemock/audio-cleanup-skillIf your system has multiple agent toolchains, pin the target:
npx skills add nemock/audio-cleanup-skill -a claude-codeThis drops the skill into ~/.claude/skills/audio-cleanup/. Claude Code picks it up automatically.
git clone https://github.com/nemock/audio-cleanup-skill.git
mkdir -p ~/.claude/skills
cp -r audio-cleanup-skill/skills/audio-cleanup ~/.claude/skills/Confirm:
ls ~/.claude/skills/audio-cleanup/SKILL.mdThe skill's description is broad on purpose — it fires on direct and indirect requests, even when the user doesn't say "skill". Examples that work:
- "Clean up the audio on
interview.mp4." - "Make my voice sound like a podcast."
- "The audio sounds bad — can you fix it?"
- "Master the audio on this video."
- "Remove the 60 Hz hum from
lecture.wav." - "There's a buzz in the background of
vlog.mov. Get rid of it." - "Normalize this to broadcast loudness."
Claude will analyze the source, pick a preset, run the script, and report the before-and-after numbers.
You can also use the script from the terminal — Claude does not have to drive it.
# default podcast preset; output is <name>_cleaned.<ext> next to the input
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4
# broadcast delivery loudness (EBU R128, -23 LUFS)
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4 --preset broadcast
# streaming loudness (Spotify / Apple Music, -14 LUFS)
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4 --preset streaming
# light touch on already-clean audio (loudness + optional hum notch only)
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4 --preset light
# heavier denoise + deeper hum notching for poor sources
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4 --preset aggressive
# force the hum frequency when detection is borderline
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4 --hum 60
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py lecture.wav --hum 50
# skip hum filtering entirely
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py podcast.mp3 --hum none
# audio-only file (WAV stays WAV; MP3 / M4A re-encoded at 192k)
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py recording.wav
# custom output path
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4 \
--output ~/Desktop/interview_master.mp4
# pick a non-default audio track
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py multitrack.mkv --audio-track 1
# analyze only — print the filter chain without writing a file
python3 ~/.claude/skills/audio-cleanup/scripts/clean_audio.py interview.mp4 --dry-run- Output filename defaults to
<input_basename>_cleaned<.ext>in the same directory as the input. Override with--output. - The script refuses to overwrite the source file.
- Video containers: video is stream-copied, audio is re-encoded as AAC at 192 kbps.
- Audio-only: WAV stays PCM 16-bit. FLAC stays FLAC. MP3 re-encodes via libmp3lame at 192k. M4A / AAC re-encodes as AAC 192k.
- Channel layout is preserved (mono stays mono, stereo stays stereo).
audio-cleanup-skill/
├── README.md
├── LICENSE
├── CHANGELOG.md
└── skills/
└── audio-cleanup/
├── SKILL.md
├── scripts/
│ └── clean_audio.py
└── references/
├── filter-reference.md
└── troubleshooting.md
The skills/<name>/ layout is the convention used by vercel-labs/agent-skills and matches the npx skills add installer's primary search path.
error: ffmpeg and ffprobe must be installed and on PATH
Install ffmpeg (see Requirements). On macOS with Homebrew make sure /opt/homebrew/bin is on PATH.
error: no audio streams found in input
The input file has no audio track. Confirm with ffprobe -i FILE -show_streams.
Loudness misses the target by more than 1 LU
Usually means the source is extremely quiet (< -45 LUFS) and the true-peak ceiling caps the gain. Pre-amplify the input or rerun on the first output: python3 clean_audio.py output_cleaned.wav --preset light.
Hum is still audible after processing
The detected frequency may be wrong. Force the right one: --hum 50 (Europe / most of Asia / Africa) or --hum 60 (North America / much of South America). If the buzz is not at the mains frequency at all, see skills/audio-cleanup/references/troubleshooting.md.
Voice sounds underwater / over-processed
Switch to --preset light, or read skills/audio-cleanup/references/troubleshooting.md for the per-filter tweaks.
Output file is identical to input or has no audio Check the printed ffmpeg command in the verbose log. Run it by hand to surface any silent error.
More: full per-symptom adjustment guidance lives in skills/audio-cleanup/references/troubleshooting.md. Per-filter reasoning lives in skills/audio-cleanup/references/filter-reference.md.
MIT — see LICENSE.