Tabfier
Transcribes guitar and bass recordings into playable tablature.
- React
- TypeScript
- TensorFlow.js
- Web Audio API
Transcribes a guitar or bass recording into playable, editable tablature, entirely in the browser — nothing is uploaded.
The problem
Transcribing your own guitar or bass playing into tab is normally manual, ear-by-ear work, or it means uploading a recording and waiting. Tabfier does it in the browser: record or import audio, get an editable tab out, nothing leaves the device.
The hard part isn’t detecting notes — it’s turning a detected pitch into a specific string and fret. The same note usually has several fingerings, and picking the wrong one produces a tab that’s technically correct and unplayable the way it’s written.
Approach and methodology
Built measured rather than tuned by ear: the project keeps a mechanism doc, a ranked list of known accuracy problems, and a results doc with real F1 scores against real guitar recordings — not just synthetic test audio, which overstates accuracy considerably (see Results).
Fret assignment is treated as an optimisation problem: the constants weighing “prefer a lower hand position” against “prefer fewer position shifts” were fit and cross-validated against real players’ actual fingering choices. Negative results are kept in the docs too — two attempts to close a gap in open-string usage both measurably hurt accuracy and were reverted, recorded rather than deleted.
Built with Claude Code as the coding agent. Every UI element carries a test id specifically so a change can be verified against the real, running app in a browser rather than trusted on faith.
Architecture
Nothing leaves the browser: transcription runs entirely client-side, and audio, notes, and edits are all stored locally. The only network request the app makes at all is fetching the model’s own weights from a CDN the first time it runs. Tab is drawn as hand-rolled SVG — no third-party notation engraver — and exports to a hand-written MIDI encoder and MusicXML.
The editor exposes real controls into that pipeline, not just a finished tab to look at: Simplify collapses a chord down to its lowest note; Fold octaves corrects octave-detection errors; Positional turns the hand-position-aware fret search on or off; Hand span sets how many frets that search will stretch across; Confidence and Min length filter out low-confidence or too-short detections before they ever reach the tab. Each one is a direct dial on a step of the pipeline above, not a separate feature bolted on afterward.
Results
The open question going in was how far a general-purpose, off-the-shelf pitch model could get on guitar specifically — an instrument where the same note usually has more than one right answer for where to play it.
| Metric | Synthetic audio | Real audio (GuitarSet) |
|---|---|---|
| Overall F1 | ~0.95 | 0.718 |
| Fret-assignment accuracy | — | 54.5% → 68.5% after two fixes |
| Bass F1 | ~0.39 | not yet measured |
A specific, counterintuitive result is documented rather than glossed over: sustained single notes — bends, vibrato — fragment worse than fast chord strums, the opposite of what “more notes at once should be harder” would predict.
Limitations
- Explicitly an experimental beta, with known accuracy problems.
- Bass transcription is the weakest measured area and hasn’t been verified on real bass recordings at all — an open question, not just a rough edge.
- The recording path has real, un-fixed accuracy costs: no input-level normalisation before the model’s fixed thresholds, and mic recording goes through a lossy codec then back.
- Manual tempo entry is the default. Automatic detection exists and works from the notes alone, but can’t always tell a tempo from its double or half.
- The model is several years old, general-purpose, and wasn’t built for guitar — weakest at exactly what guitar does a lot of: the same pitch on more than one string, bends, distortion.
Work in progress
Real-audio bass accuracy — currently a blind spot, not just a weak spot.
Raw audio capture (skipping the lossy codec round-trip) and input-level normalisation are both reasoned through, not yet built. Tap-tempo and audio-based tempo detection are on the list.
A guitar-specific model, or a simpler single-note pitch tracker for solo lines, is being considered as a way past the current model’s ceiling — not decided yet.
The tab renderer itself — drawing and editing a fretted-instrument staff from a plain list of notes — doesn’t depend on anything Tabfier-specific. Worth its own small library if a second use for it ever comes up.