Skip to main content

🦭 SEA-G2P

image

Fast multilingual text-to-phoneme converter for South East Asian languages.
Vietnamese, Thai and Indonesian, all with English code-switching.

Author: Pham Nguyen Ngoc Bao

🚀 Used By

SEA-G2P is the core phonemization engine powering:

  • VieNeu-TTS: An advanced on-device Vietnamese Text-to-Speech model with instant voice cloning.

By using SEA-G2P, VieNeu-TTS achieves high-fidelity pronunciation and seamless Vietnamese-English code-switching.

Installation

pip install sea-g2p

Usage

Simple Pipeline

from sea_g2p import SEAPipeline

pipeline = SEAPipeline(lang="vi")

# Single text
result = pipeline.run("Giá SP500 hôm nay là 4.200,5 điểm.")
print(result)
#zˈaːɜ ˈɛɜt̪ pˈe nˈam tʃˈam hˈom nˈaj lˌaː2 bˈoɜn ŋˈi2n hˈaːj tʃˈam fˈəɪ4 nˈam ɗˈiɛ4m.

# Batch processing (Parallel)
texts = ["Giá cổ phiếu tăng từ $0.000045 lên $1,234.5678 trong 3.5×10^6 giao dịch.", "Hãy gửi email đến support@example.com."] * 1000
results = pipeline.run(texts)

Thai

Thai is written without spaces, so the Thai front end normalizes, segments, and looks words up in one pass. Latin runs go through the same English engine used elsewhere, so code-switched text comes out as a single phoneme string.

from sea_g2p import SEAPipeline

th = SEAPipeline(lang="th")

result = th.run("เขาฉลาดพอที่จะซ่อนสติปัญญา")
print(result)
#kʰaw˩˩˦ tɕʰa˨˩ laːt̚˨˩ pʰɔː˧ tʰiː˥˩ tɕaʔ˨˩ sɔːn˥˩ sa˨˩ ti˨˩ pan˧ jaː˧

result = th.run("ผมใช้ iPhone ราคา ฿1,250")
print(result)
#pʰom˩˩˦ tɕʰaj˦˥ ˈaɪfoʊn raː˧ kʰaː˧ nɯŋ˨˩ pʰan˧ sɔːŋ˩˩˦ rɔːj˦˥ haː˥˩ sip̚˨˩ baːt̚˨˩

# Normalization alone: numbers, Thai digits, dates, abbreviations
from sea_g2p import Normalizer

normalized = Normalizer(lang="th").normalize("วันที่ 6 ม.ค. ๒๕๖๐")
print(normalized)
#วันที่ หก มกราคม สองพันห้าร้อยหกสิบ

Thai phonemes use IPA with Chao tone letters (˧ mid, ˨˩ low, ˥˩ falling, ˦˥ high, ˩˩˦ rising), deliberately distinct from the digit convention used for Vietnamese tones so the two can share one inventory without ambiguity. Details in thai/README.md.

Indonesian

from sea_g2p import SEAPipeline

# not `id`: that shadows the built-in id()
idn = SEAPipeline(lang="id")

result = idn.run("dia cukup cerdas untuk menyembunyikan kecerdasannya")
print(result)
#di a t͡ʃu kup t͡ʃər das un tuʔ mə ɲəm bu ɲi kan kə t͡ʃər da san ɲa

result = idn.run("Saya membeli buku seharga Rp1.250.000")
print(result)
#sa ja məm bə li bu ku sə har ɡa sa tu d͡ʒu ta du a ra tus li ma pu luh ri bu ru pi ah

# chat contractions, which look like pronounceable words to a rule engine
from sea_g2p import Normalizer

normalized = Normalizer(lang="id").normalize("yg penting tdk lupa dgn tugasnya")
print(normalized)
#yang penting tidak lupa dengan tugasnya

Phonemes are grouped one syllable per space, the same convention the Vietnamese and Thai outputs use, so a downstream TTS sees one format for the whole library.

