tape.card audio player

Studio

Read a book out loud. Stop between chapters — each stretch becomes a track, which is what makes “go back a bit” land somewhere sensible.

You may not need this page at all

Your phone’s own voice-memo app is already installed, already handles pausing and an incoming call in the middle of chapter three, and saves into storage that is already backed up — which matters, because the recordings are the only irreplaceable thing here. The box accepts what it produces: .m4a, .mp3, .wav, .ogg, .opus, .amr, .flac. Use this page when you want the one thing it adds: splitting a book into tracks as you read it, so “go back a bit” lands on a chapter instead of a guess.

0:00
Nothing recorded yet.

What this is doing

Recording straight to Opus, which the browser gives us for free through MediaRecorder. Speech at 24 kbps mono is about 180 kB a minute — a twenty-minute picture book is 3.6 MB, and a 32 GB SD card holds roughly 3,100 hours of it. Storage is not a constraint in this project and never will be.

Each stop-and-start writes a new track under /tape/audio/<title-id>/000.opus, 001.opus, and so on. The file paths are derived from the title id rather than typed, so a manifest can never point at a file that is not there.

Why this page cannot just send it

Two browser rules pull in opposite directions, and no configuration escapes them.

The microphone needs a secure context. On a plain-HTTP page navigator.mediaDevices is not restricted — it is undefined. So recording can only happen here, on HTTPS.

An HTTPS page cannot reach http://192.168.4.1. It is blocked as mixed content. The box has no public name and no way to renew a certificate, so it serves plain HTTP. Uploading can only happen from the box’s own origin.

So no single origin has both, and the two halves are joined by the one thing that works everywhere: a file. A file input needs no secure context, no permission and no network. The full argument, and the TLS trick that would one day collapse the two pages into one.