Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CD Ripper

Rip an audio CD to FLAC and MP3 320, tag it from MusicBrainz, organise it, and play it — entirely in the browser.

There is no server. The disc is read through the File System Access API, FLAC and MP3 encoding run as WebAssembly (libFLAC and LAME) on your own machine, and the library index lives in IndexedDB. Nothing is uploaded: the only network calls are metadata lookups to MusicBrainz and cover art from the Cover Art Archive.

Requirements

  • Chrome, Edge, or another Chromium browser. Safari and Firefox do not implement the File System Access API, which the whole app is built on.
  • An HTTPS origin, or localhost. showDirectoryPicker only exists in a secure context. Opening index.html from file:// will not work — the page gets an opaque origin and cannot keep the folder permissions you grant.

Running it

./run.sh          # build if needed, then serve on http://127.0.0.1:8765
./run.sh --build  # force a rebuild first

Then:

  1. Add folder… in the Library tab, and point it at your music.
  2. Insert a CD, press Choose disc…, and pick it under Locations.

The library

A library folder is anything containing audio. The scanner walks up to six levels deep and treats any directory holding audio files as an album, reading tags from Vorbis comments (FLAC) or ID3 (MP3). It also recognises its own rip layout — FLAC/<artist>/<album> with a mirror under MP3/ — and pairs the two copies rather than indexing the album twice.

Several folders can be in the library at once. Each is scanned independently, so rescanning one never disturbs another, and removing one only drops it from the index — files on disk are never touched. The folder marked rips here is where new rips are written.

Chrome drops folder permission on every reload, so a folder may show needs permission until you reconnect it. Pressing play reconnects automatically, since a permission prompt is only allowed during a click.

The index is only an index. Every field it holds is read back out of the files' own tags or rip.log, so losing IndexedDB costs nothing but a rescan.

Layout

frontend/         the app — React, Vite, no backend
  src/lib/        disc reading, encoding, tagging, MusicBrainz, the store
backend/          the original Python/FastAPI implementation, kept for its tests
tools/            make_fixture_disc.py — builds a synthetic audio CD for testing

The Python backend predates the move into the browser and is no longer used at runtime; its test suite still covers the disc-ID, TOC and naming logic that the JavaScript ports from.

Testing without a drive

tools/make_fixture_disc.py builds a directory that is byte-compatible with a mounted audio CD — a real MusicBrainz TOC with generated tones for audio — so disc identification, tagging and organisation all exercise the genuine code path.

python tools/make_fixture_disc.py --search "Radiohead OK Computer"

Then pick fixtures/Audio CD as the disc.

Discs whose tracks the browser will not list

Some discs open to "this disc's tracks can't be listed". The audio is there and Chrome is hiding it: the File System Access API only enumerates files whose names are safe as portable path components, so a directory listing silently skips anything containing < > : " / \ | ? * — the characters Windows forbids — and asking for one by name is refused for the same reason.

macOS takes track names from a disc's CD-TEXT when it has any, so a classical release mounts as 1 Martinů: Symphony No. 1 - I. Moderato.aiff. That single colon makes every track invisible, while the .TOC.plist beside them, having a clean name, reads perfectly — which is why such a disc appears to have a table of contents and no audio.

That filter applies to names the page supplies. A file the user picks in the system dialog arrives by a different route and keeps its real name, so the app offers Select the tracks…: choose all of them (Cmd + A) and ripping proceeds normally. Track numbers come from the leading digits of each filename, which is what the TOC indexes by. The choice is remembered, so a reload does not ask again.

If that ever fails, tools/stage-disc.sh copies the disc under the neutral names macOS uses when there is no CD-TEXT:

./tools/stage-disc.sh              # auto-detects the mounted CD
./tools/stage-disc.sh --dry-run    # show the renaming first

Then press Choose disc… and pick the staged folder, which identifies and rips exactly as the disc would — at the cost of a few minutes and a duplicate of the whole disc on disk.

About

Rip audio CDs to FLAC and MP3 320 entirely in the browser — tagged from MusicBrainz, with no server and nothing uploaded.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages