piper-plus-g2p 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- piper_plus_g2p-0.2.0/.gitignore +114 -0
- piper_plus_g2p-0.2.0/CHANGELOG.md +41 -0
- piper_plus_g2p-0.2.0/CONTRIBUTING.md +55 -0
- piper_plus_g2p-0.2.0/LICENSE +21 -0
- piper_plus_g2p-0.2.0/PKG-INFO +179 -0
- piper_plus_g2p-0.2.0/README.md +131 -0
- piper_plus_g2p-0.2.0/THIRD_PARTY_LICENSES.md +51 -0
- piper_plus_g2p-0.2.0/benchmarks/bench_g2p.py +109 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/__init__.py +26 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/base.py +83 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/chinese.py +612 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/custom_dict.py +356 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/data/pua.json +102 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/encode/__init__.py +5 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/encode/encoder.py +206 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/encode/id_maps.py +384 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/encode/pua.py +106 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/english.py +427 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/french.py +988 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/japanese.py +267 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/korean.py +291 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/multilingual.py +326 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/portuguese.py +696 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/py.typed +0 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/registry.py +275 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/spanish.py +819 -0
- piper_plus_g2p-0.2.0/piper_plus_g2p/swedish.py +1161 -0
- piper_plus_g2p-0.2.0/pyproject.toml +79 -0
- piper_plus_g2p-0.2.0/tests/__init__.py +0 -0
- piper_plus_g2p-0.2.0/tests/conftest.py +101 -0
- piper_plus_g2p-0.2.0/tests/test_base.py +45 -0
- piper_plus_g2p-0.2.0/tests/test_chinese.py +76 -0
- piper_plus_g2p-0.2.0/tests/test_compat.py +149 -0
- piper_plus_g2p-0.2.0/tests/test_cross_platform.py +494 -0
- piper_plus_g2p-0.2.0/tests/test_custom_dict.py +245 -0
- piper_plus_g2p-0.2.0/tests/test_e2e.py +216 -0
- piper_plus_g2p-0.2.0/tests/test_edge_cases.py +271 -0
- piper_plus_g2p-0.2.0/tests/test_encode.py +253 -0
- piper_plus_g2p-0.2.0/tests/test_encoder.py +191 -0
- piper_plus_g2p-0.2.0/tests/test_english.py +77 -0
- piper_plus_g2p-0.2.0/tests/test_french.py +52 -0
- piper_plus_g2p-0.2.0/tests/test_japanese.py +235 -0
- piper_plus_g2p-0.2.0/tests/test_korean.py +605 -0
- piper_plus_g2p-0.2.0/tests/test_language_code.py +51 -0
- piper_plus_g2p-0.2.0/tests/test_multilingual.py +399 -0
- piper_plus_g2p-0.2.0/tests/test_portuguese.py +56 -0
- piper_plus_g2p-0.2.0/tests/test_registry.py +52 -0
- piper_plus_g2p-0.2.0/tests/test_segment_text.py +34 -0
- piper_plus_g2p-0.2.0/tests/test_snapshots.py +402 -0
- piper_plus_g2p-0.2.0/tests/test_spanish.py +48 -0
- piper_plus_g2p-0.2.0/tests/test_strict_mode.py +34 -0
- piper_plus_g2p-0.2.0/tests/test_swedish.py +568 -0
- piper_plus_g2p-0.2.0/tools/generate_golden.py +69 -0
- piper_plus_g2p-0.2.0/uv.lock +824 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
.DS_Store
|
|
2
|
+
.idea
|
|
3
|
+
*.log
|
|
4
|
+
tmp/
|
|
5
|
+
*.backup
|
|
6
|
+
requirements.txt.backup
|
|
7
|
+
|
|
8
|
+
*.py[cod]
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.egg
|
|
11
|
+
*.egg-info/
|
|
12
|
+
build
|
|
13
|
+
htmlcov
|
|
14
|
+
# Python package build artifacts
|
|
15
|
+
src/python_run/build/
|
|
16
|
+
src/python_run/dist/
|
|
17
|
+
|
|
18
|
+
/data/
|
|
19
|
+
/build/
|
|
20
|
+
/build-*/
|
|
21
|
+
/local/
|
|
22
|
+
/dist/
|
|
23
|
+
/lib/
|
|
24
|
+
/install/
|
|
25
|
+
/download/
|
|
26
|
+
/p/
|
|
27
|
+
/o/
|
|
28
|
+
/f/
|
|
29
|
+
/s/
|
|
30
|
+
*.so
|
|
31
|
+
|
|
32
|
+
.venv/
|
|
33
|
+
lightning_logs/
|
|
34
|
+
|
|
35
|
+
# Claude settings
|
|
36
|
+
.claude/*
|
|
37
|
+
!.claude/commands/
|
|
38
|
+
settings.local.json
|
|
39
|
+
|
|
40
|
+
# Generated audio files
|
|
41
|
+
*.wav
|
|
42
|
+
!test/**/*.wav
|
|
43
|
+
|
|
44
|
+
# Test artifacts
|
|
45
|
+
test_piper/
|
|
46
|
+
test_build/
|
|
47
|
+
test_windows_build/
|
|
48
|
+
test_results/
|
|
49
|
+
test_ci_binaries/
|
|
50
|
+
build_log.zip
|
|
51
|
+
# Root test files (should be in src/cpp/tests or src/python/tests)
|
|
52
|
+
/test_*.cpp
|
|
53
|
+
/test_*.c
|
|
54
|
+
/test_*.py
|
|
55
|
+
/test_*.sh
|
|
56
|
+
/test_*
|
|
57
|
+
!test/
|
|
58
|
+
|
|
59
|
+
# Package build artifacts
|
|
60
|
+
nupkgs/
|
|
61
|
+
publish_test/
|
|
62
|
+
# Test logs
|
|
63
|
+
*.log
|
|
64
|
+
|
|
65
|
+
# Benchmark results
|
|
66
|
+
benchmark_results*.json
|
|
67
|
+
streaming_comparison_results.json
|
|
68
|
+
|
|
69
|
+
# Windows build artifacts
|
|
70
|
+
*.dll
|
|
71
|
+
*.exe
|
|
72
|
+
windows_build_artifacts/
|
|
73
|
+
CLAUDE.md
|
|
74
|
+
|
|
75
|
+
# Rust build artifacts
|
|
76
|
+
src/rust/target/
|
|
77
|
+
src/rust/piper-python/target/
|
|
78
|
+
src/rust/piper-python/Cargo.lock
|
|
79
|
+
|
|
80
|
+
# WebAssembly temp directories
|
|
81
|
+
src/wasm/openjtalk-web/temp/
|
|
82
|
+
src/wasm/openjtalk-web/tools/
|
|
83
|
+
|
|
84
|
+
# Debug and development scripts
|
|
85
|
+
scripts/debug/
|
|
86
|
+
debug_*.py
|
|
87
|
+
test_phoneme*.py
|
|
88
|
+
verify_*.py
|
|
89
|
+
analyze_*.py
|
|
90
|
+
check_*.py
|
|
91
|
+
create_comprehensive_*.py
|
|
92
|
+
add_missing_*.py
|
|
93
|
+
retrain_*.py
|
|
94
|
+
comprehensive_*.py
|
|
95
|
+
|
|
96
|
+
# Training datasets and downloaded models
|
|
97
|
+
datasets/
|
|
98
|
+
models/
|
|
99
|
+
|
|
100
|
+
# Local working files
|
|
101
|
+
checkpoints/
|
|
102
|
+
output/
|
|
103
|
+
pip-test/
|
|
104
|
+
upiper_comparison_samples/
|
|
105
|
+
compare_phonemes.txt
|
|
106
|
+
phoneme_map.txt
|
|
107
|
+
training_phonemes.txt
|
|
108
|
+
id_check.txt
|
|
109
|
+
sh_check.txt
|
|
110
|
+
generate_upiper_samples.py
|
|
111
|
+
nul
|
|
112
|
+
test/models/tsukuyomi-chan/
|
|
113
|
+
docs/development/usability-issues-2026-03.md
|
|
114
|
+
src/rust/target/*
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-04-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
#### Languages
|
|
13
|
+
- 7 languages: JA (pyopenjtalk), EN (g2p-en), ZH (pypinyin), KO (g2pk2), ES, FR, PT (rule-based)
|
|
14
|
+
- All dependencies are GPL-free (MIT / Apache-2.0 / BSD-3-Clause)
|
|
15
|
+
|
|
16
|
+
#### Core API
|
|
17
|
+
- `Phonemizer` ABC with IPA-first design: `phonemize()` returns clean IPA tokens, encoding is a separate step
|
|
18
|
+
- `phonemize_with_prosody()` for languages that support prosody features (e.g., Japanese A1/A2/A3)
|
|
19
|
+
- `PhonemizerRegistry` with auto-discovery and `entry_points` plugin support for third-party phonemizer extensions
|
|
20
|
+
- `MultilingualPhonemizer` with Unicode-based language detection (`UnicodeLanguageDetector`)
|
|
21
|
+
- Composite language code support (e.g., `"ja-en-zh"`) for multilingual models
|
|
22
|
+
|
|
23
|
+
#### Encoding
|
|
24
|
+
- `PiperEncoder` for phoneme ID encoding compatible with Piper TTS models
|
|
25
|
+
- PUA mapping (87 entries) as canonical `pua.json` shared with C#/Rust implementations
|
|
26
|
+
- `phoneme_id_map` loading with BOS/EOS/padding token handling
|
|
27
|
+
|
|
28
|
+
#### Dictionaries
|
|
29
|
+
- `CustomDictionary` with JSON v1.0/v2.0 format support (compatible with C++/Rust implementations)
|
|
30
|
+
|
|
31
|
+
#### Safety
|
|
32
|
+
- Input sanitization: `MAX_INPUT_LENGTH=10000` limit and control character stripping
|
|
33
|
+
|
|
34
|
+
#### Testing & CI
|
|
35
|
+
- 170+ test cases
|
|
36
|
+
- GitHub Actions CI (3 OS x 2 Python)
|
|
37
|
+
|
|
38
|
+
### Architecture
|
|
39
|
+
- IPA-first: `phonemize()` returns clean IPA tokens; encoding to integer IDs is handled separately by `PiperEncoder`
|
|
40
|
+
- GPL-free: no eSpeak-ng dependency; all runtime dependencies are MIT/Apache-2.0/BSD-3-Clause
|
|
41
|
+
- Plugin system via setuptools `entry_points` (`piper_plus_g2p.phonemizers` group)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Contributing to piper-g2p
|
|
2
|
+
|
|
3
|
+
## Development Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
cd src/python/g2p
|
|
7
|
+
uv sync --extra all --extra dev
|
|
8
|
+
uv run pytest # run the full test suite
|
|
9
|
+
uv run ruff check piper_plus_g2p/ # lint
|
|
10
|
+
uv run mypy piper_plus_g2p/ # type-check
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## How to Add a New Language
|
|
14
|
+
|
|
15
|
+
1. **Create `piper_plus_g2p/<lang>.py`** -- subclass `Phonemizer` (from `piper_plus_g2p.base`).
|
|
16
|
+
2. **Implement `phonemize_with_prosody()`** -- return `(tokens, prosody)` where
|
|
17
|
+
`tokens` is a list of IPA strings and `prosody` is a list of `ProsodyInfo | None`.
|
|
18
|
+
3. **Create `tests/test_<lang>.py`** with at least 4 tests: basic phonemization,
|
|
19
|
+
prosody values, empty input, and edge cases. If the language needs an optional
|
|
20
|
+
dependency, add a `requires_<lang>` skip marker in `tests/conftest.py`.
|
|
21
|
+
4. **Update `pyproject.toml`** -- add the language code under
|
|
22
|
+
`[project.optional-dependencies]` and include any new dependency in the `all` extra.
|
|
23
|
+
5. **Register the phonemizer** -- add a `(code, module, class)` tuple to
|
|
24
|
+
`_LANGUAGE_TABLE` in `piper_plus_g2p/registry.py`, then open a PR.
|
|
25
|
+
|
|
26
|
+
## Plugin System (entry_points)
|
|
27
|
+
|
|
28
|
+
External packages can register phonemizers without modifying this repo.
|
|
29
|
+
In your package's `pyproject.toml`:
|
|
30
|
+
|
|
31
|
+
```toml
|
|
32
|
+
[project.entry-points."piper_plus_g2p.phonemizers"]
|
|
33
|
+
xx = "my_package:MyPhonemizer"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The registry discovers these at import time via `importlib.metadata.entry_points`.
|
|
37
|
+
|
|
38
|
+
## Code Style
|
|
39
|
+
|
|
40
|
+
- **Formatter/linter**: ruff (line-length 88, target Python 3.11).
|
|
41
|
+
- **Type checking**: mypy with `ignore_missing_imports = true`.
|
|
42
|
+
- Keep each language module self-contained; shared utilities go in `base.py`.
|
|
43
|
+
|
|
44
|
+
## Testing
|
|
45
|
+
|
|
46
|
+
- Framework: **pytest**
|
|
47
|
+
- Skip markers: `requires_ja`, `requires_en`, `requires_zh`, `requires_ko`
|
|
48
|
+
(defined in `tests/conftest.py`) for tests that need optional dependencies.
|
|
49
|
+
- CI runs on 3 OS (Linux, macOS, Windows) x 2 Python versions.
|
|
50
|
+
|
|
51
|
+
## Pull Requests
|
|
52
|
+
|
|
53
|
+
- One language per PR when possible.
|
|
54
|
+
- Include before/after phonemization examples in the PR description.
|
|
55
|
+
- All CI checks must pass before merge.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 piper-plus contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: piper-plus-g2p
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Multilingual G2P (Grapheme-to-Phoneme) for TTS — eSpeak-ng free, MIT licensed
|
|
5
|
+
Project-URL: Homepage, https://github.com/ayutaz/piper-plus
|
|
6
|
+
Project-URL: Repository, https://github.com/ayutaz/piper-plus
|
|
7
|
+
Project-URL: Issues, https://github.com/ayutaz/piper-plus/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/ayutaz/piper-plus/tree/dev/src/python/g2p#readme
|
|
9
|
+
Author: piper-plus contributors
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: g2p,grapheme-to-phoneme,ipa,phonemizer,tts
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Provides-Extra: all
|
|
26
|
+
Requires-Dist: g2p-en<3,>=2.1.0; extra == 'all'
|
|
27
|
+
Requires-Dist: g2pk2<1,>=0.0.3; extra == 'all'
|
|
28
|
+
Requires-Dist: pyopenjtalk-plus<1,>=0.3; extra == 'all'
|
|
29
|
+
Requires-Dist: pypinyin<1,>=0.55.0; extra == 'all'
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: mypy>=1.13; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=7.4; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
35
|
+
Provides-Extra: en
|
|
36
|
+
Requires-Dist: g2p-en<3,>=2.1.0; extra == 'en'
|
|
37
|
+
Provides-Extra: es
|
|
38
|
+
Provides-Extra: fr
|
|
39
|
+
Provides-Extra: ja
|
|
40
|
+
Requires-Dist: pyopenjtalk-plus<1,>=0.3; extra == 'ja'
|
|
41
|
+
Provides-Extra: ko
|
|
42
|
+
Requires-Dist: g2pk2<1,>=0.0.3; extra == 'ko'
|
|
43
|
+
Provides-Extra: pt
|
|
44
|
+
Provides-Extra: sv
|
|
45
|
+
Provides-Extra: zh
|
|
46
|
+
Requires-Dist: pypinyin<1,>=0.55.0; extra == 'zh'
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
|
|
49
|
+
# piper-plus-g2p
|
|
50
|
+
|
|
51
|
+
Multilingual G2P (Grapheme-to-Phoneme) for TTS. eSpeak-ng free. MIT licensed. 8 languages.
|
|
52
|
+
|
|
53
|
+
**Standalone package** — piper-plus TTS エンジンなしで G2P 単体として利用可能です。任意の TTS エンジンと組み合わせて使えます。
|
|
54
|
+
|
|
55
|
+
## Why piper-plus-g2p?
|
|
56
|
+
|
|
57
|
+
- **MIT licensed** -- no eSpeak-ng (GPL) dependency in your TTS pipeline
|
|
58
|
+
- **8 languages** -- JA, EN, ZH, KO, ES, FR, PT, SV with consistent IPA output
|
|
59
|
+
- **IPA-first design** -- returns pure IPA token sequences, ready for any TTS model
|
|
60
|
+
|
|
61
|
+
## Comparison
|
|
62
|
+
|
|
63
|
+
| | piper-plus-g2p | phonemizer | gruut | Misaki |
|
|
64
|
+
|---|---|---|---|---|
|
|
65
|
+
| License | MIT | GPL (eSpeak-ng) | MIT | Apache-2.0 |
|
|
66
|
+
| Languages | 8 | 100+ | 20+ | EN only |
|
|
67
|
+
| eSpeak-ng required | No | Yes | No | No |
|
|
68
|
+
| IPA output | Yes | Yes | Yes | Yes |
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install piper-plus-g2p # Rule-based languages (ES, FR, PT, SV)
|
|
74
|
+
pip install piper-plus-g2p[ja,en] # Japanese + English
|
|
75
|
+
pip install piper-plus-g2p[all] # All 8 languages
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
> **Note:** The `ja` extra requires `pyopenjtalk-plus`, which provides pre-built wheels for Linux, macOS, and Windows. See [pyopenjtalk-plus](https://pypi.org/project/pyopenjtalk-plus/) for platform details.
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from piper_plus_g2p import get_phonemizer
|
|
84
|
+
|
|
85
|
+
ja = get_phonemizer("ja")
|
|
86
|
+
ja.phonemize("こんにちは")
|
|
87
|
+
# -> ["k", "o", "[", "N_n", "n", "i", "ch", "i", "w", "a"]
|
|
88
|
+
|
|
89
|
+
en = get_phonemizer("en")
|
|
90
|
+
en.phonemize("Hello world")
|
|
91
|
+
# -> ["h", "ə", "l", "ˈ", "o", "ʊ", " ", "w", "ˈ", "ɜ", "ː", "l", "d"]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Supported Languages
|
|
95
|
+
|
|
96
|
+
| Language | Code | Extra | Backend | Notes |
|
|
97
|
+
|---|---|---|---|---|
|
|
98
|
+
| Japanese | `ja` | `piper-plus-g2p[ja]` | pyopenjtalk-plus | Context-dependent N variants, prosody info |
|
|
99
|
+
| English | `en` | `piper-plus-g2p[en]` | g2p-en | CMU-dict + neural fallback |
|
|
100
|
+
| Chinese | `zh` | `piper-plus-g2p[zh]` | pypinyin | Pinyin-to-IPA conversion |
|
|
101
|
+
| Korean | `ko` | `piper-plus-g2p[ko]` | g2pk2 | Optional dependency |
|
|
102
|
+
| Spanish | `es` | -- | Rule-based | No external dependency |
|
|
103
|
+
| French | `fr` | -- | Rule-based | No external dependency |
|
|
104
|
+
| Portuguese | `pt` | -- | Rule-based | No external dependency |
|
|
105
|
+
| Swedish | `sv` | -- | Rule-based | No external dependency |
|
|
106
|
+
|
|
107
|
+
## Advanced Usage
|
|
108
|
+
|
|
109
|
+
### Multilingual (Composite Language Code)
|
|
110
|
+
|
|
111
|
+
Pass a hyphen-joined code like `"ja-en-zh"` to `get_phonemizer` to
|
|
112
|
+
automatically create a `MultilingualPhonemizer`. Language detection is
|
|
113
|
+
Unicode-based, so mixed-script text is handled without explicit tagging.
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from piper_plus_g2p import get_phonemizer
|
|
117
|
+
|
|
118
|
+
multi = get_phonemizer("ja-en-zh")
|
|
119
|
+
tokens = multi.phonemize("こんにちは Hello 你好")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### PiperEncoder
|
|
123
|
+
|
|
124
|
+
Converts IPA token lists into integer `phoneme_ids` for Piper ONNX models.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from piper_plus_g2p.encode import PiperEncoder, get_phoneme_id_map
|
|
128
|
+
|
|
129
|
+
id_map = get_phoneme_id_map("ja")
|
|
130
|
+
encoder = PiperEncoder(id_map)
|
|
131
|
+
phoneme_ids = encoder.encode(["k", "o", "[", "N_n", "n", "i", "ch", "i", "w", "a"])
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Piper Model Compatibility
|
|
135
|
+
|
|
136
|
+
piper-plus-g2p produces phoneme tokens directly compatible with
|
|
137
|
+
[Piper TTS](https://github.com/rhasspy/piper) ONNX models. Use
|
|
138
|
+
`PiperEncoder` with the model's `phoneme_id_map` from `config.json`:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
import json
|
|
142
|
+
from piper_plus_g2p import get_phonemizer
|
|
143
|
+
from piper_plus_g2p.encode import PiperEncoder
|
|
144
|
+
|
|
145
|
+
with open("model/config.json") as f:
|
|
146
|
+
config = json.load(f)
|
|
147
|
+
|
|
148
|
+
encoder = PiperEncoder(config["phoneme_id_map"])
|
|
149
|
+
phonemizer = get_phonemizer("ja")
|
|
150
|
+
tokens = phonemizer.phonemize("こんにちは")
|
|
151
|
+
phoneme_ids = encoder.encode(tokens)
|
|
152
|
+
# -> ready for ONNX inference
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Use `strict=True` to raise errors on unknown tokens instead of silently
|
|
156
|
+
skipping them:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
encoder = PiperEncoder(config["phoneme_id_map"], strict=True)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Cross-Platform Consistency
|
|
163
|
+
|
|
164
|
+
piper-plus-g2p is also available as:
|
|
165
|
+
- **Rust crate**: `piper-plus-g2p` on crates.io
|
|
166
|
+
- **Go module**: `github.com/ayutaz/piper-plus/src/go/phonemize`
|
|
167
|
+
- **npm package**: `@piper-plus/g2p` for browser/WASM
|
|
168
|
+
|
|
169
|
+
All three implementations share the same PUA mapping table and are
|
|
170
|
+
validated against a common test fixture.
|
|
171
|
+
|
|
172
|
+
## Requirements
|
|
173
|
+
|
|
174
|
+
- Python >= 3.11
|
|
175
|
+
- Language backends are installed via extras (see [Supported Languages](#supported-languages))
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# piper-plus-g2p
|
|
2
|
+
|
|
3
|
+
Multilingual G2P (Grapheme-to-Phoneme) for TTS. eSpeak-ng free. MIT licensed. 8 languages.
|
|
4
|
+
|
|
5
|
+
**Standalone package** — piper-plus TTS エンジンなしで G2P 単体として利用可能です。任意の TTS エンジンと組み合わせて使えます。
|
|
6
|
+
|
|
7
|
+
## Why piper-plus-g2p?
|
|
8
|
+
|
|
9
|
+
- **MIT licensed** -- no eSpeak-ng (GPL) dependency in your TTS pipeline
|
|
10
|
+
- **8 languages** -- JA, EN, ZH, KO, ES, FR, PT, SV with consistent IPA output
|
|
11
|
+
- **IPA-first design** -- returns pure IPA token sequences, ready for any TTS model
|
|
12
|
+
|
|
13
|
+
## Comparison
|
|
14
|
+
|
|
15
|
+
| | piper-plus-g2p | phonemizer | gruut | Misaki |
|
|
16
|
+
|---|---|---|---|---|
|
|
17
|
+
| License | MIT | GPL (eSpeak-ng) | MIT | Apache-2.0 |
|
|
18
|
+
| Languages | 8 | 100+ | 20+ | EN only |
|
|
19
|
+
| eSpeak-ng required | No | Yes | No | No |
|
|
20
|
+
| IPA output | Yes | Yes | Yes | Yes |
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install piper-plus-g2p # Rule-based languages (ES, FR, PT, SV)
|
|
26
|
+
pip install piper-plus-g2p[ja,en] # Japanese + English
|
|
27
|
+
pip install piper-plus-g2p[all] # All 8 languages
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> **Note:** The `ja` extra requires `pyopenjtalk-plus`, which provides pre-built wheels for Linux, macOS, and Windows. See [pyopenjtalk-plus](https://pypi.org/project/pyopenjtalk-plus/) for platform details.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from piper_plus_g2p import get_phonemizer
|
|
36
|
+
|
|
37
|
+
ja = get_phonemizer("ja")
|
|
38
|
+
ja.phonemize("こんにちは")
|
|
39
|
+
# -> ["k", "o", "[", "N_n", "n", "i", "ch", "i", "w", "a"]
|
|
40
|
+
|
|
41
|
+
en = get_phonemizer("en")
|
|
42
|
+
en.phonemize("Hello world")
|
|
43
|
+
# -> ["h", "ə", "l", "ˈ", "o", "ʊ", " ", "w", "ˈ", "ɜ", "ː", "l", "d"]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Supported Languages
|
|
47
|
+
|
|
48
|
+
| Language | Code | Extra | Backend | Notes |
|
|
49
|
+
|---|---|---|---|---|
|
|
50
|
+
| Japanese | `ja` | `piper-plus-g2p[ja]` | pyopenjtalk-plus | Context-dependent N variants, prosody info |
|
|
51
|
+
| English | `en` | `piper-plus-g2p[en]` | g2p-en | CMU-dict + neural fallback |
|
|
52
|
+
| Chinese | `zh` | `piper-plus-g2p[zh]` | pypinyin | Pinyin-to-IPA conversion |
|
|
53
|
+
| Korean | `ko` | `piper-plus-g2p[ko]` | g2pk2 | Optional dependency |
|
|
54
|
+
| Spanish | `es` | -- | Rule-based | No external dependency |
|
|
55
|
+
| French | `fr` | -- | Rule-based | No external dependency |
|
|
56
|
+
| Portuguese | `pt` | -- | Rule-based | No external dependency |
|
|
57
|
+
| Swedish | `sv` | -- | Rule-based | No external dependency |
|
|
58
|
+
|
|
59
|
+
## Advanced Usage
|
|
60
|
+
|
|
61
|
+
### Multilingual (Composite Language Code)
|
|
62
|
+
|
|
63
|
+
Pass a hyphen-joined code like `"ja-en-zh"` to `get_phonemizer` to
|
|
64
|
+
automatically create a `MultilingualPhonemizer`. Language detection is
|
|
65
|
+
Unicode-based, so mixed-script text is handled without explicit tagging.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from piper_plus_g2p import get_phonemizer
|
|
69
|
+
|
|
70
|
+
multi = get_phonemizer("ja-en-zh")
|
|
71
|
+
tokens = multi.phonemize("こんにちは Hello 你好")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### PiperEncoder
|
|
75
|
+
|
|
76
|
+
Converts IPA token lists into integer `phoneme_ids` for Piper ONNX models.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from piper_plus_g2p.encode import PiperEncoder, get_phoneme_id_map
|
|
80
|
+
|
|
81
|
+
id_map = get_phoneme_id_map("ja")
|
|
82
|
+
encoder = PiperEncoder(id_map)
|
|
83
|
+
phoneme_ids = encoder.encode(["k", "o", "[", "N_n", "n", "i", "ch", "i", "w", "a"])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Piper Model Compatibility
|
|
87
|
+
|
|
88
|
+
piper-plus-g2p produces phoneme tokens directly compatible with
|
|
89
|
+
[Piper TTS](https://github.com/rhasspy/piper) ONNX models. Use
|
|
90
|
+
`PiperEncoder` with the model's `phoneme_id_map` from `config.json`:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import json
|
|
94
|
+
from piper_plus_g2p import get_phonemizer
|
|
95
|
+
from piper_plus_g2p.encode import PiperEncoder
|
|
96
|
+
|
|
97
|
+
with open("model/config.json") as f:
|
|
98
|
+
config = json.load(f)
|
|
99
|
+
|
|
100
|
+
encoder = PiperEncoder(config["phoneme_id_map"])
|
|
101
|
+
phonemizer = get_phonemizer("ja")
|
|
102
|
+
tokens = phonemizer.phonemize("こんにちは")
|
|
103
|
+
phoneme_ids = encoder.encode(tokens)
|
|
104
|
+
# -> ready for ONNX inference
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use `strict=True` to raise errors on unknown tokens instead of silently
|
|
108
|
+
skipping them:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
encoder = PiperEncoder(config["phoneme_id_map"], strict=True)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Cross-Platform Consistency
|
|
115
|
+
|
|
116
|
+
piper-plus-g2p is also available as:
|
|
117
|
+
- **Rust crate**: `piper-plus-g2p` on crates.io
|
|
118
|
+
- **Go module**: `github.com/ayutaz/piper-plus/src/go/phonemize`
|
|
119
|
+
- **npm package**: `@piper-plus/g2p` for browser/WASM
|
|
120
|
+
|
|
121
|
+
All three implementations share the same PUA mapping table and are
|
|
122
|
+
validated against a common test fixture.
|
|
123
|
+
|
|
124
|
+
## Requirements
|
|
125
|
+
|
|
126
|
+
- Python >= 3.11
|
|
127
|
+
- Language backends are installed via extras (see [Supported Languages](#supported-languages))
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Third-Party Licenses — piper-g2p (Python)
|
|
2
|
+
|
|
3
|
+
piper-g2p is licensed under MIT. Below are the licenses of its
|
|
4
|
+
dependencies, grouped by optionality.
|
|
5
|
+
|
|
6
|
+
## Core (no external dependencies)
|
|
7
|
+
|
|
8
|
+
piper-g2p core has zero required runtime dependencies. Languages ES, FR,
|
|
9
|
+
PT, SV, and KO are fully rule-based and need no external packages.
|
|
10
|
+
|
|
11
|
+
## Optional: Japanese (`pip install piper-g2p[ja]`)
|
|
12
|
+
|
|
13
|
+
| Package | License | Purpose |
|
|
14
|
+
|---------|---------|---------|
|
|
15
|
+
| pyopenjtalk-plus | MIT | OpenJTalk bindings for Japanese G2P |
|
|
16
|
+
| numpy | BSD-3-Clause | Numerical arrays (pyopenjtalk dep) |
|
|
17
|
+
|
|
18
|
+
## Optional: English (`pip install piper-g2p[en]`)
|
|
19
|
+
|
|
20
|
+
| Package | License | Purpose |
|
|
21
|
+
|---------|---------|---------|
|
|
22
|
+
| g2p-en | Apache-2.0 | CMU Pronouncing Dictionary + neural G2P |
|
|
23
|
+
| numpy | BSD-3-Clause | Neural network inference |
|
|
24
|
+
|
|
25
|
+
## Optional: Chinese (`pip install piper-g2p[zh]`)
|
|
26
|
+
|
|
27
|
+
| Package | License | Purpose |
|
|
28
|
+
|---------|---------|---------|
|
|
29
|
+
| pypinyin | MIT | Hanzi to Pinyin conversion |
|
|
30
|
+
|
|
31
|
+
## Optional: Korean (`pip install piper-g2p[ko]`)
|
|
32
|
+
|
|
33
|
+
| Package | License | Purpose |
|
|
34
|
+
|---------|---------|---------|
|
|
35
|
+
| g2pk2 | Apache-2.0 | Korean G2P with neural disambiguation |
|
|
36
|
+
|
|
37
|
+
> **Note:** g2pk2 may pull in heavy transitive dependencies (torch or
|
|
38
|
+
> tensorflow). Consider whether Korean support is needed before installing.
|
|
39
|
+
|
|
40
|
+
## Development
|
|
41
|
+
|
|
42
|
+
| Package | License | Purpose |
|
|
43
|
+
|---------|---------|---------|
|
|
44
|
+
| pytest | MIT | Test framework |
|
|
45
|
+
| ruff | MIT | Linter/formatter |
|
|
46
|
+
| mypy | MIT | Type checker |
|
|
47
|
+
|
|
48
|
+
## No copyleft licenses
|
|
49
|
+
|
|
50
|
+
All runtime dependencies are MIT, Apache-2.0, or BSD-3-Clause.
|
|
51
|
+
No GPL, LGPL, or AGPL licenses are present.
|