You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(asr): audio transcription — Whisper via ONNX, pure Rust (closes Phase 7)
Ports docling's AsrPipeline (native-Whisper path, its ASR defaults:
whisper tiny, temperature-0 greedy, timestamps) as a new fleischwolf-asr
crate, Rust all the way down:
- symphonia demuxes/decodes the audio in-process — wav, mp3, flac, ogg,
aac, m4a, plus the audio track of mp4/mov; no ffmpeg. AVI is the one
container symphonia cannot demux (clear error).
- A ported log-mel front-end (80 Slaney mel filters, centered STFT,
Whisper's exact log/clamp/rescale), unit-tested against librosa
reference values.
- Whisper tiny encoder/decoder ONNX (onnx-community export) on ort —
the same runtime as layout/TableFormer/OCR. Greedy decoding implements
OpenAI's rules: special-token + non-speech-symbol suppression (the
default suppress_tokens="-1" set, derived by decode-scanning the
vocabulary), suppress_blank, forced initial timestamp with
max_initial_timestamp, timestamp pairing/monotonicity, the
timestamp-probability-mass rule, and the no-speech gate
(p_nospeech > 0.6 && avg_logprob < -1). 30-second windowing advances
seek to the last emitted timestamp.
- GPT-2 byte-level BPE decoding from vocab.json alone (no merges needed
for id→text). FLEISCHWOLF_ASR_LANG selects the language via
added_tokens.json (default en).
- Each segment renders as a `[time: start-end] text` paragraph (docling's
conversation form, Python float formatting).
Wiring: InputFormat::Audio now converts (the rejects-unimplemented test
moves to XmlDoclang, the one remaining backend-less format);
download_dependencies.sh fetches Whisper tiny from Hugging Face
(--no-asr to skip; DOCLING_ASR_{ENCODER,DECODER,VOCAB} override).
Verified end-to-end on tests/data/audio: all 12 audio fixtures + the
mp4/mov video fixtures transcribe the LibriVox sample correctly
("Shakespeare on scenery by Oscar Wilde…", [time: 0.0-10.0]); silence
yields whisper-tiny's documented model-faithful behavior. 8 new unit
tests (mel filterbank vs librosa, silence floor, timestamp rules, byte
decoder, resampler, wav decode, time formatting).
Docs: README (status, models table, try-it), MIGRATION (status:
migration complete; crate map; ML table; Phase 7 done), COMPARING (HTML
31/32 + refreshed gap table from the earlier commits).
@@ -293,22 +306,17 @@ tail of docling-specific quirks (below), each typically 1–2 lines.
293
306
294
307
### HTML
295
308
296
-
Against live docling: **10 / 32** exact, **12 / 32** whitespace-normalized. (The
297
-
older committed groundtruth would report a lower 6/32 — it predates docling's
298
-
padded-table serializer; see §A.) The remaining real differences trace to a
299
-
small number of *systematic* behaviours below, not to parsing errors — closing
300
-
each tends to fix several fixtures at once.
301
-
302
-
### Known divergences (tracked conformance gaps)
303
-
304
-
HTML — remaining gaps (4 of 32), all blocked or impractical:
309
+
**31 / 32** content-exact against the committed groundtruth (regenerated from
310
+
live docling); the table-padding divergence is deliberate (§4 of
311
+
`MIGRATION.md`). The four gaps once thought browser-bound have all been closed,
312
+
three of them **without any browser**:
305
313
306
-
| # |Difference | Example |Why it's blocked|
314
+
| # |Former gap | Example |Resolution|
307
315
|---|---|---|---|
308
-
| 1 |Browser-rendering visibility / nav suppression|`wiki_duck`|docling renders the page in a headless browser to drop nav/menu/sidebar cruft — not replicable from parsing alone|
309
-
| 2 |Key-value-pair / form extraction |`kvp_data_example`| docling's `form_region` subsystem builds key/marker/value relations using rendered bounding boxes and synthesizes `<!-- missing-text -->`placeholders — browser-bbox-dependent|
310
-
| 3 |Browser-hidden image (mobile nav) dropped|`hyperlink_02`| docling drops it via rendered visibility|
311
-
| 4 |Deeply-nested-table padding when flattened into a cell |`table_06`| docling pads the rich-cell text using rendered table bounding boxes; shallow nesting matches, ≥3-level deep padding does not|
316
+
| 1 |Key-value-pair / form extraction|`kvp_data_example`|detected statically from docling's `keyN` / `keyN_valueM` / `keyN_marker``id`-convention → `field_region`/`field_item` nodes + `<!-- missing-text -->` markers; no bboxes involved|
317
+
| 2 |Browser-hidden image (mobile nav) dropped |`hyperlink_02`| docling never emits inline image markers; restricting the wrapper→picture path to `<a>`and dropping inline images reproduces it statically|
318
+
| 3 |Deeply-nested-table cell padding |`table_06`|not rendered geometry after all — BeautifulSoup collapses whitespace-only text nodes to `\n`/`' '`, docling's `get_text` adds a trailing space per cell, and the `\n` runs flatten to spaces at render; ported byte-exact|
319
+
| 4 |Stylesheet-collapsed nav/menus |`wiki_duck`| CSS-cascade visibility genuinely needs a rendered page: available behind the `web-browser` feature / `--use-web-browser` (Rust-driven Chromium). The saved fixture's stylesheets are external + host-relative, so offline conversion cannot resolve them — the one remaining miss|
312
320
313
321
Markdown — **10/10**. Both former gaps fixed: `signature`/`stamp` → image blocks,
314
322
and the `2\.` escape via contiguity-aware text merging (pulldown splits both
| TableFormer (optional) |`models/tableformer/{encoder,decoder,bbox}.onnx` (+ `.data` sidecars where the export needs them) |
282
+
| Whisper tiny (audio/ASR; skip with `--no-asr`) |`models/asr/{encoder_model,decoder_model}.onnx`, `models/asr/vocab.json` (+ `added_tokens.json` for language selection) |
274
283
275
284
Idempotent — safe to re-run; it skips files already on disk. Pass `--force` to
276
285
re-fetch everything, or set `$FLEISCHWOLF_MODELS_URL` to fetch from a
277
-
different host (your own export, an internal mirror, …). pdfium is Linux x64
286
+
different host (your own export, an internal mirror, …); the Whisper assets
287
+
come from Hugging Face (`$FLEISCHWOLF_ASR_MODELS_URL` overrides, or point
288
+
`DOCLING_ASR_{ENCODER,DECODER,VOCAB}` at explicit files). pdfium is Linux x64
278
289
only for now — other platforms, or building the models from source, need
0 commit comments