How Edouard's eb-pipeline-2026 compares to our kampus-media-ai-processor, and a plan to merge them into a single hosted service.
What each pipeline is, how it's built, where each one is stronger, and what's missing from their repo.
Merge into our hosted service: ground rules, target pipeline, phases 0 – 6, and the risks to watch.
Same goal and the same voice engine, but very different scope and depth.
A 10-stage local Python pipeline that runs from a PDF or HTML book all the way to the stores: multiple voices, emotion tags, mastering, upload and storefront checks.
fr-CA) audiobooksA hosted service that goes deeper on the hard middle: getting the text right, checking it before any voice money is spent, and automatically fixing what the voice got wrong.
| Theirs · eb-pipeline-2026 | Ours · kampus-media-ai-processor | |
|---|---|---|
| Runs as | Python command-line tool (process.py) running 10 numbered stages on a book folder | Cloudflare Worker + Python container, with a database (D1), file storage (R2) and a web app |
| Who uses it | Whoever runs it from a terminal on a Mac | Anyone with the web app: uploads, batches, Google Drive import, review and approve |
| State | JSON and TEI XML files in each book's intermediate/ folder | Database tables: books, chapters, jobs, takes, notes, holds, batches |
| AI model | Gemini 2.5 Pro via LiteLLM | Grok via the Cursor SDK |
| Voices | Many voices (one per character), or a single narrator | One narrator voice per book |
| Size | ≈ 20k lines of Python | ≈ 10k lines (TypeScript + Python) |
AI finds each character, infers gender and age, and casts a distinct Cartesia voice. We read every book with one narrator.
Per-sentence delivery notes become Cartesia <emotion/>, <speed/> and <volume/> tags. Our speed is fixed at 0.62.
192 kbps, −19 LUFS loudness, −3.5 dB peak, click-free joins. Ours is 128 kbps with no loudness step, which Audible (ACX) would reject.
OCR (Docling + Apple Vision) for scans, and HTML/ePub input. We need a PDF with a text layer.
≈ 18,000 fr-CA respellings (e.g. abaissèrent → abaissère) plus per-book overrides for proper nouns.
Packaging for Audible, Apple, De Marque, Google Play, LivresAudio; Google Gemini as an alternative voice provider.
The AI only returns paragraph positions, never words. A bad answer can misplace a chapter break but can't put invented prose in a book.
Reads type size and position to drop footnotes, running heads, page numbers, ornaments and publisher pages.
Compares chapters against the extracted text and holds the book if anything was lost, before a cent of voice is spent. A regression corpus guards every change.
Theirs writes a report for a person to read. Ours re-records the wrong paragraphs and splices them in, leaving the rest of the recording untouched.
Web app, batch uploads, Drive import, a queue limited to the number of streams Cartesia allows, crash recovery, cost tracking, safe deploys.
Every chapter take is kept with its settings, timings and listen-back report, so any version can be compared or restored.
10-checkBook is only a spec: there is no checkBook.py.09-uploadBook imports Str8Up-webapps, which isn't in the repo.samples/ books the README uses aren't included.The core path, from PDF to QA report, is real, working code that's worth porting. Distribution and storefront checks can't run from this repo alone, so for now they're a design to follow, not code to lift.
We read both codebases but didn't run theirs.
Fold their capabilities into our hosted service, one measured phase at a time. Distribution comes later.
The end goal is a hosted service, and ours already is one: queue, web app, batches, recovery, costs.
The parts that are hardest to retrofit (the quality gate, listen-back and repair) are already built and tested.
Their AI enrichment follows our rule: answers must be exact excerpts of the text. That lets their steps slot straight in.
It returns positions, labels or exact excerpts. Any answer that doesn't match the text is thrown away, never fixed up.
Only the copy sent to the voice is rewritten. Timings always map back to the printed page.
Like their intermediate/ folder, in R2, so any step can be inspected, re-run or compared.
Printed headings, single narrator, neutral delivery. A stalled model never blocks a book.
The corpus becomes a benchmark: extraction checks plus listen-back accuracy.
Our PDF extractor, plus OCR for scanned PDFs, plus their HTML/ePub parser. All three give the same paragraph list.
AI finds chapters; the check holds bad books before any voice is spent.
AI finds the characters and picks voices. Editable in the web app. Single narrator stays the default.
Speaker, emotion, speed, volume, foreign passages and pronunciations, saved as JSON over our paragraphs (not TEI).
Our print-to-speech rules, then their 18k dictionary, then per-book overrides.
Our AI pause plan plus their emotion, speed and volume tags.
Cartesia (one session per speaker run) or Google Gemini. Segment cache in R2: change one sentence, re-record one sentence.
Re-record wrong paragraphs with the right voice. Their homophone matching cuts false flags.
Lossless master, repairs done on it, then −19 LUFS, 192 kbps, ID3 tags, credit tracks.
Loudness, peak, noise floor, silences, dropouts. An Audible (ACX) failure holds the book.
Built from their spec: a scheduled ISBN lookup on Apple, Google Play, Audible, De Marque and LivresAudio.
Out of scope for now. Output keeps their <ISBN>_000.mp3 layout so their tooling can plug in.
Package + CLI, step outputs in R2, ISBN column, benchmark corpus.
Lossless masters, mastering chain, acoustic QA.
OCR, HTML/ePub, dictionary + overrides.
Annotation step, delivery tags, segment cache.
Casting, speaker switching, multi-voice repair. The largest phase.
Second provider, placed by ear.
Can run in parallel at any time.
Out of scope for now.
container/ into a Python package with a CLI: one codebase for the service, the corpus and Edouard's machinestage_runs tableisbn column to bookscorpus.py into a benchmark: extraction + listen-back accuracy, seeded with our past problem books and their samplesWhy first: today's 128 kbps, unnormalized output would be rejected by Audible.
Turn the dictionary on only if listen-back accuracy goes up on the benchmark.
grok.py gateway, so there's one way to call AI modelsCheck first how inline <speed/> combines with our base speed of 0.62.
align.py keeps workingEmotion tags can sound unstable over a 10-hour book. Every expressive feature stays behind a switch until benchmark accuracy and a side-by-side listening test favour it.
Annotation adds a pass over every sentence on top of structure and pacing. Each step needs a timeout, a fallback and a cost line, like the existing ones.
Lossless masters take ≈ 5 MB per minute, so ≈ 3 GB for a 10-hour book: cheap in R2, but over the Worker's 100 MB request limit. The existing multipart upload already handles that.
They use Gemini via LiteLLM; we use Grok via the Cursor SDK. Their prompts move behind our single gateway and get re-tested on the benchmark.
Str8Up-webapps for distributionKeep our service, quality gate and repair loop. Bring in their voices, expression, mastering and inputs, one measured phase at a time.