Pitch-shift the audio of any media file by semitones. Works with MP4, MP3, WAV, and anything else ffmpeg supports.
Available as a CLI tool and a web UI.
- Node.js >= 18
- ffmpeg installed and in PATH (optional: ffmpeg with librubberband for higher quality)
npm install
npm run build# Via tsx (development)
npm run dev -- input.mp4 -s +3
# Via built JS
node dist/index.js input.mp4 -s +3 -o output.mp4
# Or link globally
npm link
pitch input.mp4 -s -2| Flag | Description |
|---|---|
-s, --semitones <n> |
Pitch shift in semitones (-24 to +24, supports decimals) |
-o, --output <path> |
Output file path (default: <input>.pitch+N.<ext>) |
npm start
# → http://localhost:3000Pick a file, set the semitones with the slider, and hit "Pitch Shift". The result downloads directly in the browser.
The port is configurable via the PORT environment variable:
PORT=8080 npm startsrc/
index.ts CLI entry point (commander)
server.ts Web server (node:http, no deps)
pitch.ts Core pitch-shift logic
ffmpeg.ts ffmpeg detection, probing, execution
utils.ts Helpers (semitone math, path generation)
public/
index.html Web UI (self-contained, inline CSS/JS)
- Calculates the frequency ratio from semitones:
2^(semitones/12) - If ffmpeg has librubberband, uses
rubberband=pitch=<ratio>(best quality, preserves tempo) - Otherwise, falls back to
asetrate+aresample+atempofilter chain - Video streams are copied without re-encoding (
-c:v copy)
See TODO.md for planned improvements.