Kampus Media · Audiobook production · Nov 4, 2026

Two audiobook pipelines,
one product.

How Edouard's eb-pipeline-2026 compares to our kampus-media-ai-processor, and a plan to merge them into a single hosted service.

eb-pipeline-2026 · local Python CLI kampus-media-ai-processor · hosted service
Agenda

Two parts

01

The difference

What each pipeline is, how it's built, where each one is stronger, and what's missing from their repo.

02

The plan

Merge into our hosted service: ground rules, target pipeline, phases 0 – 6, and the risks to watch.

01

The difference

Same goal and the same voice engine, but very different scope and depth.

At a glance

Same goal, different shapes

Theirs

Wide

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.

Shared

Common ground

  • French and Québécois French (fr-CA) audiobooks
  • Cartesia sonic-3 voices over WebSocket
  • Cartesia ink-whisper transcription to compare audio with the text
  • AI used only to point at text, never to rewrite it
Ours

Deep

A 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.

Architecture

How each one is built

Theirs · eb-pipeline-2026Ours · kampus-media-ai-processor
Runs asPython command-line tool (process.py) running 10 numbered stages on a book folderCloudflare Worker + Python container, with a database (D1), file storage (R2) and a web app
Who uses itWhoever runs it from a terminal on a MacAnyone with the web app: uploads, batches, Google Drive import, review and approve
StateJSON and TEI XML files in each book's intermediate/ folderDatabase tables: books, chapters, jobs, takes, notes, holds, batches
AI modelGemini 2.5 Pro via LiteLLMGrok via the Cursor SDK
VoicesMany voices (one per character), or a single narratorOne narrator voice per book
Size≈ 20k lines of Python≈ 10k lines (TypeScript + Python)
Pipelines

The steps, side by side

Theirs 10 file-based stages
01PDF → HTML
OCR
›
02Validate HTML
›
03Voice casting
›
04TEI enrichment
›
05Pronun­ciation
›
06Emotion tags
›
07Synthesize + master
›
08QA report
›
09Upload to stores
›
10Store check
Ours one hosted job per book
EXTRACTPDF layout reading
›
STRUCTUREAI finds chapters
›
GATEQuality check, hold for review
›
SPEAKABLEPrint → speech
›
PACINGAI places pauses
›
NARRATECartesia stream
›
LISTENTranscribe + compare
›
FIXRe-record bad paragraphs
›
DELIVERWeb app + zip
Only theirs does this Only ours does this (or does it much more deeply) Both do it
Their extra breadth sits at the edges: casting, enrichment, emotion tags, stores. Our extra depth sits in the middle: extraction, the quality gate, listening back and repair. Very little overlaps, which is why they merge well.
Strengths

Where theirs is ahead

Multiple voices

AI finds each character, infers gender and age, and casts a distinct Cartesia voice. We read every book with one narrator.

Expressive delivery

Per-sentence delivery notes become Cartesia <emotion/>, <speed/> and <volume/> tags. Our speed is fixed at 0.62.

Audible-ready audio

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.

Scanned PDFs + ePub

OCR (Docling + Apple Vision) for scans, and HTML/ePub input. We need a PDF with a text layer.

Pronunciation dictionary

≈ 18,000 fr-CA respellings (e.g. abaissèrent → abaissère) plus per-book overrides for proper nouns.

Stores + 2nd voice engine

Packaging for Audible, Apple, De Marque, Google Play, LivresAudio; Google Gemini as an alternative voice provider.

Strengths

Where ours is ahead

Text fidelity by design

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.

PDF cleanup by typography

Reads type size and position to drop footnotes, running heads, page numbers, ornaments and publisher pages.

Check before narration

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.

Automatic repair

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.

Runs as a service

Web app, batch uploads, Drive import, a queue limited to the number of streams Cartesia allows, crash recovery, cost tracking, safe deploys.

Takes and history

Every chapter take is kept with its settings, timings and listen-back report, so any version can be compared or restored.

Scorecard

Capability by capability

