TTS: Síntesi de veu
Contingut
1a prova: F5-TTS, no funciona
(no acaba de funcionar, resultats inconsistents)
(m'he fet un lio amb el XTTS-v2 i la instal·lació de Coqui TTS)
prompt: "vull fer clonació i síntesi de veu en català amb F5-TTS. Tinc una RTX5060 Ti 16GB."
Per català, però, hi ha un punt important: el model base de F5-TTS no és específicament un model català, així que la qualitat de pronunciació catalana dependrà molt del text, del model/checkpoint i de l'àudio de referència. Si vols qualitat alta i consistent en català, podem plantejar també fine-tuning.
mkdir -p F5-TTS cd F5-TTS python3 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip setuptools wheel
3. Instal·la PyTorch El repositori actual de F5-TTS documenta PyTorch amb CUDA 12.8, i PyTorch publica wheels específiques cu128.
Jo tinc CUDA 13.2, però no passa res
pip install torch==2.8.0+cu128 torchaudio==2.8.0+cu128 \
--extra-index-url https://download.pytorch.org/whl/cu128
$ python3
import torch
print("PyTorch:", torch.__version__)
print("CUDA:", torch.version.cuda)
print("CUDA disponible:", torch.cuda.is_available())
print("GPU:", torch.cuda.get_device_name(0))
print("Compute capability:", torch.cuda.get_device_capability(0))
PyTorch: 2.8.0+cu128
CUDA: 12.8
CUDA disponible: True
GPU: NVIDIA GeForce RTX 5060 Ti
Compute capability: (12, 0)
4. Instal·la F5-TTS
git clone https://github.com/SWivid/F5-TTS.git cd F5-TTS pip install -e .
ara el meu directori de treball és ~/F5-TTS/F5-TTS. No confondre el primer amb el segon.
$ f5-tts_infer-cli --help $ f5-tts_infer-gradio --help -> es descarrega el model
5. Primera prova: interfície web
$ f5-tts_infer-gradio
Normalment et donarà una adreça local del tipus:
Obre-la al navegador.
La interfície de F5-TTS permet fer inferència a partir d'una veu de referència i generar text nou. El projecte actual també disposa de funcionalitats d'inferència per chunks i altres modes.
però jo no estic davant de l'ordinador. I no puc fer:
perquè el port 7860 no està obert (m'he quedat aquí) (...)
Gravo una veu que representa que és de referència, i a partir d'aquesta veu podré fer síntesi/clonació. És a dir, jo el que volia fer aquí ja és la clonació. Aquesta tècnica s'emmarca amb la tècnica de clonació directa amb un model zero-shot multilingüe. Models com F5-TTS permeten clonar una veu a partir només d'uns segons d'àudio i generar directament en l'idioma objectiu. Els models que es poden fer servir són XTTS-v2 (Coqui), F5-TTS o GPT-SoVITS (estic provant F5-TTS), i el problema és que cap d'aquests models té el català com a idioma oficialment suportat de sèrie.
$ arecord -f cd gravacio.wav scp gravacio.* joan@192.168.1.184:/home/joan/Baixades $ f5-tts_infer-cli --model F5TTS_Base --ref_audio /home/joan/Baixades/gravacio.wav --ref_text "It was a cold and quiet evening when Emily arrived in the small village of Blackwood. The streets were almost empty, and a thick fog covered the old houses. As she walked towards the house she had recently inherited from her grandmother, she noticed a strange light shining from one of the upstairs windows. Emily stopped and stared at it for a moment. She was certain that the house had been empty for years, so she could not understand who could be inside." --gen_text "Good morning. This is a simple test of generating an English speech from a text" --output_dir /home/joan/projectes --output_file prova.wav --speed 0.06
es genera el fitxer /home/joan/Baixades/prova.wav
NOTA: recordem que en el portàtil tinc un punt de muntatge a /home/joan/projectes en el servidor.
$ find ~/.cache/gface -type d -iname "*F5*" 2>/dev/null /home/joan/.cache/huggingface/hub/models--SWivid--F5-TTS /home/joan/.cache/huggingface/hub/models--SWivid--F5-TTS/snapshots/84e5a410d9cead4de2f847e7c9369a6440bdfaca/F5TTS_v1_Base /home/joan/.cache/huggingface/hub/models--SWivid--F5-TTS/snapshots/84e5a410d9cead4de2f847e7c9369a6440bdfaca/F5TTS_Base /home/joan/.cache/huggingface/hub/.locks/models--SWivid--F5-TTS $ f5-tts_infer-cli --model F5TTS_v1_Base --ref_audio /home/joan/Baixades/gravacio.wav --ref_text "It was a cold and quiet evening when Emily arrived in the small village of Blackwood. The streets were almost empty, and a thick fog covered the old houses. As she walked towards the house she had recently inherited from her grandmother, she noticed a strange light shining from one of the upstairs windows. Emily stopped and stared at it for a moment. She was certain that the house had been empty for years, so she could not understand who could be inside." --gen_text "Good morning. This is a simple test of generating an English speech from a text" --output_dir /home/joan/projectes --output_file prova2.wav --speed 0.06 $ f5-tts_infer-cli --model F5TTS_Base --ref_audio /home/joan/projectes/gravacio2.wav --ref_text "It was a cold and quiet evening when Emily arrived in the small village of Blackwood." --gen_text "Good morning. This is a simple test of generating an English speech from a text" --output_dir /home/joan/projectes --output_file prova.wav --speed 0.06
No m'acaba de sortir. Obtinc uns resultats en anglès bastant inconsistents, i en català no ho aconseguiré.
2a prova: model VITS
2a prova per a la síntesi d'una veu en català
Abans de fer la clonació de veu primer he de fer síntesi de veu en català. S'ha de separar el problema en dos passos:
- Genera la parla en català amb un model ja entrenat pel Projecte Aina (BSC), com Matxa-TTS o el VITS multi-parlant (projecte-aina/tts-ca-coqui-vits-multispeaker) — és la primera solució tecnològica publicada com a model lingüístic en obert que ofereix interpretació de text a veu en català central, nord-occidental, balear i valencià, disponible a Hugging Face. - Converteix el timbre a la teva veu amb una eina de voice conversion com RVC (Retrieval-based Voice Conversion) o so-vits-svc. Entrenes un model petit amb ~10-30 minuts d’àudio net de la teva veu (parlant en qualsevol idioma, fins i tot) i li apliques la sortida del TTS català. El model de conversió només ha d’aprendre el color de la teva veu, no l'idioma, així que funciona molt bé i és ràpid d’entrenar amb 16GB. Aquest segon pas és la clonació de veu, i la desenvolupo en una altra entrada. Ara ens centrarem només en la síntesi.
Anem a fer dons la síntesi de veu en català.
mkdir ~/veu-catala && cd ~/veu-catala python3 -m venv venv source venv/bin/activate # a Windows: venv\Scripts\activate pip install --upgrade pip
Recordem que estem seguint:
Primer instal·lem PyTorch. Aquí el Claude em fa un avís: La teva 5060 Ti és arquitectura Blackwell (sm_120). Si instal·les PyTorch “normal” (per exemple amb CUDA 12.1 o 12.4), et donarà l’error CUDA capability sm_120 is not compatible. Necessites la build amb CUDA 12.8 o superior:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
i comprovem que ho detecta bé:
python -c "import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))"
També necessitem com a dependència:
sudo apt install ffmpeg
i ara ja podem instal·lar TTS (llibreria coqui-tts, compatible amb els models VITS del BSC)
$ pip install TTS ERROR: Ignored the following versions that require a different python version: 0.0.10.2 Requires-Python >=3.6.0,<3.9; 0.0.10.3 Requires-Python >=3.6.0,<3.9; 0.0.11 Requires-Python >=3.6.0,<3.9; 0.0.12 Requires-Python >=3.6.0,<3.9; 0.0.13.1 Requires-Python >=3.6.0,<3.9; 0.0.13.2 Requires-Python >=3.6.0,<3.9; 0.0.14.1 Requires-Python >=3.6.0,<3.9; 0.0.15 Requires-Python >=3.6.0,<3.9; 0.0.15.1 Requires-Python >=3.6.0,<3.9; 0.0.9 Requires-Python ... >=3.7.0,<3.11; 0.7.1 Requires-Python >=3.7.0,<3.11; 0.8.0 Requires-Python >=3.7.0,<3.11; 0.9.0 Requires-Python >=3.7.0,<3.11 ERROR: Could not find a version that satisfies the requirement TTS (from versions: none) ERROR: No matching distribution found for TTS
Confirmat: el paquet TTS original de Coqui està abandonat (l'empresa va tancar) i el darrer release no accepta Python ≥3.12, que és probablement el que tens instal·lat. Hi ha un fork actiu mantingut per Idiap que ha canviat de nom a coqui-tts.
pip install coqui-tts -> ara sí
Aquest fork suporta Python 3.10 fins a <3.13 (i les últimes versions ja arriben fins <3.14). Si el teu python3 --version et dona 3.13 o més nou, hauràs de crear el venv amb una versió compatible:
Prova ràpida amb el model multi-parlant:
from TTS.api import TTS
tts = TTS("tts_models/ca/custom/vits-multispeaker") # o el nom exacte del repo d'Aina a HF
tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu en català.", speaker="ona", file_path="prova.wav")
Però dóna un error:
from TTS.api import TTS ImportError: cannot import name 'isin_mps_friendly' from 'transformers.pytorch_utils' (/home/joan/veu-catala/venv/lib/python3.12/site-packages/transformers/pytorch_utils.py)
Trobat exactament: és un problema conegut i molt recent — transformers 5.x va eliminar la funció isin_mps_friendly que coqui-tts encara fa servir internament (a TTS/tts/layers/tortoise/autoregressive.py). Se't deu haver instal·lat automàticament una versió massa nova de transformers.
Solució
Fixa transformers a una versió anterior a la 5.0:
pip install "transformers==4.57.6"
$ pip show transformers
Name: transformers
Version: 4.57.6
$ python -c "from TTS.api import TTS; print('OK')"
OK
Ara sí!
Ja puc fer la prova de síntesi:
from TTS.api import TTS
tts = TTS("tts_models/ca/custom/vits-multispeaker") # o el nom exacte del repo d'Aina a HF
tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu en català.",
speaker="ona",
file_path="prova.wav")
Els models que podem fer servir estan aquí:
i són:
- Vits 2
- Matxa-TTS
- Matxa-TTS-multiaccent -> aquest és el Matxa v2 (multiaccent), i és el que acabaré fent servir finalment
- StableTTS
- StyleTTS 2
Canvio el codi per al model vits:
tts = TTS("tts_models/ca/custom/vits") # funciona! descarrega el model
FileNotFoundError: [!] No espeak backend found. Install espeak-ng or espeak to your system.
primer he d'instal·lar espeak-ng
Instal·lació espeak-ng
NOTA1: aquest procés el faig dues vegades, perquè la primera vegada l'he fet fora del venv, i la segona vegada dins del venv, que seria el correcte.
NOTA2: el model de síntesi que faré servir finalment serà el Matxa V2, que funciona per grafemes, i això vol dir que aquest model no necessita el espeak-ng.
Instal·lo espeak-ng a la màquina, fora d'un venv, perquè ho faré servir bastant.
previ, les eines de make per compilar projectes C:
sudo apt update sudo apt install autoconf automake libtool-bin pkg-config build-essential $ which aclocal /usr/bin/aclocal $ aclocal --version aclocal (GNU automake) 1.16.5 sudo apt install libtool
cd ~/veu-catala git clone https://github.com/projecte-aina/espeak-ng.git cd espeak-ng ./autogen.sh -> crec que dóna error... ./configure --prefix=$HOME/veu-catala/espeak-ng-build make make install ./autogen.sh (ara ja funciona) ./configure --prefix=$HOME/veu-catala/espeak-ng-build make make install
ja ho tinc instal·lat.
Exportem les variables d'entorn
export ESPEAK_DATA_PATH=$HOME/veu-catala/espeak-ng-build/share/espeak-ng-data export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/veu-catala/espeak-ng-build/lib export PATH=$HOME/veu-catala/espeak-ng-build/bin:$PATH
NOTA: Val la pena afegir aquestes tres línies al final del ~/.bashrc (o a un script activate_env.sh propi que sourregis cada cop abans de treballar-hi), perquè si no les hauràs de tornar a exportar cada vegada que obris terminal nova.
4. Un parell de dependències més que demana Aina
pip cache purge pip install mecab-python3 unidic-lite
NOTA: he fet el fallo que ho hauria d'haver fet amb el venv del projecte que estava fent. Per tant, torno a activar el venv i faig la instal·lació del espeak-ng
cd ~/veu-catala source venv/bin/activate
(torno a estar dins del venv, i torno a fer la instal·lació del espeak-ng)
cd ~/veu-catala git clone https://github.com/projecte-aina/espeak-ng.git cd espeak-ng ./autogen.sh ./configure --prefix=$HOME/veu-catala/espeak-ng-build make make install
export ESPEAK_DATA_PATH=$HOME/veu-catala/espeak-ng-build/share/espeak-ng-data export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/veu-catala/espeak-ng-build/lib export PATH=$HOME/veu-catala/espeak-ng-build/bin:$PATH
pip cache purge pip install mecab-python3 unidic-lite
(ara sí!)
$ espeak-ng --voices=ca Pty Language Age/Gender VoiceName File Other Languages 5 ca --/M Catalan roa/ca 5 ca-ba --/M Catalan_(Balearic) roa/ca-ba 5 ca-nw --/M Catalan_(North-western) roa/ca-nw 5 ca-va --/M Catalan_(Valencian) roa/ca-va
Síntesi de veu amb vits
python -c "from TTS.api import TTS; print('OK')"
OK
Ja tinc la llibreria TTS instal·lada.
(en aquest punt hauria de recordar de com funciona espeak-ng)
Ja puc continuar en el punt on estava abans, de fer una prova de síntesi: (recordem que ara, per acabar de fer la síntesi, es farà servir espeak-ng)
from TTS.api import TTS
tts = TTS("tts_models/ca/custom/vits") # funciona! descarrega el model
tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu en català.", speaker="ona", file_path="prova.wav")
ja ho tinc, ho ha fet bastant bé, amb algun error. Puc provar els altres models, o altres speakers.
Tinc aquest codi, que no funciona massa bé:
from TTS.api import TTS
tts = TTS("tts_models/ca/custom/vits") # funciona! descarrega el model
tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu en català.", speaker="ona", file_path="prova.wav")
- quins són els models que puc fer servir en comptes de "tts_models/ca/custom/vits"?
- quins són els speakers que puc fer servir a més d'"ona"?
from TTS.api import TTS models = TTS().list_models() # Segons la versió, list_models() retorna una llista o un objecte ModelManager noms = models if isinstance(models, list) else models.list_models() print([m for m in noms if "/ca/" in m or "/cat/" in m])
Retorna:
['tts_models/ca/custom/vits']
només em retorna un model:
tts_models/ca/custom/vits: el que ja fas servir. És multi-speaker, entrenat amb dades de Festcat i Google Catalan.
Vull mirar tots els speakers:
tts = TTS("tts_models/ca/custom/vits")
print(tts.speakers)
...', 'jan', 'mar', 'ona', 'pau', 'pep', 'pol', 'teo']
for s in tts.speakers[:10]:
tts.tts_to_file(text="Bon dia, això és una prova.", speaker=s, file_path=f"/home/joan/projectes/t001_{s}.wav")
'/home/joan/projectes/t001_00236e350cc84b94a6684f182acf96e68963d7fa1164d4fa56da20f46f210b2dd3ecf189e97fb3c94113a54c12dc20550508f5b7b9b37e1873898d58a308feb5.wav'
'/home/joan/projectes/t001_00459.wav'
'/home/joan/projectes/t001_00762.wav'
'/home/joan/projectes/t001_00983a845f95493fb27125b114c635f3b40060efaee167d32d8a3dd040c877713446c7bd3e6944641227bdb4165ecb8d684ec2ef66c817e65e77c52cc50e62ed.wav'
'/home/joan/projectes/t001_01591.wav'
'/home/joan/projectes/t001_02452.wav'
'/home/joan/projectes/t001_02689.wav'
'/home/joan/projectes/t001_02992.wav'
'/home/joan/projectes/t001_02f7d61edf5063ca42953b1068539f1572985aa9448555cfd8d7667121eeedc72c912d95cf33abf61a1f9620f2a01be4251a53aa5440d15849003fb31210d830.wav'
'/home/joan/projectes/t001_03115.wav'
I canvio la línia i provo les diferents veus:
tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu.", speaker="jan", file_path=f"/home/joan/projectes/t001_jan.wav") tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu.", speaker="mar", file_path=f"/home/joan/projectes/t001_mar.wav") tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu.", speaker="ona", file_path=f"/home/joan/projectes/t001_ona.wav") tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu.", speaker="pau", file_path=f"/home/joan/projectes/t001_pau.wav") tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu.", speaker="pep", file_path=f"/home/joan/projectes/t001_pep.wav") tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu.", speaker="pol", file_path=f"/home/joan/projectes/t001_pol.wav") tts.tts_to_file(text="Bon dia, això és una prova de síntesi de veu.", speaker="teo", file_path=f"/home/joan/projectes/t001_teo.wav")
La qualitat no és molt bona:
- La llibreria original TTS de Coqui ja no es manté, perquè l'empresa va tancar. El fork mantingut és coqui-tts (pip install coqui-tts), que funciona amb el mateix codi i sol donar menys problemes amb versions noves de Python i PyTorch.
- El Projecte AINA (BSC) ha publicat models catalans més recents a Hugging Face, com Matxa amb el vocoder alVoCat, que tenen diversos accents i solen sonar més naturals. No es carreguen amb TTS(...): tenen el seu propi codi d'inferència. -> aquest és el que farem servir
Un codi més complet és el que em proposa Claude: (que és el model del projecte AINA (BSC))
pip install huggingface_hub
script prova.py:
import glob
from huggingface_hub import snapshot_download
from TTS.utils.synthesizer import Synthesizer
# Baixa el model (només cal la primera vegada, es queda en cau)
model_dir = snapshot_download(repo_id="projecte-aina/tts-ca-coqui-vits-multispeaker")
# Localitza els fitxers dins la carpeta "model"
config_path = f"{model_dir}/model/config.json"
speakers_path = glob.glob(f"{model_dir}/model/speakers*.pth")[0]
checkpoint_candidates = [
p for p in glob.glob(f"{model_dir}/model/*.pth")
if "speakers" not in p
]
model_path = checkpoint_candidates[0]
print("Checkpoint:", model_path)
print("Config:", config_path)
print("Speakers:", speakers_path)
synthesizer = Synthesizer(
model_path, config_path, speakers_path, None, None, None,
use_cuda=True,
)
# Mostra els parlants disponibles
print("Parlants disponibles:", synthesizer.tts_model.speaker_manager.speaker_names[:10])
text = "Bon dia! Això és una prova de síntesi de veu en català."
speaker = synthesizer.tts_model.speaker_manager.speaker_names[0]
wav = synthesizer.tts(text, speaker_name=speaker)
synthesizer.save_wav(wav, "prova.wav")
print("Fet! Genera't: prova.wav")
dóna un error que el Claude el sap solucionar:
Substitueix la crida al Synthesizer per:
synthesizer = Synthesizer(
tts_checkpoint=model_path,
tts_config_path=config_path,
tts_speakers_file=speakers_path,
use_cuda=True,
)
Puc provar amb els parlants: 'mar' (833), 'ona'(834), 'pau'(835), 'pep'(836), 'pol'(837), 'teo'(838), 'uri'(839)
hi ha 840 parlants.
per tant els índex d'aquests són: 833, 834, 835, 836, 837, 838, 839
Els parlants de Festcat (ona, pau,...) i d'OpenSLR tenen hores de gravació d'estudi. Són les veus més netes i estables.
aquestes veus (Festcat) es corresponen totes a parlants de català central. uri seria una mica unisex.
Però n'hi ha moltes d'altres de veus (840 parlants)
Sobre les 840 veus
La fitxa del model parla de 255 parlants, però tu en veus 840. No ho he trobat documentat, però és habitual en models de Coqui que el fitxer speakers.pth inclogui tots els identificadors que apareixien a les dades de partida. Això no vol dir que tots tinguin prou material d'entrenament. A Common Voice molts voluntaris només han gravat unes poques frases, i és probable que el model hagi après molt poc d'aquests parlants.
A la pràctica, això fa que la qualitat sigui molt desigual:
- Els parlants de Festcat (ona, pau,...) i d'OpenSLR tenen hores de gravació d'estudi. Són les veus més netes i estables.
- Els parlants de Common Voice amb moltes gravacions poden sonar bé, però amb el soroll i la variabilitat de gravacions casolanes.
- Els parlants amb molt poques gravacions sovint sonen genèrics, inestables o amb artefactes.
editar el config.json
ls -la /home/joan/.cache/huggingface/hub/models--projecte-aina--tts-ca-coqui-vits-multispeaker/snapshots/b90a4d6a94475a367ec4be8b9fca14e348240b6d/model/config.json joe /home/joan/.cache/huggingface/hub/models--projecte-aina--tts-ca-coqui-vits-multispeaker/snapshots/b90a4d6a94475a367ec4be8b9fca14e348240b6d/model/config.json
i en el config.json apuntem la ruta real:
"speakers_file": "/home/joan/.cache/huggingface/hub/models--projecte-aina--tts-ca-coqui-vits-multispeaker/snapshots/b90a4d6a94475a367ec4be8b9fca14e348240b6d/model/speakers.pth",
Tornem a provar, i finalment ha funcionat!
python3 prova.py ... 7955f7d04b0a4ba49c653677f215265658afde6e89fdd2391eb714531056'] Fet! Genera't: prova.wav
I ara sí que se sent molt bé!
Per tant, ja tinc un codi per fer síntesi de veu en català amb una veu molt bona
Puc provar els altres speaker_names i els altres models
he provat fins a 15 veus, i sembla ser que encara n'hi ha més. El model que he provat és: tts-ca-coqui-vits-multispeaker
- https://huggingface.co/projecte-aina/tts-ca-coqui-vits-multispeaker
- https://huggingface.co/spaces/softcatala/comparativa-tts-catala
NOTA: com que ja tenia aquesta part funcionant, ara vaig voler continuar amb el RVC per fer clonació. Però les millors proves de clonació les he aconseguit amb el model de síntesi del Matxa v2, que no necessita espeak-ng.
creat per Joan Quintana Compte, setembre 2026