Journal

7 September 2026 · Jonathan · bookmentimenti-networkpodcastsstory

Bookmenti, two months in: from a scraper to our own transcription machine

Bookmenti, two months in: from a scraper to our own transcription machine

Two months ago Bookmenti was a web shell with an empty database. Today it has listened to more than 7,000 hours of podcasts and caught over 5,000 books. So I thought I’d tell you how that happened, in the order it happened, because almost nothing went the way I planned it.

Mid July: getting it online at all

On 15 July I finally got the app deployed on the box - a Bun and Hono backend, a React frontend, one container behind Coolify at bookmenti.com. It could log you in and that was about it. The next day I moved the database from a SQLite file to a real Postgres service, because I knew what was coming.

What was coming was transcripts. Bookmenti only works if it can read what people say on a show, and my plan at the time was to take the transcripts Spotify already makes. So I built a scraper: a patched Firefox in its own container, logged in with a throwaway account, routed through a VPN because Spotify hides the transcript tab from datacenter IPs. And it worked! Roughly one to three minutes per episode, about a megabyte each. But I knew from day one it was fragile. It broke their terms, it depended on a cookie I had to lift from my own browser at home, and one policy change at Spotify would have ended it.

19 July: the day the plan changed

While the scraper crawled I ran a proper experiment on the side. Could the box transcribe the audio itself? Earlier attempts had died because the NeMo stack needed about nine gigabytes of memory, way more than our server has to spare. But onnx-asr with the Parakeet TDT 0.6B model in int8, plus a voice activity detector to chunk the audio, ran a two-hour episode in 23 minutes on the CPU and peaked at 2.7 GB. That’s about five times faster than realtime, on hardware we already pay for.

Then I compared the output to Spotify’s transcript of the same episode. Clean speech was basically equal - 88.5% raw word agreement, and most of the disagreement was names that both of them got wrong differently. But the real finding was the timestamps. Spotify’s drifted by up to 147 seconds against the actual MP3 from the feed, because of ad insertion. Ours were exact by construction, since we transcribe the very file people listen to. For a product whose whole point is “jump to the moment the book comes up”, that decided it.

So on 19 July I scrapped the scraper and built the transcriber: a queue in SQLite, a poller that reads the RSS feeds every 30 minutes, two workers chewing through episodes newest first, and a little status server that pushes progress to Cloudflare so the site can show “transcribing now, ready in 40 minutes” on every episode. The same day I switched bookmenti.com over to a new frontend built on Astro and Cloudflare Workers. The old React bundle was 399 KB gzipped. The new podcast page, with the audio player and the karaoke word highlighting, is 23 KB, and none of it is a framework - it’s all just the web platform.

Finding the books

Transcripts are the easy half. The hard half is reading them and knowing that “the thing Tim mentioned about habits” is Atomic Habits and not just a word. So I built a benchmark first: 50 episodes, every book hand-verified, every evidence quote checked against its own transcript. Then I ran 24 combinations of model and prompt through it. Kimi K2.6 got the best F1 at 0.882 but it’s expensive. The winner in practice was a pipeline of small Gemini Flash-Lite calls: a wide finder, a mechanical filter for fabrications, a three-way judge, and a namer for the mentions where nobody says the title out loud. It reaches roughly the same quality for about half a cent per episode.

That went live the same afternoon. The first run took 27 episodes and found 66 mentions and 88 books, and for the first time the charts on the front page showed real data instead of placeholders. Then the boring, important weeks: covers that validate before they’re shown, a store link only when the ISBN really resolves on Amazon, slug URLs, chronological mention timelines per book, the quotes surfaced on every book page. And a logo, finally - a bookmark with a waveform inside it, made on 23 July.

Where it stands today

The numbers on the front page right now: 5,150 books, 10,618 mentions, 3,343 episodes, 100 podcasts, 7,306 hours of audio listened to. In August the whole thing also got a semantic search endpoint that AI assistants can talk to over MCP, with per-user keys and a daily quota, and every result links back to the exact second in the episode.

Honest limits: the extractor still runs on Gemini’s free tier, so it processes about a hundred episodes a day and the backlog is real. The cheap finder misses the deeply implied mentions - maybe two out of every sixty - that only the expensive models catch. And 100 shows is still a tiny slice of podcasting.

But here’s the thing I didn’t see coming in July. Building the transcriber for Bookmenti gave me thousands of hours of transcripts that were only ever read by a language model looking for book titles. That felt like a waste, and it turned into Podmenti, which I’ll write about next. Bookmenti was the idea that wouldn’t die. It turns out it was also the seed of something bigger, and I have loved every week of it.