Capability
Theirs
Ours
Text in
PDF with a text layer
●
●
Scanned PDF (OCR)
●
—
HTML / ePub
●
—
Typography-aware cleanup
◐
●
Quality gate before narration
◐
●
Voice
Multiple voices
●
—
Emotion / speed / volume tags
●
—
AI-planned pauses
◐
●
Capability
Theirs
Ours
Voice (cont.)
Pronunciation dictionary
●
◐
Second voice provider
●
—
Audio quality
Listen back, word by word
●
●
Automatic paragraph repair
—
●
Audible (ACX) mastering
●
—
Operations
Hosted web app + queue
—
●
Store upload + checks
◐
—
●  yes◐  partial or not runnable from the repo—  no
Caveats

What's missing from their repo

  • It's a single commit, pushed today.
  • 10-checkBook is only a spec: there is no checkBook.py.
  • 09-uploadBook imports Str8Up-webapps, which isn't in the repo.
  • The samples/ books the README uses aren't included.
  • OCR uses Apple Vision, so stage 01 only runs on macOS.

What that means

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.

02

The plan

Fold their capabilities into our hosted service, one measured phase at a time. Distribution comes later.

The decision

Our hosted service is the base

Hosted

The end goal is a hosted service, and ours already is one: queue, web app, batches, recovery, costs.

Reliable

The parts that are hardest to retrofit (the quality gate, listen-back and repair) are already built and tested.

Compatible

Their AI enrichment follows our rule: answers must be exact excerpts of the text. That lets their steps slot straight in.

Their steps come in as modules inside our container. The container also gets a command-line entry point, so Edouard can still run the same code locally on a book folder.
Ground rules

Five rules for the merged design

1

The AI never writes words the listener hears

It returns positions, labels or exact excerpts. Any answer that doesn't match the text is thrown away, never fixed up.

2

The book text never changes

Only the copy sent to the voice is rewritten. Timings always map back to the printed page.

3

Every step saves its output

Like their intermediate/ folder, in R2, so any step can be inspected, re-run or compared.

4

Every AI step has a fallback

Printed headings, single narrator, neutral delivery. A stalled model never blocks a book.

5

No change ships without a measurement

The corpus becomes a benchmark: extraction checks plus listen-back accuracy.

Target pipeline

The merged version, step by step

01both

Ingest

Our PDF extractor, plus OCR for scanned PDFs, plus their HTML/ePub parser. All three give the same paragraph list.

02ours

Structure + gate

AI finds chapters; the check holds bad books before any voice is spent.

03theirs

Casting

AI finds the characters and picks voices. Editable in the web app. Single narrator stays the default.

04theirs

Annotation

Speaker, emotion, speed, volume, foreign passages and pronunciations, saved as JSON over our paragraphs (not TEI).

05both

Speakable copy

Our print-to-speech rules, then their 18k dictionary, then per-book overrides.

06both

Pacing + delivery

Our AI pause plan plus their emotion, speed and volume tags.

07both

Synthesis

Cartesia (one session per speaker run) or Google Gemini. Segment cache in R2: change one sentence, re-record one sentence.

08ours

Listen + repair

Re-record wrong paragraphs with the right voice. Their homophone matching cuts false flags.

09theirs

Mastering

Lossless master, repairs done on it, then −19 LUFS, 192 kbps, ID3 tags, credit tracks.

10theirs

Acoustic QA

Loudness, peak, noise floor, silences, dropouts. An Audible (ACX) failure holds the book.

11new

Storefront checks

Built from their spec: a scheduled ISBN lookup on Apple, Google Play, Audible, De Marque and LivresAudio.

12later

Distribution

Out of scope for now. Output keeps their <ISBN>_000.mp3 layout so their tooling can plug in.

Roadmap

Phases 0 – 6, in order of payoff

PHASE 0

Foundations

Package + CLI, step outputs in R2, ISBN column, benchmark corpus.

Mostly ours
Needs: nothing
PHASE 1

Audible-ready audio

Lossless masters, mastering chain, acoustic QA.

From their 07 + 08
Needs: phase 0
PHASE 2

More inputs, better pronunciation

OCR, HTML/ePub, dictionary + overrides.

From their 01, 02, 05
Needs: phase 0
PHASE 3

Expressive narrator

