speech-text-data-aligners / docs /ARCHITECTURE.md
pltobing's picture
chore(repo): finalize licensing and documentation
51e84d2
|
Raw History Blame Contribute Delete
7.33 kB
# Architecture
Speech-Text Data Aligners is a library-first forced-alignment framework. The core
contract accepts WAV audio plus a known, authoritative transcript and returns
backend-neutral timed words. The CLI is only a composition and presentation layer.
The mandatory design rules are defined in the
[modular architecture contract](MODULAR_ARCHITECTURE_CONTRACT.md) and the
[aligner engineering contract](ALIGNER_ENGINEERING_CONTRACT.md).
## Layers and Dependency Direction
```text
CLI --------------------> Application --------------------> Core
| ^
+----------> Data -------------+
+----------> Benchmarking -----+
+----------> Runtime ----------+
CLI -- lazy composition --> Concrete Backends
| |
+------------> Core
+------------> Runtime
```
In compact form:
```text
CLI -> Application -> Core
-> Data
-> Benchmarking
-> Runtime
Concrete Backends -> Core / Runtime
```
The enforced consequences are:
- Core does not import application, data, benchmarking, CLI, or concrete backends.
- Data and benchmarking do not depend on concrete backends.
- Application services receive an `AlignmentBackend` protocol instance; they do not
branch on NeMo, MFA, or WhisperX names.
- Concrete backend packages do not import one another.
- The registry stores lazy dotted factories so unavailable optional runtimes do not
break backend-neutral imports or sibling backends.
- The CLI delegates annotation and benchmarking to reusable Python services.
## Current Package Tree
```text
src/speech_text_data_aligners/
|-- __init__.py public backend-neutral facade
|-- application/
| |-- annotate.py annotation orchestration and publication policy
| `-- benchmark.py identical-request benchmark orchestration
|-- backends/
| |-- registry.py immutable lazy backend composition
| |-- nemo/
| | |-- backend.py neutral adapter
| | |-- config.py typed configuration
| | |-- manifest.py reference JSONL and output-manifest parsing
| | |-- runner.py isolated NFA execution
| | `-- ctm.py word CTM parsing and mapping
| |-- mfa/
| | |-- backend.py neutral adapter
| | |-- config.py typed configuration
| | |-- corpus.py temporary WAV/LAB corpus
| | |-- runner.py isolated MFA execution
| | `-- textgrid.py word-tier parsing and mapping
| `-- whisperx/
| |-- backend.py neutral adapter
| |-- config.py typed configuration
| |-- segments.py full-WAV authoritative segments
| |-- provider.py isolated-worker transport
| |-- worker.py lazy heavyweight native runtime
| `-- parser.py native word-dictionary parsing and mapping
|-- benchmarking/
| |-- metrics.py sparse-gold and pairwise metrics
| `-- reports.py JSON/CSV/Markdown report rendering
|-- cli/
| |-- main.py command dispatch
| |-- annotate.py annotation argument adapter
| `-- benchmark.py benchmark argument adapter
|-- core/
| |-- models.py immutable neutral values and provenance
| |-- protocols.py injected backend contracts
| |-- errors.py project exception taxonomy
| |-- normalization.py lexical plans and monotonic reconciliation
| |-- validation.py result and publication-path invariants
| `-- extraction.py six first/last output fields
|-- data/
| |-- audio.py WAV resolution and lightweight probing
| `-- metadata.py preserving, atomic CSV I/O
`-- runtime/
|-- process.py shell-free injected subprocess boundary
|-- artifacts.py temporary and retained artifact lifecycle
`-- receipts.py hashes and run provenance
```
Package-marker `__init__.py` files not shown above are deliberately empty. The root
`__init__.py` is the tested public facade.
## Backend Isolation and Native Containment
```text
PARENT PROCESS
Python caller or CLI
|
v
backend-neutral application API
|
v
AlignmentBackend protocol
|
v
concrete adapter (NeMo | MFA | WhisperX)
|
| injected process/provider boundary
v
+------------------------------------------------------+
| ISOLATED NATIVE RUNTIME |
| NeMo NFA process | MFA process | WhisperX worker |
| Heavy optional dependencies and model lifecycle |
+------------------------------------------------------+
|
| native files / native dictionaries
v
adapter-local builder, parser, and reconciliation
|
| only neutral records cross this point
v
AlignmentResult | AlignmentFailure | diagnostics | provenance
```
NeMo manifests, output manifests, and CTM rows remain inside
`backends.nemo`. MFA corpus labels and TextGrid objects remain inside
`backends.mfa`. WhisperX segment payloads and native result dictionaries remain
inside `backends.whisperx`. NeMo CTM, MFA TextGrid, and WhisperX native dictionaries
never escape their adapters; callers receive only backend-neutral models.
The parent process does not import heavyweight NeMo, MFA, WhisperX, Torch, or
Torchaudio packages. NeMo and MFA run through the shared shell-free process boundary.
WhisperX runs in a dedicated worker that imports its heavy stack only after invocation.
## Transcript-to-Result Data Flow
```text
authoritative transcript
|
v
backend-specific reference representation
|
v
native timed words
|
v
shared monotonic reconciliation
|
v
shared validation
|
v
AlignmentResult
```
The authoritative `en_transcript` remains unchanged throughout. A backend may
normalize or expand text only through a reversible plan that retains ownership of
original lexical words. Shared reconciliation requires complete monotonic coverage,
and shared validation rejects non-finite, negative, reversed, overlapping, incomplete,
or out-of-audio timestamps. It never clamps, interpolates, or invents a timestamp.
## Reuse and Composition
The root facade exposes reusable annotation and benchmark services. Applications may
inject any object satisfying `AlignmentBackend`, including a lightweight test or
custom backend. The default registry is a convenience for the CLI, not a dependency of
the application layer.
Benchmarking consumes the same neutral results as annotation. Native parsing,
transcript mapping, CSV I/O, metric calculation, report rendering, and process
execution each have one owning layer, so adding another adapter does not require
changes to established backend-neutral behavior.
Architecture is enforced by deterministic AST tests and Import Linter contracts. The
accepted audit and complete dependency evidence are recorded in the
[Stage 5 final acceptance report](STAGE_5_FINAL_ACCEPTANCE_REPORT.md).