moore-g2p
Transcription graphème-phonème pour le mooré, langue gur parlée par environ huit millions de personnes au Burkina Faso.
Convertit du texte mooré en phonèmes, en deux notations produites depuis un inventaire unique :
- ARPABET — pour les systèmes de synthèse vocale (Tacotron2, VITS, F5-TTS)
- IPA — pour la lecture humaine, la documentation et la description linguistique
from moore_g2p import transcribe, transcribe_ipa
transcribe("bãngã") # 'B AA_N N G AA'
transcribe_ipa("bãngã") # 'bãnga'
Installation
Usage local, pendant le développement
Depuis le dossier du projet, en mode éditable : les modifications du code sont prises en compte immédiatement, sans réinstallation.
git clone https://github.com/root-gift/moore-g2p.git
cd moore-g2p
python -m venv .venv # environnement isolé
source .venv/bin/activate # Windows : .venv\Scripts\activate
pip install -e ".[dev]" # paquet + outils de développement
pytest
Il n'y a pas de requirements.txt : les dépendances sont déclarées dans
pyproject.toml, qui est la source unique depuis la PEP 621. Celles de
développement — pytest, black, flake8, build, twine — vivent dans
[project.optional-dependencies] et s'installent avec le suffixe [dev].
Depuis PyPI, une fois publié
pip install moore-g2p
Aucune dépendance à l'exécution. Le paquet n'importe que re, sys,
typing, unicodedata et argparse, tous dans la bibliothèque standard.
Rien à installer, aucun conflit de versions possible, et l'intégration dans
un pipeline d'entraînement n'ajoute rien à son environnement.
Usage
Un mot
from moore_g2p import MooreG2P
g = MooreG2P()
g.transcribe("rĩmã") # 'R I_N M AA_N'
g.transcribe("rĩmã", notation="ipa") # 'rĩmã'
Une phrase, ponctuation comprise
La ponctuation est conservée : c'est le seul support de la prosodie — pauses, groupes de souffle, intonation montante.
g.transcribe_text("Rĩmã, fo yaa bãngã?")
# 'R I_N M AA_N , F O | Y AA1 | B AA_N N G AA ?'
g.transcribe_text("Rĩmã, fo yaa bãngã?", notation="ipa")
# 'rĩmã, fo jaː bãnga?'
En ARPABET, | marque la frontière de mot. En IPA, les mots sont séparés
par une espace, selon l'usage phonétique.
Traiter un corpus
Utilisez strict=True : tout graphème non reconnu lève alors une exception
au lieu de disparaître silencieusement du texte d'entraînement.
g = MooreG2P(strict=True)
try:
g.transcribe(ligne)
except ValueError as e:
print(f"ligne {n} : {e}")
Nombres
Les chiffres sont développés en toutes lettres avant la conversion, comme le
fait text/numbers.py dans Tacotron2 — sauf que celui-ci dépend d'inflect,
qui ne connaît que l'anglais.
from moore_g2p.numbers import expand_number, expand_numbers
expand_number(0) # 'zaalm'
expand_number(13) # 'piig la a tã'
expand_number(2001) # 'tusra yiib la a ye'
expand_numbers("Yaa 25 la 3.") # 'Yaa pisi la a nu la tãabo.'
Structure. Le connecteur dépend du rang de ce qui suit : la a devant une
unité, la seul devant un rang supérieur.
112 = koabg la piig la a yiibu
└ la devant « dix »
└ la a devant l'unité
Le a est une particule autonome, non un élément du numéral : 1 se dit
yembo, yembre ou ye. La particule tombe devant la forme yi, et devant elle seule.
L'unité prend sa forme brève (yi, tã) sous une dizaine seule, et sa
forme pleine (yiibu, tãabo) dès qu'une centaine ou un rang supérieur
précède :
12 = piig la yi
612 = kobs-yoob la piig la a yiibu
3003 = tusra tãab la a tãabo
Trois formes coexistent ainsi pour 3 : tãabo pleine, tã brève, tãab
devant la. Devant un connecteur, la voyelle finale tombe : piiga → piig,
koabga → koabg, tusri → tusr, yiibu → yiib ; pisi, kobisi et
yopoe sont invariables.
Le millier a quatre formes selon le contexte : tusri isolé, tusr devant
la, tusra avec un multiplicateur de 2 à 9, tus avec un multiplicateur
dizaine. Le trait d'union des dizaines ne s'écrit que devant une
consonne : pis-tã, mais pisi. Les centaines reprennent exactement cette
structure avec le radical kobs- : kobisi (200), kobs-tã (300),
kobs-naase (400).
Méthode. ATTESTES contient les formes fournies par un locuteur et est
consultée en premier, comme un lexique d'exceptions ; le reste est généré par
règles. La plage traitée va de 0 à 999 999.
from moore_g2p.numbers import conflits
for n, attestee, generee in conflits():
print(n, attestee, "|", generee)
Liaison. À la lecture, la a est couramment prononcé en liaison. Le
module produit la forme orthographique et laisse la réalisation au modèle
acoustique, qui l'apprend de l'audio. Si l'on préfère encoder la liaison au
niveau des phonèmes, c'est une règle à ajouter au G2P et non au module de
nombres, car elle dépasse le cas des numéraux.
Variantes libres. yembo, yembre et ye sont interchangeables pour 1,
comme wae et wɛ pour 9. canoniser() les ramène à une forme unique, ce
qui permet de comparer deux écritures d'un même nombre sans qu'un choix de
variante compte comme une différence.
from moore_g2p.numbers import canoniser
canoniser("pis-wɛ la yembre") # 'pis-wae la ye'
conflits() liste les cas où la règle diverge d'une forme attestée, variantes
mises à part. Ce sont
les points du système qui restent à arbitrer par un locuteur ; tant qu'ils
figurent dans ATTESTES, la forme attestée l'emporte.
Le développement est actif par défaut et se désactive par
MooreG2P(nombres=False).
Lexique d'exceptions
Prioritaire sur toutes les règles, et modifiable à chaud. C'est le bon endroit pour les noms propres, les emprunts et les toponymes. Tant qu'une entrée n'utilise que des symboles existants, aucun réentraînement n'est nécessaire en aval.
g = MooreG2P(lexique={"Wẽnnaam": "W EH_N N1 AA1 M"})
g.transcribe("Wẽnnaam") # 'W EH_N N1 AA1 M'
Ligne de commande
moore-g2p "Rĩmã, fo yaa bãngã?"
moore-g2p -n ipa "Rĩmã, fo yaa bãngã?"
moore-g2p --tacotron2 "bãngã"
moore-g2p --inventaire
cat corpus.txt | moore-g2p --strict > corpus.phonemes
Intégration Tacotron2
g.to_tacotron2("Rĩmã, fo yaa bãngã?")
# '{R I_N M AA_N}, {F O} {Y AA1} {B AA_N N G AA}?'
Les accolades délimitent les zones ARPABET, pas les mots ; la ponctuation
reste à l'extérieur, où Tacotron2 la déclare déjà. Le préfixe @ est ajouté
en interne par _arpabet_to_sequence — ne l'écrivez pas.
Les symboles doivent d'abord être déclarés dans text/symbols.py, faute de
quoi Tacotron2 les supprime sans avertissement :
from text.symbols import symbols
g.verifier_couverture(symbols) # lève une erreur en listant les manquants
Points de conception
Normalisation Unicode
ã ẽ ĩ õ ũ possèdent une forme précomposée. ɛ̃ et ɔ̃ n'en ont pas :
ce sont toujours deux points de code, lettre plus tilde combinant. Aucune
normalisation Unicode ne peut les atomiser — c'est pourquoi le conseil
habituel « normalisez en NFC » échoue ici.
Le paquet ramène donc ɛ̃ vers ẽ et ɔ̃ vers õ, qui sont des caractères
uniques, dès la première étape. Après quoi plus aucun diacritique combinant
ne subsiste et le reste du traitement devient insensible à la saisie.
import unicodedata as ud
g.transcribe(ud.normalize("NFC", "Wẽnnaam")) == \
g.transcribe(ud.normalize("NFD", "Wẽnnaam")) # True
Créneaux réservés
La matrice d'embeddings d'un modèle TTS a exactement n_symboles lignes.
Ajouter un symbole après l'entraînement change cette taille et rend tout
checkpoint inchargeable.
L'inventaire réserve donc des lignes vides, placées à la fin pour que les
indices des symboles réels ne bougent jamais. Pour en attribuer une plus
tard, renseignez inventory.CRENEAUX_ACTIVES ; un fine-tune léger reste
nécessaire pour que la ligne apprenne quelque chose.
Le ton n'est pas traité
Le mooré est une langue à tons, mais l'orthographe standard ne les note pas. Un modèle entraîné sur cette base les apprend implicitement, par mémorisation lexicale, et se trompe sur les mots inconnus et les homographes tonaux. Traiter les tons demanderait un lexique tonal et un désambiguïsateur morphosyntaxique.
À valider par un locuteur natif
Ces choix reposent sur la cohérence interne, sans attestation documentaire.
Ils sont modifiables en tête de inventory.py.
- Timbre des voyelles dénasalisées — on suppose que
ẽ[ɛ̃] donne [ɛ] etõ[ɔ̃] donne [ɔ]. VoirDENASALISATION. - Asymétrie des nasales doublées —
ẽẽetõõsont admises,ãã,ĩĩ,ũũnon. VoirNASALES_DOUBLABLES. - Portée de la dénasalisation — seules
g,d,bdéclenchent la règle. VoirCONS_DENASALISANTES. - Suites vocaliques — elles ne figurent dans aucune source publiée. Voir
SUITES.
Développement
Un Makefile regroupe les commandes courantes.
make install # environnement de développement
make test # tests avec couverture
make lint # flake8 + black --check
make format # applique black
make build # sdist + wheel, puis twine check
Les vérifications tournent aussi avant chaque commit si vous le souhaitez :
pre-commit install
L'intégration continue exécute la suite sur Linux, macOS et Windows, de Python 3.8 à 3.12, plus le lint et la construction du paquet.
Publier une nouvelle version
- Mettre à jour la version dans
pyproject.tomletmoore_g2p/__init__.py. Le workflow refuse de publier si les deux divergent du tag. - Compléter
CHANGELOG.md. make test && make lint && make build- Créer une release GitHub avec le tag
vX.Y.Z.
La publication sur PyPI se fait alors automatiquement, par publication de
confiance — aucun jeton API à stocker. Il faut l'avoir configurée une fois
sur PyPI, dans les paramètres du projet, en déclarant le dépôt GitHub et le
workflow publish.yml.
Pour publier à la main :
make build
twine upload --repository testpypi dist/* # essai
twine upload dist/* # publication
Licence
MIT. Voir LICENSE.
Citation
@software{moore_g2p,
title = {moore-g2p: Grapheme-to-Phoneme Conversion for Mooré},
author = {Zongo, Michael Roger},
year = {2026},
url = {https://github.com/root-gift/moore-g2p}
}
Metadata
Release files for moore-g2p 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| moore_g2p-0.2.0.tar.gz | 34.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| moore_g2p-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.1 kB
Release files / moore_g2p-0.2.0.tar.gz
| Download URL | moore_g2p-0.2.0.tar.gz |
|---|---|
| Size | 34.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
64fd18bf0a36d3aebbd9ede38e6144684073cc39450f8b61216d2a5aad7bedd9
|
|
BLAKE2b-256 checksum How to use checksums |
383f7eddb10fea91f4d50ada6eb0268b08508d4fcdbb87f6991485502f2cdeac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|
Release files / moore_g2p-0.2.0-py3-none-any.whl
| Download URL | moore_g2p-0.2.0-py3-none-any.whl |
|---|---|
| Size | 22.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
16d004290854626762c7c9328d5a0207cc82908275679639f1edd700ae98de8a
|
|
BLAKE2b-256 checksum How to use checksums |
5a28ed57c23f6c1210053a29a5c1f055f388112c47db166bacc4aa951eaaa5e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|
Security for moore-g2p 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.