Annotation step, delivery tags, segment cache.

From their 04 + 06
Needs: phase 0
PHASE 4

Multiple voices

Casting, speaker switching, multi-voice repair. The largest phase.

From their 03 + ours
Needs: phase 3
PHASE 5

Google Gemini voices

Second provider, placed by ear.

From their 06B + 07B
Needs: phase 1
PHASE 6

Storefront checks

Can run in parallel at any time.

Their spec, new code
Needs: ISBN column
LATER

Distribution

Out of scope for now.

Needs: Str8Up-webapps from Edouard
Phases 0 and 1 go first, together: they share most of their code, and nothing else matters for sales until our audio passes Audible's checks.
Phases 0 – 1

Foundations and Audible-ready audio

Phase 0 Foundations

  • Reorganize container/ into a Python package with a CLI: one codebase for the service, the corpus and Edouard's machine
  • Save each step's output to R2, with a stage_runs table
  • Add an isbn column to books
  • Turn corpus.py into a benchmark: extraction + listen-back accuracy, seeded with our past problem books and their samples

Phase 1 Audible-ready audio

  • Keep a lossless master in R2; do repairs on it instead of re-encoding the MP3 each time
  • Mastering: click-free fades, exact silences, two-pass loudness (−19 LUFS, −3.5 dBTP), 192 kbps 44.1 kHz constant bitrate, ID3 tags, credit tracks
  • Acoustic QA in the web app's quality view; an Audible (ACX) failure holds the book

Why first: today's 128 kbps, unnormalized output would be rejected by Audible.

Phases 2 – 3

Better text in, more expression out

Phase 2 Inputs + pronunciation

  • OCR fallback when the text layer is missing or garbled: Docling with RapidOCR or Tesseract in the Linux container (Apple Vision is macOS-only), or a cloud OCR service if quality falls short
  • HTML/ePub ingest that produces our paragraph format, so the structure step and gate apply unchanged
  • 18k-entry dictionary, per-book overrides editable in the web app, listen-back taught the respellings

Turn the dictionary on only if listen-back accuracy goes up on the benchmark.

Phase 3 Expressive single narrator

  • Port their enrichment prompts behind our grok.py gateway, so there's one way to call AI models
  • Validate every excerpt against the text; drop anything that doesn't match
  • Emotion, speed and volume tags sent to Cartesia; segment cache in R2
  • On/off switch per book; start with the 6 primary emotions their own spec calls stable

Check first how inline <speed/> combines with our base speed of 0.62.

Phases 4 – 6

Many voices, two engines, live stores

Phase 4
Multiple voices

  • Casting step + casting editor in the web app
  • One Cartesia session per speaker run (a session can't change voice)
  • Word timings stitched across sessions so align.py keeps working
  • Repairs re-record with the right voice

Phase 5
Google Gemini voices

  • Provider setting per book
  • Their safety-filter workarounds ported
  • Gemini returns no word timings, so it relies on listen-back placing paragraphs by ear (already built)
  • Separate cost line per provider

Phase 6
Storefront checks

  • Built from their stage 10 spec
  • Scheduled ISBN lookups: listed, buyable, sample plays
  • Status panel per book
  • No dependencies, so it can run in parallel at any time
Risks

What to watch

Delivery tags could make it worse

Emotion 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.

More AI calls per book

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.

Storage

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.

Two AI stacks

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.

Next steps

What we need, and what happens next

From Edouard

  • The sample books (Le Fantôme de l'Opéra, Xavier Dolan L'indomptable) for the benchmark
  • His tested Cartesia and Google voice settings
  • Confirmation the pronunciation dictionary is tuned for the same Cartesia voices we use
  • Eventually, Str8Up-webapps for distribution

Next

  • Start Phases 0 and 1 together: lossless masters and step-output storage share most of their code
  • First milestone: a book from the corpus that passes Audible's (ACX) checks, with listen-back accuracy unchanged
  • Then pick between Phase 2 (inputs) and Phase 3 (expression) based on which books are waiting
Summary

Their breadth on
our foundation.

Keep our service, quality gate and repair loop. Bring in their voices, expression, mastering and inputs, one measured phase at a time.