Metadata-Version: 2.4
Name: verbalis
Version: 0.1.0a1
Summary: Rewrites text the way it is read aloud: numbers, dates, symbols, abbreviations, and web addresses as words.
Keywords: tts,text-normalization,verbalization,speech
Author: Software Mansion
License-Expression: MIT
License-File: LICENSE
License-File: THIRD_PARTY_NOTICES.md
License-File: licenses/Unicode-3.0.txt
License-File: licenses/cn2an-MIT.txt
License-File: licenses/nlohmann-json-MIT.txt
Classifier: Programming Language :: C++
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.9
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"
Description-Content-Type: text/markdown

# Verbalis

Verbalis rewrites text the way it is read aloud, for text-to-speech front ends:

```
Dnia 12.03.2025 kupiłem 3 bilety.
→ Dnia dwunastego marca dwa tysiące dwudziestego piątego kupiłem trzy bilety.
```

Numbers, dates, times, phone numbers, money, units, symbols, abbreviations, and web addresses become words.
Languages: German, English (US, GB), Spanish, French, Hindi, Italian, Polish, Portuguese, and Chinese.

## C++

```cpp
#include <verbalis/verbalizer.h>

verbalis::Verbalizer english("en-us");
english.process("I bought 3 tickets for $49.");  // "I bought three tickets for forty-nine dollars."

// Turn steps off, or add readings of your own
verbalis::Verbalizer custom("en-us", {.numbers = false, .abbreviations = {{"approx.", "approximately"}}});

// Map the output back to the input: each change of [start, end), counted in code points
verbalis::Result result = english.process_with_changes("5 apples & pears");
```

Add it to a CMake project:

```cmake
add_subdirectory(verbalis/cpp)   # or FetchContent
target_link_libraries(your_target PRIVATE verbalis::verbalis)
```

## Python

```bash
pip install verbalis   # not yet published; to build from a checkout: pip install .
```

```python
from verbalis import Options, Verbalizer

english = Verbalizer("en-us")
english.process("I bought 3 tickets for $49.")  # "I bought three tickets for forty-nine dollars."

# Turn steps off, or add readings of your own
custom = Verbalizer("en-us", Options(numbers=False, abbreviations={"approx.": "approximately"}))

# Map the output back to the input: offsets count code points, so they index Python strings
text = "5 apples & pears"
for change in english.process_with_changes(text).changes:
    print(text[change.start : change.end], "->", change.replacement)
```

`Verbalizer("xx")` raises `ValueError` for an unsupported language; `Verbalizer.languages()` lists the supported
codes. A `Verbalizer` is immutable and releases the GIL while it works, so threads can share one instance.

A TypeScript package with the same API is in progress.

## Development

```bash
cmake -S cpp -B cpp/build -DVERBALIS_BUILD_TESTS=ON && cmake --build cpp/build -j
ctest --test-dir cpp/build --output-on-failure

uv venv && uv pip install ".[test]" && .venv/bin/pytest   # Python: build the extension, run tests/python
```

The parity tests check the C++ and Python output against `tests/parity/baseline/`, which every implementation must match.

## License

MIT. Verbalis is extracted from the text preprocessor of [Phonemis](https://github.com/IgorSwat/Phonemis). Third-party
notices are in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
