Why a Local Recording Store Saves Bytes Instead of Blobs
I make Pianory, a browser piano learning and practice app. AI helped draft this article; I checked its claims against the current source and focused tests. Our local recording store has to persist browser audio safely.
I make Pianory, a browser piano learning and practice app. AI helped draft this article; I checked its claims against the current source and focused tests.
Our local recording store has to persist browser audio safely. The code documents a WebKit IndexedDB problem with Blob values in ephemeral sessions, including Safari private browsing and automated WebKit. New audio rows therefore store an ArrayBuffer of bytes, while an optional Blob field remains readable for older rows. This is a documented implementation choice, not a claim that a unit test reproduces the browser bug.
A subtle detail is when conversion happens. Saving awaits blob.arrayBuffer() before opening the read-write transaction. Awaiting asynchronous conversion inside a transaction risks letting IndexedDB auto-commit before the metadata and audio writes finish. Once bytes are ready, the store adds the metadata and audio row in one transaction.
At read time, it accepts the legacy Blob or reconstructs a Blob from bytes and the stored MIME type. It checks the recording ID, namespace, byte size and MIME type against metadata before returning it. That boundary keeps the application-facing object useful while the persisted form stays explicit.
The focused test checks save/read/export size and MIME type, namespace isolation, and that a failed audio write leaves no metadata row. I ran pnpm exec vitest run src/lib/recordings/store.spec.ts: seven tests passed. They use a mocked IndexedDB, so they do not independently establish Safari or WebKit behavior.
The practical lesson for media persistence is to decide the stored representation and transaction timing deliberately, then reconstruct and validate at the read boundary. Source: src/lib/recordings/store.ts and src/lib/recordings/store.spec.ts in the Pianory repository.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.