Indonesian spelling is regular except for one thing: ⟨e⟩ writes both /ə/ and /e/ and nothing distinguishes them. The dictionary settles it from KBBI, the official Indonesian dictionary, whose pronunciation field marks the schwa — see indo/README.md for how the sources were chosen and which approaches were measured and rejected.

Individual Modules

from sea_g2p import Normalizer, G2P

normalizer = Normalizer(lang="vi")
g2p = G2P(lang="vi")

# Automatic parallel processing when list is passed
texts = ["Giá cổ phiếu tăng từ $0.000045 lên $1,234.5678 trong 3.5×10^6 giao dịch.", "Hãy gửi email đến support@example.com."]
normalized = normalizer.normalize(texts)
print(normalized)
#['giá cổ phiếu tăng từ không chấm không không không không bốn lăm <en>u s d</en> lên một nghìn hai trăm ba mươi bốn phẩy năm sáu bảy tám <en>u s d</en> trong ba chấm năm nhân mười mũ sáu giao dịch.', 'hãy gửi email đến <en>support</en> a còng <en>example</en> chấm com.']
phonemes = g2p.convert(normalized)
print(phonemes)
#['zˈaːɜ kˈo4 fˈiɛɜw t̪ˈaŋ t̪ˌy2 xˌoŋ tʃˈəɜm xˌoŋ xˌoŋ xˌoŋ xˌoŋ bˈoɜn lˈam jˈuː ˈɛs dˈiː lˈen mˈo6t̪ ŋˈi2n hˈaːj tʃˈam bˈaː mˈyəj bˈoɜn fˈəɪ4 nˈam sˈaɜw bˈa4j t̪ˈaːɜm jˈuː ˈɛs dˈiː tʃˈɔŋ bˈaː tʃˈəɜm nˈam ɲˈən mˈyə2j mˈu5 sˈaɜw zˈaːw zˈi6c.', 'hˈa5j ɣˈy4j ˈiːmeɪl ɗˌeɜn səpˈɔːɹt ˈaː kˈɔ2ŋ ɛɡzˈæmpəl tʃˈəɜm kˈɔm.']

Features

  • Blazing Fast: Core engine rewritten in Rust with binary mmap lookup.
  • Multithreading: Automatic parallel processing using Rayon/Rust for batch inputs.
  • Zero Dependency: Pre-compiled wheels for Windows, Linux, and macOS.
  • Smart Normalization: Staged pipelines per language — 17 stages for Vietnamese (numbers, dates, units, formulas, technical terms), 8 for Thai (Thai digits ๐-๙, Buddhist-era dates, repetition, abbreviation table).
  • Thai word segmentation: no-space script handled with a 91,865-word dictionary and a unigram-cost dynamic program; boundary F1 0.987 against PyThaiNLP newmm.
  • Indonesian morphology: 172,557-word dictionary built from WikiPron and KBBI, extended by affix derivation, compounding and reduplication rather than by machine-generated guesses.
  • Never gives up on a word: Thai text outside the dictionary is read by orthographic rule, so new names and transliterations still get phonemes.
  • Bilingual Support: Handles mixed Vietnamese/English and Thai/English text seamlessly.
  • Markup tags: Wrap a span to control reading:
    • <en>...</en> — keep the content for the English phonemizer (e.g. <en>hello</en>).
    • <math>...</math> — read as a math formula: variable clusters are spelled letter-by-letter and operators/symbols are voiced, while function names (sin, cos, log, lim, ...) are preserved. <math>b² - 4ac</math>"bê bình phương trừ bốn a xê", <math>∫f dx</math>"tích phân ép đê ích".

📊 Performance

The following benchmarks were conducted on a dataset of 1,000,000 sentences:

Language Module Throughput
Vietnamese Normalizer ~41,000 sentences/s
Vietnamese G2P ~415,000 sentences/s
Vietnamese Full pipeline ~37,000 sentences/s
Thai Normalizer ~1,000,000 sentences/s
Thai Full pipeline (normalize + segment + G2P) ~180,000 sentences/s
Indonesian Full pipeline ~500,000 sentences/s

(Tested on CPython 3.12, Windows 11, Multithreaded)

Technical Architecture

SEA-G2P is designed for maximum performance in production environments:

  • Memory Mapping (mmap): Instead of loading a huge JSON/SQLite into RAM, we use a custom binary format (.bin) mapped directly into memory. This allows near-instant startup and extremely low memory overhead.
  • String Pooling: To minimize file size, all unique strings (words and phonemes) are stored once in a global string pool and referenced by 4-byte IDs.
  • Binary Search: Words are pre-sorted during the build process, allowing O(log n) lookup speeds directly on the memory-mapped data.
  • Per-language sections: one binary holds every language. Scripts that cannot collide with the Latin keyspace get their own namespace, so the Thai dictionary and its word frequencies ship beside the Vietnamese/English tables and can never fall out of sync with them.

Source layout

path contents
src/core/ language-agnostic: the mmap dictionary loader, the generic abbreviation table
src/lang/vi/ Vietnamese normalizer, number-to-words, syllable data
src/lang/en/ English frequency wordlist used to settle ambiguous splits
src/lang/th/ Thai normalizer, segmenter, rule-based G2P, number-to-words
src/lang/id/ Indonesian normalizer, rule-based G2P, number-to-words
src/g2p/ the shared engine for Latin-script text
tests/ *.rs integration tests and python/ end-to-end tests

For the binary format specification, see src/core/dict.rs. For the Thai and Indonesian data pipelines and their measurements, see thai/README.md and indo/README.md.

Development

