Behind the library
Nobody writes these pages.
A school records a class and drops it in a folder. Within the hour it is compressed, transcribed, described, numbered, filed and announced, and the notes you read on a class page are the output of that job rather than anything typed afterwards. Embodied Yoga, who record in Rishikesh, have been running it weekly.
The weekly run
- 1
A scheduled job wakes up every hour
It runs on GitHub Actions, so it does not depend on anyone's laptop being open. It checks the upload folder, and if there is nothing new it exits in seconds.
- 2
The recording is compressed where it sits
A 74-minute class comes off the camera at 4.0GB. ffmpeg brings it to 220MB at 720p, about eighteen times smaller, which is the difference between a library that is affordable to serve and one that is not.
- 3
The audio is transcribed
A 16kHz mono track goes to Whisper. A 90-minute class costs a few pence to transcribe, so every class in the library has a full transcript whether or not anyone asks for one.
- 4
The transcript is read and the class is described
A language model reads the transcript and returns a title, a focus paragraph and the list of shapes and transitions. That is where every class page's copy comes from. It costs about $0.015 a class.
- 5
It is numbered, filed and published
The job works out the next number in the series, names the folder to match, attaches the description to the file, moves the recording into place and emails the team. A ten-minute test recording went from upload to filed in nine minutes on a GitHub runner.
What went wrong first
Most of the work was not connecting the services. It was the failures that only turn up once something runs unattended every hour.
- A robot cannot own a file
- Google service accounts have no storage quota, so the job could read the Drive and create folders but not write a single byte into it. Replacing the contents of an existing file turns out to be exempt, because ownership never changes. That one fact removed a second storage service and an extra account from the design.
- A full size is not a downloaded file
- Google Drive reports a file's real size before it has fetched any of it. The compression step was reading placeholders, finding the size already correct and skipping the work. It now waits for the bytes rather than the number.
- The notifier was the thing that broke
- Moving the job from a Mac to a Linux runner left a macOS-only notification command in place. Three runs failed at the last line, and because the failure was in the part that reports failures, nothing said so. Announcements are now non-fatal.
- Links get opened by machines
- Mail clients and link scanners open links before people do, so an approval or sign-in link that acts on a plain visit can be spent by software. These links land on a page and are only spent by the form on it.
This site
Hono on Cloudflare Workers, with D1 for members and classes and R2 for video. Video is streamed through the Worker rather than handed out as a signed URL, so membership is checked on every request including every seek. Payment is Stripe, and membership is only ever written by the webhook: coming back from the checkout page proves you returned, not that you paid.
Adding a school is a row and a price rather than a deployment: it brings its own slug, its own landing page, its own library and its own accent colour, and a membership at one school opens nothing at another. The 34 classes on the platform carry their real titles, lengths, recording dates and notes, straight out of the pipeline above.