# Changelog All notable changes to **TTS Voice Creator — Clone and Design** are documented here. Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned with [Semantic Versioning](https://semver.org/). --- ## [Unreleased] ### Added - **Paragraphs are fused across columns and pages for narration.** A paragraph that continues into the next column or onto a later page is now one block in the reader and the exported MP3, so a sentence is no longer cut in two at the seam. Words split at the seam are closed up (`jähr-` + `lich`); real compound hyphens are kept; headings, interview turns and finished paragraphs are never glued together. Highlighting still follows the region each sentence began in. - **Pronunciation & spelling panel (per article).** Acronyms are spoken from the article's language (decided once per article, with per-block override for quotations) using an extended built-in list, letter-by-letter spelling for `USB`/`HDMI`-style acronyms, and an editable per-article glossary. Unfamiliar acronyms are listed with their sentence, and the language model can decide expansion / letters / word from context. - **German and English spellchecker with fix-or-mark.** Unknown words are underlined in the review list and listed with suggestions per page and per article; click a suggestion (undoable), or *Keep* to add the word to the issue's dictionary. *Fix with language model* corrects only what passes strict guards (a dictionary suggestion, or a known word within two edits) and keeps names/terms; the whole-magazine quality check now runs the same pass and reports pages with words still marked. - **Clean up boxes now also fits text boxes to their text.** A side that cuts through letters grows (at most a letter or two, never into a neighbouring box) and empty margins are trimmed. Boxes you drew or resized by hand are never touched. It also runs automatically after **OCR again (this page)**; on page 61 of the measured issue it widened the left-column paragraphs ~10 pt to cover their text, cutting clipped edges from 7 to 0. A box never grows into a neighbouring box; when it gains whole lines, its text is re-read from the enlarged crop and replaced only by a longer reading that still starts with the old text. - **Inset pull quotes get a region of their own.** A display-coloured quote set into the text (detection wraps body text around it, so no box covered it) is found from the page image — a muted-colour blob of quote size on plain paper that no headline, figure or existing pull quote covers — and added as a *pull quote* region (never read aloud). Runs after **OCR again (this page)** and in **Clean up boxes**. On the measured 204-page issue it finds the two real quotes (pages 40 and 62) and one infographic (page 139, harmless and deletable). - **A paragraph that wraps around an inset pull quote is cut into a full-width part and a narrow part**, so its box no longer sits over the quote (as the right-hand column already did). The text lines are measured from the page image; the text is cut in proportion to line width at a space, within a word or two of the printed break, and the two pieces are read in order and rejoined for narration. A paragraph whose lines are all narrow just gets a narrower box. Runs after **OCR again (this page)** and in **Clean up boxes**; new pieces join the same articles. - **Review shows what is wrong with each page, on the page.** A *What is wrong on this page* panel (measured live from the page render, not from the last run) explains each problem in plain language with its own fix button, and marks it on the boxes: red dashed frame = text outside any box, orange edge = a box edge cutting through text, purple dashed = two boxes over the same text, yellow dotted = words that look mis-read, red wavy underline = unknown words. **Fix this page automatically** fits boxes, adds inset pull quotes, cuts paragraphs that wrap around them, finds missed text, re-reads suspicious words and (with a language model) fixes provable misspellings, with one Undo. - **The whole-magazine run now fixes as well as checks:** *Quality check / run* also fits boxes, finds inset pull quotes and cuts wrapped paragraphs on every page before the missed-text, re-read and spelling steps, and reports how many boxes it fixed. - **Text flow indicator.** Review draws a green arrow where an article's text carries on to the next box below or the next column, and chips where it continues on another page (*continues on page 111 ›*, *‹ from page 110*) plus *article starts / ends*; a *Show text flow* switch hides them. The reading text shows small markers (`↓`, `col ›`, `p.111 ›`) at the exact word where a paragraph crosses a box, column or page. Built from the same fusion the narration uses (`GET .../articles/{id}/flow`), so the arrows show what is read as one paragraph. On the measured issue: 97 column, 29 page and 21 below continuations. - **The whole-magazine button is now named *Auto-fix all pages*** (it fixes boxes, adds pull quotes, finds missed text, re-reads words and fixes provable misspellings on every page) and keeps a layout backup first. - **Continuation pages are linked into their articles automatically.** Detection often found an article's headline page and left the pages that follow as one-page stand-ins ("Page 61") that had to be approved one by one (79 of 132 articles on the measured issue). Text no article owns is now attached to the article running from the page before, unless that article already ended (a signed end such as `(hag)`), it is more than two pages back, or a headline with a byline/deck opens a new article there. Text you already approved (as part of a stand-in page) stays approved when it is merged; an approved article that gains text nobody approved goes back to *detected*, so nothing unreviewed is ever narrated. Stand-ins whose text moved are removed. Runs at import, in **Auto-fix all pages**, and on its own (`POST .../articles/auto-link`, undoable). - **Link an article to a page by hand:** *Link to page N — Article continues there / starts there* in the review panel picks the text that belongs (the paragraph that carries the sentence on, up to the next headline) and adds it ticked; undoable. - **Flow arrows follow the reading order:** a green arrow for every jump to another column and for a sentence running across boxes (dashed when a new paragraph starts, solid when a sentence continues), chips for page jumps. - **Much less noise:** the *Auto-fix all pages* report now lists what was fixed and only the pages that need a decision about their boxes (with a *Start with page N* button and compact page pills); pages with only words to check are collapsed and optional. The per-box "words look mis-read" marks are gone (spelling keeps its red wavy underline). The spellchecker knows ~130 company/product names, treats a word printed twice anywhere in the issue as vocabulary (missing-umlaut words such as `fur` stay flagged) and treats two unknown capitalised words in a row as a person's name: 871 → 625 findings on the measured issue. - **"Article ends" is only claimed when it is true.** An article counts as ended when it is signed off (`(rah) et`, `(hag)` — OCR noise after the code is tolerated) or when the next region, on the same page or at the top of the next, is a headline, deck or byline. Otherwise the last box shows a clickable *no end marker — link page N ›* chip that adds the next page's text in one click. - **Photos and graphics that no box covers get a figure region automatically** (a dense unboxed blob of real size; thin, line-structured ink is text and is left alone). New figures join the article with the most text on their page. - **Text that is not narratable page furniture stays out of linked articles:** running heads that recur on 3+ pages, lists of page numbers and reference/source lists are no longer pulled in when continuation pages are linked. An article made only of text you already approved becomes approved. - The per-page fix and the whole-issue run keep `quality_report.json` in step, so the thumbnail badges and the list of pages needing a decision match the layout as it is now. Running heads and adverts are no longer audited for clipped edges or overlaps. - **Articles nobody has reviewed are blue.** In the article list an unapproved, unrejected article has a blue background and edge and a *not reviewed* pill (approved keeps its green edge), so what still needs a person stands out. - **Overlapping boxes are fixed automatically.** Where a lower-ranked box runs over a higher-ranked one (headline > deck/byline > body > caption/sidebar/pull quote), the lower one is cut back to the largest part that no longer overlaps, unless that would leave under 40% of it (then both stay for a human). Hand-placed boxes and boxes of equal rank are never touched. - **Fewer false alarms and better fits:** a strip of solid ink beside a headline (a photo or filled panel behind it) is no longer counted as letters cut off; headline and deck boxes may grow up to 70 px sideways (body boxes 16 px); an inset pull-quote box that repeats text a box already holds becomes a duplicate. - **Rules and dotted leaders are not missed text.** The dots between a table-of-contents entry and its page number (and thin printed rules) are ink but no letters; the audit now ignores ink that is only a few pixel rows tall. - **Stacked boxes of a column now meet at the gap between two lines** (*seam mending*). Detection often cuts a column into slices that overlap or leave a line in the seam, so that line was in neither box and both reported a clipped edge. The shared boundary moves to the nearest blank gap (below the line for a paragraph that is still running, above it after a finished one, in the middle of an overlap); a line that had fallen into the seam is read on its own and attached to the box that now owns it, and the box takes the column's width. Page 32 of the measured issue: clipped edges 2 → 0 and the lost line "Entwicklungen auseinander. „KI ist bei uns in allen" is back in the text. 57 seams were mended across the issue. - **"Edge cuts text" needs the box's own lines.** Ink beside a left/right edge only counts as cut-off letters when it sits on the rows where the box itself has text and is intermittent (letters and gaps); a solid vertical line (a screenshot frame, a chart border, a photo edge) or ink between the box's lines does not, and a thin horizontal rule above or below is not a cut line. On the measured issue clipped edges fell from 82 to 48 and pages needing a decision from 53 to 42. - **Unboxed ink in or beside a picture, chart or advert is no longer reported as missed text** (labels of a chart, text set into a photo, an advert's own wording). ### Changed - **The Contents button is the first item of the sticky review bar**, so it stays in reach while scrolling a long page. - **The page thumbnail is the Review button.** In the thumbnail grid, clicking the (big) page image opens the page in review; the separate *Review* / *Review this page* buttons are gone. A page shared by two or more articles keeps one labelled *Review* button per article, so it stays clear which is meant. ### Fixed - **An approved page is no longer purple.** A page the quality check flagged stayed purple even after you approved its article; now your approval wins and the page shows its review colour (the warning badge on the card still lists what the check found). Purple means flagged *and* nobody has approved anything on the page. An old MP3 on an article nobody approved (left over from before pages were linked) no longer turns a page green either: audio only counts for approved articles. - **Reading order is now applied automatically after import, *OCR again* and every per-page fix**, not only by the manual *Fix reading order* button. Until now the order after import was whatever the vision/LLM step returned, so a column's short last box could be read after the whole other column; on the measured issue 101 of 204 pages had a saved order that differs from the column-aware order. Pages whose order you fixed by hand stay untouched, except after *OCR again*, when every region is new and a hand order can no longer apply. - **The review list shows each region's whole text**, not the first 220 characters, so every misspelling gets its red wavy underline (like a word processor). The engine's `[Non-Text]` marker and hairline boxes (under 3 pt tall) are now treated as OCR noise by *Clean up boxes* and after a page re-OCR, so they no longer show up as near-invisible regions. Fitted boxes keep a little air on grown sides. - **The quality check no longer flags correct text as "suspect OCR".** The word check guessed the language per fragment (`iPhones statt Token` read as English) and flagged valid German; it now uses the page's language, the same lenient German rules as the spellchecker, and treats words that recur on the page (names, brands) as vocabulary. Page 61 of the measured issue went from 11 suspect regions to 3 (one a genuinely truncated word), and the issue from 758 to 610 before the language fix's full effect. - Suspended compounds (`Programmier- und Hausaufgaben`) no longer lose their hyphen when regions are merged or layouts are grouped; already-ingested `Programmierund` shows in the spelling list with a one-click repair. ### Changed - `prepare_text_for_tts` accepts the article language and glossary; narration no longer guesses the language per fragment. --- ## [1.54.0] — 2026-09-27 ### Fixed - **Phone review layout:** the review toolbar no longer sticks to the top on narrow screens, where it covered most of the page image and made drawing regions or drag-selecting boxes start on a toolbar button. - **The region-type picker in review opens again** and **"Find missed text" / "Verify OCR text" work**: their click handlers were never exported to the page. A new unit test fails if any inline `mag*` handler is not exported. ### Added - The quality check now measures box edges at pixel level on all four sides and reports articles that claim the same text regions (duplicates that would be narrated more than once). - **Driving mode is now a podcast-style player.** Back/forward 15 seconds, a seek bar, a playback-speed button (0.75×–2×, remembered), and toggles to show or hide the article text as karaoke (whole article scrolls, current sentence and word highlighted) and the article's images. - **Full-page advertisements are recognised automatically.** A page with detected advertisement regions and no narratable text turns green (dashed), is never read aloud and is skipped by the quality check — no button or manual approval. (`PUT/DELETE /api/magazine/{id}/pages/{page}/advertisement` still exist to force the state.) - **Whole-magazine quality check.** The "Quality check / run" button (first in the contents toolbar) runs, per page: missed-text recovery, guarded OCR re-reading, and a pixel audit that reports ink outside every box, overlapping text boxes, and boxes clipping the first/last letters of a column. Pages that still need attention are listed with links into review; the report is saved as `quality_report.json`. Thumbnail cards gain quality-stage colours (clean = blue, problems = purple overriding review colours, with a clickable warning badge on the thumbnail listing what was found) and a live per-page indicator while the run works. The same indicator now covers every batch step (OCR/ingest, paragraph and advertisement recognition, figure fixing, audio rendering); each background job reports `{page|pages, step}` in its result. --- ## [1.53.5] — 2026-09-25 ### Added - **Magazine review now has two conservative OCR quality checks.** “Find missed text” uses an independent local pass to add only genuinely absent, non-overlapping regions; “Verify OCR text” uses language-aware spell checking only to flag suspicious regions and changes text only after a guarded re-read of the real page crop. - **Whole-magazine figure-boundary repair is available as an explicit batch action** in the contents view, while the review-page action is now page-scoped. ### Changed - **Magazine TTS expands known abbreviations without changing displayed OCR text.** In German, `KI` remains visible as printed but is spoken as “Künstliche Intelligenz.” - **Figure crops use pixel-level edge refinement for dense images.** Clear image boundaries are tight on all four sides instead of retaining coarse-grid paper margins on only some edges. ### Fixed - **Approve & Next advances to the immediately following physical page.** Page navigation also switches to the article that owns the visible page (or creates a page-scoped placeholder), preventing multi-page articles from being skipped and preventing approval from mutating the wrong article. - **Drop caps no longer introduce spaces or lose an entire opening line.** Split initials such as `S prechende`, `K I`, `A m`, and `B i s` are joined, and guarded second reads restore article-opening text even when the surviving remainder begins with a valid capitalized word. - **Semantic layout no longer creates giant paragraph boxes across two columns**, reorders run-on byline fragments, or labels ordinary lower-page paragraphs as captions when no figure is nearby. - **Narrow pull quotes between columns remain separate regions**, and figure/advertisement cleanup is less likely to absorb surrounding editorial text. - **All eight resize handles now have the same appearance.** The delete control no longer covers the north-east resize handle. --- ## [1.53.4] — 2026-09-24 ### Fixed - **Playwright's iPhone project can launch Chromium reliably.** The iPhone 13 device profile defaults to WebKit, but the shared system-browser override supplied a Chromium executable, causing Playwright to pass WebKit launch arguments to Chromium and lose the browser immediately. The mobile project now explicitly selects Chromium while retaining iPhone viewport, touch, scale-factor and user-agent emulation. --- ## [1.53.3] — 2026-09-24 ### Fixed - **Magazine: paragraphs flowing from one column into the next no longer create a giant union box over both columns.** The semantic stage keeps one physical box per column while still merging fragments within each individual column. Existing saved union boxes need “OCR again (this page)” or a fresh import because their original component boxes have already been discarded. --- ## [1.53.2] — 2026-09-24 ### Added - **Magazine: exported MP3s can use a second voice for printed interviews.** When exactly two recurring speaker labels are detected, the narrator and optional interview voice alternate turns without reading the labels aloud; ordinary prose containing colons is left alone. - **Magazine: generated-audio playlists now include a synchronized reading companion.** The playlist shows page, duration and played/partly-played/unplayed status, follows the current sentence and word using estimated timing, displays the article's figures alongside the transcript, remembers playback progress, and offers previous/play/next controls plus a progress display in driving mode. - **Magazine: title and issue metadata can be edited after import.** Exported filenames use a parsed issue year/month when available, and a new “Regenerate all MP3s” action rebuilds approved audio after metadata, text, pronunciation or voice changes. - **Magazine review: a page-level checkbox selects or clears every text and image region**, including an indeterminate state for partially selected pages. ### Changed - **Magazine narration now performs conservative OCR and pronunciation cleanup without changing displayed source text.** Printed line-break hyphens are removed, known German/English abbreviations are expanded for speech, and dictionary-backed missing German umlauts are restored only when unambiguous. - **Magazine page cards now show every article sharing the page with direct Review and Play actions**, and the article list is once again the default contents view. - **Voice searches now include display names and tags** in both the voice library and shared voice pickers. ### Fixed - **Magazine: oversized drop caps no longer make vision OCR omit the first line of a paragraph.** Suspicious lowercase starts receive a guarded local-OCR second opinion that is accepted only when it substantially matches the existing transcription. - **Magazine: internal headings on continuation pages no longer split a multi-page article into separate playlist items.** --- ## [1.53.0] — 2026-09-23 ### Added - **Magazine: the "All pages" grid is colour-coded by review status** — blank (no article yet, the normal mid-review state), red (has content, not reviewed), yellow (reviewed), green (reviewed and MP3 generated), grey (reviewed, nothing to narrate — a blank page or an ad). A small legend explains the colours. ### Fixed - **Magazine: "Review this page" on a page-coverage gap failed with "Method Not Allowed."** The endpoint it needs (`POST /api/magazine/{doc_id}/articles`, added alongside the gap-jump feature itself) had never actually been deployed with a container restart. --- ## [1.52.1] — 2026-09-22 ### Fixed - **Magazine: the page-grid column slider only changed card width, not thumbnail size.** A fixed thumbnail height meant fewer columns just left more empty space around the same small image instead of showing it bigger. The thumbnail now sizes by aspect ratio instead of a fixed height, so the slider is a real zoom. ### Removed - **Magazine: the page-coverage gap banner.** Redundant now that the "All pages" view's own per-card "no article" tag already says the same thing in context — it was a second warning repeating information already on screen. --- ## [1.52.0] — 2026-09-22 ### Changed - **Magazine: the article-thumbnail grid is gone; "Thumbnails" now means the page-by-page view.** An article is a poor thumbnail unit — it can span many pages or share one with others — so the toggle is back to two states: List (articles, for the title/author/duration/status detail that only makes sense per article) and the page-complete thumbnail grid added earlier. "All pages" is also now the default view on first open. - **Magazine: the page grid's column count is adjustable, 1-12**, via a slider next to the view toggle (shown only in that view) — a "zoom" between an overview of the whole issue and a close look at a few pages, remembered per browser. --- ## [1.51.0] — 2026-09-22 ### Fixed - **Magazine: reviewing a page-coverage gap borrowed an unrelated article as context.** Approve or "Not an article" on that page would have silently changed the status of whatever nearby article was borrowed, not said anything about the page actually being looked at. A gap page now gets its own dedicated article record (`POST /api/magazine/{doc_id}/articles`) instead. - **Magazine: "Approve" (now "Approve & Next") jumps to the next unresolved page, not the next article.** Advancing by article order alone was exactly what left page-coverage gaps invisible to this workflow in the first place; it now walks forward page by page and stops at whichever needs a decision next — an unreviewed article, or a page nothing covers yet — reusing the same one-click flow as the coverage-gap banner either way. --- ## [1.50.0] — 2026-09-22 ### Added - **Magazine: an "All pages" view.** Articles are a poor unit for "have I seen everything" — one can span many pages, several can share one page, and neither the list nor thumbnail view (both article-grained) can show either case. This adds a third view, cycled by the same toggle button, showing every page 1..N with its own thumbnail and whichever article(s) claim it (a page shared by two pieces shows both; a page claimed by none is flagged and links straight into Review there via the page-coverage jump added earlier). Articles remain the unit for narration, Approve, and audio export, which are inherently article-scoped — this is a complete-picture view alongside them, not a replacement. --- ## [1.49.0] — 2026-09-22 ### Added - **Magazine: a page-coverage gap finder.** Approve only ever advances to the next detected article, so a page never grouped into any article at all — an ad, a missed piece, anything detection skipped entirely — was never surfaced by that workflow. Confirmed live: 73 of 204 pages (36%) in one real issue belonged to no article whatsoever. The article list now shows a banner listing every such gap as page ranges, each a one-click jump straight into Review at that page (the review UI's own page navigation already isn't restricted to one article's pages — the missing piece was purely that nothing pointed there). --- ## [1.48.2] — 2026-09-22 ### Changed - **Magazine: "Generate all audio" progress now shows page number, not article count.** "Article 6/44" said little about how far through the magazine a run actually was; it now maps back to that article's own starting page and shows "p. 20 / 204" instead, falling back to the article count if a page number isn't available for some reason. --- ## [1.48.1] — 2026-09-22 ### Fixed - **Magazine: "Listen"/"Continue" on an article with a generated MP3 still went through the live reader.** It hit "Pick a narrator voice first" instead of just playing the file that already existed. Both buttons now check for a generated MP3 first and play it instantly through the playlist player — no voice pick, no synthesis wait; "Continue" resumes from the saved position when one exists. Only an article with no generated audio falls back to the live sentence-by-sentence reader. --- ## [1.48.0] — 2026-09-22 ### Added - **Magazine: "Generate all audio" resumes instead of redoing everything.** It now only renders approved articles that don't already have an MP3 — safe to click again after an aborted or partial run (a container restart mid-batch, closing the tab, etc.) without re-synthesising what already finished. --- ## [1.47.1] — 2026-09-22 ### Added - **Magazine: a progress bar for "Generate all audio."** The export status was a single line of text that jumped between "Article N/Total…" and a mid-render "sentence X/Y" — now a `` bar plus a plain "N / Total" count track the same numbers visually, parsed from the job's own progress text. --- ## [1.47.0] — 2026-09-22 ### Added - **Magazine: click a region's text to edit it, no pencil icon needed.** The pencil-icon editor (with its Save/Split-here/Cancel actions) still opens exactly the same way — this just adds the text itself as a faster path to it, since the row is a checkbox `