text-processing-rs
Library Listed
Inverse Text Normalization (ITN) — convert spoken-form ASR output to written form
- Downloads
- 3,608
- Dependents
- 2
- Stars
- 48
- Forks
- 21
- Contributors
- 8
- Commits
- 132
- Latest release
- 0.2.2 ·
About
A Rust port of NVIDIA NeMo Text Processing supporting both Inverse Text Normalization (ITN) and Text Normalization (TN).
What it does
ITN: Spoken → Written
Converts spoken-form ASR output to written form:
| Input | Output |
|---|---|
| two hundred thirty two | 232 |
| five dollars and fifty cents | $5.50 |
| january fifth twenty twenty five | January 5, 2025 |
| quarter past two pm | 02:15 p.m. |
| one point five billion dollars | $1.5 billion |
| seventy two degrees fahrenheit | 72 °F |
TN: Written → Spoken
Converts written-form text to spoken form (useful for TTS preprocessing):
| Input | Output |
|---|---|
| 123 | one hundred twenty three |
| $5.50 | five dollars and fifty cents |
| January 5, 2025 | january fifth twenty twenty five |
| 2:30 PM | two thirty p m |
| 1st | first |
| 200 km/h | two hundred kilometers per hour |
Usage
Rust
use text_processing_rs::{normalize, tn_normalize};
// ITN: spoken → written
let result = normalize("two hundred");
assert_eq!(result, "200");
let result = normalize("five dollars and fifty cents");
assert_eq!(result, "$5.50");
// TN: written → spoken
let result = tn_normalize("$5.50");
assert_eq!(result, "five dollars and fifty cents");
let result = tn_normalize("123");
assert_eq!(result, "one hundred twenty three");
JavaScript (WASM)
Build wasm artifacts:
Read the full README
npm run wasm:build:node
npm run wasm:build:web
Node usage:
import * as wasm from "./pkg-node/text_processing_rs.js";
console.log(wasm.normalize("two hundred")); // "200"
console.log(wasm.tnNormalize("$5.50")); // "five dollars and fifty cents"
wasm.addRule("gee pee tee", "GPT");
console.log(wasm.normalize("gee pee tee")); // "GPT"
The generated npm package name is @fluidinference/text-processing-rs.
Web project usage (Vite / Next.js / webpack):
npm install @fluidinference/text-processing-rs
import init, * as wasm from "@fluidinference/text-processing-rs";
async function run() {
// Loads and initializes the .wasm module (required once at startup)
await init();
const itn = wasm.normalize("two hundred");
const tn = wasm.tnNormalize("$5.50");
console.log(itn); // "200"
console.log(tn); // "five dollars and fifty cents"
wasm.addRule("gee pee tee", "GPT");
console.log(wasm.normalize("gee pee tee")); // "GPT"
}
run();
If your framework supports top-level await, you can initialize at module load time:
import init, * as wasm from "@fluidinference/text-processing-rs";
await init();
Sentence-level normalization scans for normalizable spans within a larger sentence:
use text_processing_rs::{normalize_sentence, normalize_sentence_lang, tn_normalize_sentence};
// ITN sentence mode
let result = normalize_sentence("I have twenty one apples");
assert_eq!(result, "I have 21 apples");
// ITN sentence mode, language-aware ("en", "fr", "es", "de", "zh", "hi", "ja")
let result = normalize_sentence_lang("j'ai vingt et un ans", "fr");
assert_eq!(result, "j'ai 21 ans");
// TN sentence mode
let result = tn_normalize_sentence("I paid $5 for 23 items");
assert_eq!(result, "I paid five dollars for twenty three items");
Swift
import NemoTextProcessing
// ITN: spoken → written
let result = NemoTextProcessing.normalize("two hundred")
// "200"
// TN: written → spoken
let spoken = NemoTextProcessing.tnNormalize("$5.50")
// "five dollars and fifty cents"
// Sentence modes
let itn = NemoTextProcessing.normalizeSentence("I have twenty one apples")
// "I have 21 apples"
// Language-aware ITN sentence mode ("en", "fr", "es", "de", "zh", "hi", "ja")
let itnFr = NemoTextProcessing.normalizeSentence("j'ai vingt et un ans", language: "fr")
// "j'ai 21 ans"
let tn = NemoTextProcessing.tnNormalizeSentence("I paid $5 for 23 items")
// "I paid five dollars for twenty three items"
CLI
# ITN
nemo-itn two hundred thirty two # → 232
nemo-itn -s "I have twenty one apples" # → I have 21 apples
# TN
nemo-tn 123 # → one hundred twenty three
nemo-tn '$5.50' # → five dollars and fifty cents
nemo-tn -s 'I paid $5 for 23 items' # → I paid five dollars for twenty three items
# Pipe from stdin
echo "2:30 PM" | nemo-tn # → two thirty p m
Compatibility
ITN (Spoken → Written)
98.6% compatible with NeMo text processing test suite (1200/1217 tests passing).
| Category | Status |
|---|---|
| Cardinal numbers | 100% |
| Ordinal numbers | 100% |
| Decimal numbers | 100% |
| Money | 100% |
| Measurements | 100% |
| Dates | 100% |
| Time | 97% |
| Electronic (email/URL) | 96% |
| Telephone/IP | 96% |
| Whitelist terms | 100% |
TN (Written → Spoken)
| Category | Examples |
|---|---|
| Cardinal numbers | 123 → one hundred twenty three |
| Ordinal numbers | 1st → first, 21st → twenty first |
| Decimal numbers | 3.14 → three point one four |
| Money | $5.50 → five dollars and fifty cents |
| Measurements | 200 km/h → two hundred kilometers per hour |
| Dates | January 5, 2025 → january fifth twenty twenty five |
| Time | 2:30 PM → two thirty p m |
| Electronic (email/URL) | test@gmail.com → t e s t at g m a i l dot c o m |
| Telephone | 123-456-7890 → one two three, four five six, seven eight nine zero |
| Whitelist terms | Dr. → doctor, Mr. → mister |
Features
- ITN (Inverse Text Normalization): spoken → written form for ASR post-processing
- TN (Text Normalization): written → spoken form for TTS preprocessing
- Cardinal and ordinal number conversion (both directions)
- Decimal numbers with scale words (million, billion)
- Currency formatting (USD, GBP, EUR, JPY, and more)
- Measurements including temperature (°C, °F, K) and data rates (gbps)
- Date parsing (multiple formats) and decade verbalization (1980s → nineteen eighties)
- Time parsing with AM/PM, 24-hour format, and timezone preservation
- Email and URL normalization
- Phone numbers, IP addresses, SSN
- Case preservation for proper nouns and abbreviations
- Sentence-level normalization with sliding window span matching
- Custom rules for domain-specific terms
- C FFI for integration with Swift, Python, and other languages
Building
Rust
cargo build
cargo test
WASM + JavaScript
# Build + smoke test (Node) + build browser artifact
npm run wasm:ci
# Create a tarball from the browser package
npm run wasm:pack
# Publish browser package to npm (requires npm auth)
npm run wasm:publish
CLI Tools
# Build the Rust library (release, with FFI)
cargo build --release --target aarch64-apple-darwin --features ffi
# Build Swift CLI tools
cd swift-test && swift build
Binaries are at swift-test/.build/debug/nemo-itn and swift-test/.build/debug/nemo-tn.
Swift (XCFramework)
# Install Rust targets
rustup target add aarch64-apple-darwin x86_64-apple-darwin
rustup target add aarch64-apple-ios aarch64-apple-ios-sim
# Build XCFramework
./build-xcframework.sh
Output:
output/NemoTextProcessing.xcframework- Add to Xcode projectoutput/NemoTextProcessing.swift- Swift wrapper
License
Apache 2.0
Acknowledgments
This project is a Rust implementation based on the inverse text normalization grammars from NVIDIA NeMo Text Processing. All credit for the original algorithms and test cases goes to the NVIDIA NeMo team.
Compatibility
- Runs on
- GPU support unknown
What shows it
- no dependency or feature matches a backend row
- Native code
- None found
- No native code found
- Python bindings
- No Python binding crate found
- License
- Apache-2.0
Compare with similar projects
Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
Inverse Text Normalization (ITN) — convert spoken-form ASR output to written form |
3,608 downloads over 30 days | 2 | 48 | 0.2.2 | GPU support unknown | No native code found | Apache-2.0 |
|
parakeet-rs Listed
Fast ASR & Speaker Diarization with NVIDIA Parakeet via ONNX |
51,716 downloads over 30 days | 8 | 421 | 0.4.4 | CUDA, WebGPU, Metal, Vulkan | Binds native code: ort-sys (feature api-24) | Apache-2.0 OR MIT |
|
rustfst Listed
Library for constructing, combining, optimizing, and searching weighted finite-state transducers (FSTs). |
24,531 downloads over 30 days | 10 | 192 | 1.3.1 | GPU support unknown | No native code found | Apache-2.0 OR MIT |
|
tts-rs Listed
High-level Text-To-Speech (TTS) interface |
21,892 downloads over 30 days | 19 | 143 | 0.26.3 | GPU support unknown | Binds native code: speech-dispatcher-sys, tolk-sys (feature tolk) | MIT |
|
jpreprocess Listed
Japanese text preprocessor for Text-to-Speech application (OpenJTalk rewrite in rust language). |
14,491 downloads over 30 days | 7 | 61 | 0.15.0 | GPU support unknown | No native code found | BSD-3-Clause |
|
voxr New
Audio and speech on boostr: compressed-audio decode, resampling, DSP and grapheme to phoneme, with speech synthesis (Kokoro, VITS), voice cloning (VoxCPM2), transcription with word timings (Whisper), voice activity (Silero) and audio-text scoring (CLAP), on CPU or CUDA. |
642 downloads over 30 days | 2 | 2 | 0.9.1 | CUDA | No native code found | Apache-2.0 |
|
sherpa-rs Archived
Rust bindings to https://github.com/k2-fsa/sherpa-onnx |
9,888 downloads over 30 days | 4 | 313 | 0.6.8 | CUDA | Binds native code: sherpa-rs-sys. Build uses a native toolchain: bindgen, cmake | MIT |
All projects in Speech and audioAll projects in Text, embeddings and search
Why ListedNo archive, New or Featured rule places it, so it is Listed.
What it lacks for Featured
- It has 2 active dependents and 2 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days. The repository route reads 48 stars, 21 forks and 8 contributors. It needs 4,539 stars, 434 forks and 79 contributors together.
What else the check found
- The last activity is on 1 Nov 2026, 8 days ago. The rules expect an update within 365 days. Dormancy rule
Exact rules: Listed, Featured library. The check on applied thresholds version 9.
Every rule outcome, as the check records it
expected-interval: version 0.2.2 base 300, capped at 3 releases = 150, raised to the 365-day floor: E = 365 daysdormancy: last activity 2026-11-01, 8 days ago, E = 365: activefeatured: not featured: active_users 2 < 11 and new_adopters 2 < 9 and repository route stars 48 (needs 4539), forks 21 (needs 434), contributors 8 (needs 79)listed: listed: no archive, new or featured rule applies
Measurements and sources
Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.
Sources6 sources
- Description: the crates.io description
- crates.io database dump, fetched
- RustSec advisory database, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption2 active dependents, 2 new dependents in 365 days1 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | 2 | crates.io database dump | Yes | |
| New dependents (365 days) | 2 | crates.io database dump | Yes | |
| Peak active dependents | 2 | crates.io database dump | Yes | |
| Active dependents as a share of the peak | 1 | crates.io database dump | Yes | |
| Binary downloads per release | Not measured | Yes |
MaintenanceLatest human commit: 8 days ago3 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-11-01 | GitHub repository | Yes | |
| Latest release | 2026-04-27 | crates.io database dump | Yes | |
| First release | 2026-03-07 | crates.io database dump | Yes | |
| Latest version | 0.2.2 | crates.io database dump | Yes | |
| Days the oldest outside issue waits for a reply | 0 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 8 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | Yes | |
| Published docs | true | crates.io database dump | Yes | |
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityUnpatched vulnerabilities: none
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | none | RustSec advisory database | Yes | |
| RustSec unmaintained advisory | none | RustSec advisory database | Yes | |
| Deprecation notice | none | crates.io database dump | Yes | |
| Deprecated requirement | none | crates.io database dump | Yes |
Distribution3 releases, 3,608 downloads over 30 days5 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 3 | crates.io database dump | Yes | |
| Downloads over 30 days | 3608 | crates.io database dump | Yes | |
| Binary downloads over the last 3 releases | Not measured | Yes | ||
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | false | crates.io database dump | Yes | |
| Crate deleted from crates.io | false | crates.io database dump | Yes |
Repository48 stars, 21 forks, 8 contributors, 132 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 48 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 21 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 8 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 132 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | Apache-2.0 | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | GPU support unknown | crates.io database dump | No | |
| What shows each backend | no dependency or feature matches a backend row | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | No native code found | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | 2 | crates.io database dump | No |
Corrections and review history
No correction applies to this entry.
Judgments
A judgment enters only through an approved issue and a merged pull request.
No judgment applies to this entry.