To install for development purposes:

  1. Clone the repository:

    git clone https://github.com/pnnbao97/sea-g2p
    cd sea-g2p
    
  2. Install in editable mode:

    pip install -e .
    
  3. Run the tests:

    cargo test --release      # Rust integration tests
    python -m pytest tests/   # Python end-to-end tests
    

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sea_g2p-0.9.1.tar.gz (29.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

sea_g2p-0.9.1-cp310-abi3-win_amd64.whl (27.5 MB view details)

Uploaded CPython 3.10+Windows x86-64

sea_g2p-0.9.1-cp310-abi3-win32.whl (27.4 MB view details)

Uploaded CPython 3.10+Windows x86

sea_g2p-0.9.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (27.9 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

sea_g2p-0.9.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (28.0 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

sea_g2p-0.9.1-cp310-abi3-macosx_11_0_arm64.whl (27.8 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

sea_g2p-0.9.1-cp310-abi3-macosx_10_12_x86_64.whl (27.7 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file sea_g2p-0.9.1.tar.gz.

File metadata

  • Download URL: sea_g2p-0.9.1.tar.gz
  • Upload date:
  • Size: 29.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.15.0

File hashes

Hashes for sea_g2p-0.9.1.tar.gz
Algorithm Hash digest
SHA256 9ecb286442c34c96b8a2f20bf32196c168271600a8bad1cf23825d0e1b8fb3da
MD5 df513eacbd169d41adb8fc0e8de2da52
BLAKE2b-256 4ab7e1b8ea81f220a719a57c2e1da439cf0396f36f257bf145ba4502554f0823

See more details on using hashes here.

File details

Details for the file sea_g2p-0.9.1-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: sea_g2p-0.9.1-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 27.5 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.15.0

File hashes

Hashes for sea_g2p-0.9.1-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 b6d7c09afb83750abe61735ad2e60f5c20b4cdfac30b1b9b1904de9f64f10c32
MD5 456920f778700a73e751943ef9c5663d
BLAKE2b-256 982d4553efd8f340f332eb5976118e441b09ec95cf60d27fd1ad04240d885905

See more details on using hashes here.

File details

Details for the file sea_g2p-0.9.1-cp310-abi3-win32.whl.

File metadata

  • Download URL: sea_g2p-0.9.1-cp310-abi3-win32.whl
  • Upload date:
  • Size: 27.4 MB
  • Tags: CPython 3.10+, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.15.0

File hashes

Hashes for sea_g2p-0.9.1-cp310-abi3-win32.whl
Algorithm Hash digest
SHA256 3273e36cf2ff1883b88ed53dfe24d682c30b4d3efc6fe91d53acb0ff29f2f4ba
MD5 b2aa8722a2df34be6a25538189f799d5
BLAKE2b-256 7f3fdd035cfc623add72c81838490b01fda2c8f78df9de31d1ada74603ab9c18

See more details on using hashes here.

File details

Details for the file sea_g2p-0.9.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for sea_g2p-0.9.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d80682d652f080e0b3c3c33096e18823f98d1238a26805792443732286d2accf
MD5 112768cc722749d4c0148bad4642a3a1
BLAKE2b-256 b1710878a2f3fd3f827dc95c859e25d042bd98698f60d639e44405ac3f7adc68

See more details on using hashes here.

File details

Details for the file sea_g2p-0.9.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for sea_g2p-0.9.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 47d01f303093a287e63de9bfb067593425ef65a161c16532c41f45afbcd93fd2
MD5 5b001f42be55e447a6f0abcee38f765f
BLAKE2b-256 8ff36ad06ab44c872d7d07266965682067e89b8a79eb96ece78e5393792e886b

See more details on using hashes here.

File details

Details for the file sea_g2p-0.9.1-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sea_g2p-0.9.1-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 685c906b47d420c1e212afb1fad1bc3c36aa9f6729e3e72d2e0aa38fc78e4f44
MD5 1e73e306a623a07fd365f720771f7484
BLAKE2b-256 246ab5141611390a4dbac56ee9c06f1c364239e364022580d93ed5e76559a563

See more details on using hashes here.

File details

Details for the file sea_g2p-0.9.1-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for sea_g2p-0.9.1-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 80c1bac1c791f6d92a0f82e14bcd390dfc96538202b70bcd843c0103c9c760b2
MD5 a076ae1ca81bd01c34fe487eb759f9bf
BLAKE2b-256 19c50b1d3f831d4d872040150ce5e73daf69650ac8319f3e2a222c78c06d2f24

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.9.1 This release

7 files

0.9.0

7 files

0.8.9

7 files

0.8.8

7 files

0.8.7

7 files

0.8.6

7 files

0.8.5

7 files

0.8.4

7 files

0.8.3

7 files

0.8.2

7 files

0.8.1

7 files

0.8.0

7 files

0.7.33

7 files

0.7.32

7 files

0.7.31

7 files

0.7.30

7 files

0.7.29

7 files

0.7.28

7 files

0.7.27

7 files

0.7.26

7 files

0.7.25

7 files

0.7.24

7 files

0.7.23

7 files

0.7.22

7 files

0.7.21

7 files

0.7.20

7 files

0.7.19

7 files

0.7.18

7 files

0.7.17

7 files

0.7.16

7 files

0.7.15

7 files

0.7.14

7 files

0.7.13

7 files

0.7.12

7 files

0.7.11

7 files

0.7.10

7 files

0.7.9

7 files

0.7.8

7 files

0.7.7

7 files

0.7.6

7 files

0.7.5

9 files

0.7.4

9 files

0.7.3

9 files

0.7.2

9 files

0.7.1

9 files

0.7.0

9 files

0.6.12

9 files

0.6.11

9 files

0.6.10

9 files

0.6.9

9 files

0.6.8

9 files

0.6.7

9 files

0.6.6

9 files

0.6.5

9 files

0.6.4

9 files

0.6.3

9 files

0.6.2

9 files

0.6.1

9 files

0.6.0

9 files

0.5.9

9 files

0.5.8

9 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page