Online kwam ik een artikel tegen waarbij de auteur de stappen toont om XTTS-v2 te installeren. Wat me nogal vaak opvalt is dat dit soort blog posts verre van compleet zijn. Je zou bijna gaan denken dat het een vorm van clickbait is. Niet dat ik de auteur daarvan beschuldig hoor, integendeel. Hierbij dan ook mijn poging om het werkend te krijgen en wat meer diepgang te geven.
Ter info, ik gebruik in dit geval een Mac M1 machine. Onder Linux zullen de stap relatief hetzelfde zijn, vermoed ik.
In stap 1 wordt de repository van het project vanaf de git omgeving van huggingface gedownload.
git clone https://huggingface.co/coqui/XTTS-v2
De auteur gaat vervolgens de 'virtual environment' activeren, maar deze bestaat nog helemaal niet. Dus die gaan we aanmaken in de map van het project. Omdat ik in het verleden problemen ondervond met de hoogst geïnstalleerde versie van Python op mijn machine, kies ik ervoor om Python 3.10 te testen.
cd XTTS-v2/
python3.10 -m venv .
source ./bin/activate
Hierna zou de virtuale environment actief moeten zijn (bij mij verschijnt er (XTTS-v2)
voor de command prompt. Waarom we dit doen? Op deze manier kunnen we het project scheiden van andere installaties op onze machine, zodat ze elkaar minder beïnvloeden.
De auteur wil vervolgens de requirements installeren. Dit kan je doen door alle benodigde pakketten in een bestandje te benoemen en dit met een commando te laten installeren. Hij heeft echter de volgorde verkeerd om staan. Dus we draaien het even om. We maken eerst het bestand requirements.txt
aan. Ik heb een kleine wijziging erin gemaakt, wat veel vaker fout gaat bij dit soort blog posts en dat is het gebruik van PyTorch
. Veelal wordt er verwezen naar een versie die niet meer bestaat. Op de PyTorch pagina is dezelfde versie wel te vinden, maar zonder de aanvulling op het versie nummer:
cat <<EOF > requirements.txt
absl-py==2.1.0
aiohappyeyeballs==2.4.3
aiohttp==3.11.2
aiosignal==1.3.1
annotated-types==0.7.0
anyascii==0.3.2
asttokens==2.4.1
attrs==24.2.0
audioread==3.0.1
babel==2.16.0
bangla==0.0.2
blinker==1.9.0
blis==0.7.11
bnnumerizer==0.0.2
bnunicodenormalizer==0.1.7
catalogue==2.0.10
certifi==2024.8.30
cffi==1.17.1
charset-normalizer==3.4.0
click==8.1.7
cloudpathlib==0.20.0
colorama==0.4.6
confection==0.1.5
contourpy==1.3.1
coqpit==0.0.17
cycler==0.12.1
cymem==2.0.8
Cython==3.0.11
dateparser==1.1.8
decorator==5.1.1
docopt==0.6.2
einops==0.8.0
encodec==0.1.1
executing==2.1.0
filelock==3.13.1
Flask==3.1.0
fonttools==4.55.0
frozenlist==1.5.0
fsspec==2024.2.0
g2pkk==0.1.2
grpcio==1.68.0
gruut==2.2.3
gruut-ipa==0.13.0
gruut_lang_de==2.0.1
gruut_lang_en==2.0.1
gruut_lang_es==2.0.1
gruut_lang_fr==2.0.2
hangul-romanize==0.1.0
huggingface-hub==0.26.2
idna==3.10
inflect==7.4.0
ipython==8.29.0
itsdangerous==2.2.0
jamo==0.4.1
jedi==0.19.2
jieba==0.42.1
Jinja2==3.1.3
joblib==1.4.2
jsonlines==1.2.0
kiwisolver==1.4.7
langcodes==3.4.1
language_data==1.2.0
lazy_loader==0.4
librosa==0.10.2.post1
llvmlite==0.43.0
marisa-trie==1.2.1
Markdown==3.7
markdown-it-py==3.0.0
MarkupSafe==2.1.5
matplotlib==3.9.2
matplotlib-inline==0.1.7
mdurl==0.1.2
more-itertools==10.5.0
mpmath==1.3.0
msgpack==1.1.0
multidict==6.1.0
murmurhash==1.0.10
networkx==2.8.8
nltk==3.9.1
num2words==0.5.13
numba==0.60.0
numpy==1.26.3
packaging==24.2
pandas==1.5.3
parso==0.8.4
pillow==10.2.0
platformdirs==4.3.6
pooch==1.8.2
preshed==3.0.9
prompt_toolkit==3.0.48
propcache==0.2.0
protobuf==5.28.3
psutil==6.1.0
pure_eval==0.2.3
pycparser==2.22
pydantic==2.9.2
pydantic_core==2.23.4
Pygments==2.18.0
pynndescent==0.5.13
pyparsing==3.2.0
pypinyin==0.53.0
pysbd==0.3.4
python-crfsuite==0.9.11
python-dateutil==2.9.0.post0
pytz==2024.2
PyYAML==6.0.2
regex==2024.11.6
requests==2.32.3
rich==13.9.4
safetensors==0.4.5
scikit-learn==1.5.2
scipy==1.14.1
shellingham==1.5.4
six==1.16.0
smart-open==7.0.5
soundfile==0.12.1
soxr==0.5.0.post1
spacy==3.7.5
spacy-legacy==3.0.12
spacy-loggers==1.0.5
srsly==2.4.8
stack-data==0.6.3
SudachiDict-core==20241021
SudachiPy==0.6.8
sympy==1.13.1
tensorboard==2.18.0
tensorboard-data-server==0.7.2
thinc==8.2.5
threadpoolctl==3.5.0
tokenizers==0.20.3
# Verwijderd vanwege versie problemen
# torch==2.5.1+cu124
# torchaudio==2.5.1+cu124
# torchvision==0.20.1+cu124
torch==2.5.1
torchaudio==2.5.1
torchvision==0.20.1
tqdm==4.67.0
trainer==0.0.36
traitlets==5.14.3
transformers==4.46.2
typeguard==4.4.1
typer==0.13.0
typing_extensions==4.12.2
tzdata==2024.2
tzlocal==5.2
umap-learn==0.5.7
Unidecode==1.3.8
urllib3==2.2.3
wasabi==1.1.3
wcwidth==0.2.13
weasel==0.4.1
Werkzeug==3.1.3
wrapt==1.16.0
yarl==1.17.1
EOF
Om deze vervolgens te gebruiken om de pakketten te installeren:
pip install -r requirements.txt
Als alles meezit wordt alles zonder meldingen geïnstalleerd. De oplossing van het versienummer werkt voor mij in ieder geval.
Vervolgens gaan we TTS installeren. De schrijver heeft het over dat deze installatie wel 40 minuten kan duren, maar 3 seconden later is hij klaar. Het is mij onduidelijk waarom hij dit schreef.
pip install TTS==0.22.0 --no-deps
In het vervolg wil hij PyTorch
gaan installeren, maar dit is al gebeurd. Het lijkt wel of deze blog posts verkeerd om gepubliceerd is. En hierna houdt de post ook op. Wat hebben we nu bereikt? Nou, eigenlijk niet zoveel tot zo ver.
In de readme.md
staat nog wat informatie van het project zelf. We nemen het eerste voorbeeld en passen hem een beetje aan. Aangezien het een variant is de voice cloning gebruikt, is er een audio sample nodig. Er staan een aantal voorbeelden in de samples
map. Hiernaast is het voorbeeld wat verouderd. We passen het gpu=True
aan naar tts.to("mps")
. mps
is de GPU acceleratie voor m1 processoren. Voor NVidea GPU's kan je cuda
gebruiken.
cat <<EOF > test-1.py
from TTS.api import TTS
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
tts.to("mps")
# generate speech by cloning a voice using default settings
tts.tts_to_file(text="It took me quite a long time to develop a voice, and now that I have it I'm not going to be silent.",
file_path="output.wav",
speaker_wav="./samples/en_sample.wav",
language="en")
EOF
python ./test-1.py
Na uitvoer loop ik tegen het volgende probleem aan:
NotImplementedError: Output channels > 65536 not supported at the MPS device. As a temporary fix, you can set the environment variable `PYTORCH_ENABLE_MPS_FALLBACK=1` to use the CPU as a fallback for this op. WARNING: this will be slower than running natively on MPS.
En hier begint dan ook meteen de ellende. Ik zou willen proberen of een nieuwere PyTorch
versie dit oplost, maar dat kan niet zomaar. Na het aanpassen naar de laatste versie (2.7.0) moet ook sympy>=1.13.3 worden geïnstalleerd, wat weer leid tot het volgende:
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
tts 0.22.0 requires numpy==1.22.0; python_version <= "3.10", but you have numpy 1.26.3 which is incompatible.
Na het weer terug zetten van de requirements, probeer ik het voorstel wat in het log voorbij komt:
export PYTORCH_ENABLE_MPS_FALLBACK=1; python test-1.py
Dit lijkt geen effect te hebben. Als alternatief kunnen we tts.to("cpu")
in het script gebruiken. En dit werkt wel! Maar ja, wel een stuk trager dan we zouden willen natuurlijk. Na het aanpassen naar cpu
werkt het voorbeeld en hebben we een output.wav
bestand.
Inmiddels geloof ik wel dat Engels behoorlijk goed uitgesproken kan worden met TTS systemen, maar Nederlands is nog vaak een probleem. Om dit te testen pas ik het script aan met een Nederlandse tekst en gebruik hierbij de engelse sample.
from TTS.api import TTS
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
tts.to("cpu")
# generate speech by cloning a voice using default settings
tts.tts_to_file(text="Het is belangrijk dat het geluid duidelijk uitgesproken wordt, en daardoor verstaanbaar is.",
file_path="output.wav",
speaker_wav="./samples/en_sample.wav",
language="nl")
En het resultaat is erg goed! Een test met de Spaanse stem (een mannelijke stem) werkt wel, maar is niet geweldig. Ook de Franse sample levert niet echt geweldig resultaat. Het is overigens wel verstaanbaar. Als test heb ik online een audio sample gezocht, en met wat uitproberen komen er behoorlijk goede resultaten uit.
De snelheid op deze manier is helaas wel een puntje. Interessant zou zijn om het op een CUDA compatible systeem te testen, of te onderzoeken of en hoe dit direct met PyTorch te doen is.