ffmpeg-audio
One ffmpeg shape recurs across the voiceprint, diarization, whisper, and
training lanes: mono · 16 kHz · signed-16-bit PCM WAV —
ffmpeg -ac 1 -ar 16000 -c:a pcm_s16le. This skill is that convention as a
single idempotent CLI, so the same bytes come out every time regardless of who
runs it or what container went in.
Defaults are the convention (SR=16000, CH=1, CODEC=pcm_s16le). Change
them in one place at the top of ffmpeg_audio.py if a lane ever needs a
different target.
Safety model
- Dry-run by default. Every op prints the exact
ffmpegcommand it would run and changes nothing until--apply. - Idempotent. An output that already exists and is newer than its input(s)
is skipped — re-running a batch is a no-op.
--forcerebuilds anyway. - Read-only
probenever writes.
The four ops
normalize — any audio → mono 16k PCM WAV (the canonical convention).
python3 ~/.claude/skills/ffmpeg-audio/ffmpeg_audio.py normalize output.m4a -o alice.wav --applyBatch a roster with globs +
--suffix(no-o):python3 .../ffmpeg_audio.py normalize alice.* bob.* carol.* --suffix .16k.wav --applytrim — slice
--start/--durationthen normalize (the enroll-clip pattern:superwhisper/recordings/<ts>/output.wav→~/enroll/alice.wav, 22s).python3 .../ffmpeg_audio.py trim output.wav --start 0 --duration 22 -o ~/enroll/alice.wav --applyconcat — join N inputs into one normalized WAV (filter_complex concat).
python3 .../ffmpeg_audio.py concat a.wav b.wav c.wav -o joined.wav --applyprobe — ffprobe readout (codec · channels · rate · duration). Read-only.
python3 .../ffmpeg_audio.py probe alice.wav
Reconcile a YAML catalog
For a fixed set of jobs (e.g. the enroll roster), declare them once and reconcile — idempotent, so it's safe to re-run after adding one person.
python3 .../ffmpeg_audio.py reconcile jobs.yaml # dry-run
python3 .../ffmpeg_audio.py reconcile jobs.yaml --apply # execute
See examples/enroll_roster.yaml for the shape:
jobs:
- op: trim
input: ~/superwhisper/recordings/2026-06-05/output.wav
start: 0
duration: 22
output: ~/enroll/alice.wav
- op: normalize
input: ~/recordings/bob.m4a
output: ~/enroll/bob.wav
- op: concat
inputs: [~/clips/a.wav, ~/clips/b.wav]
output: ~/enroll/merged.wav
Flags
--apply— actually run ffmpeg (default: dry-run preview)--force— rebuild even if the output is up-to-date--json— machine-readable result array (for chaining)--suffix— output name when-ois omitted (normalize/trim batch mode)
Notes
- macOS:
brew install ffmpeg· Ubuntu:apt-get install -y ffmpeg. The script hard-fails on a missingffmpeg/ffproberather than running half a batch. - Stdlib only for the four ops;
reconcileneeds PyYAML. - Output dirs are created as needed. Inputs are glob-expanded (order-preserving, de-duped); a missing input surfaces as a per-job error, never silent.
License
Apache 2.0