Gandr text to speech as a Haystack component.
pip install gandr-haystackimport os
from gandr_haystack import GandrTTS
tts = GandrTTS(voice="gandr-mia") # reads GANDR_API_KEY from the env
result = tts.run(text="Your appointment is confirmed for Tuesday at two fifteen.",
path="out.wav")
result["audio"] # WAV bytesIn a pipeline:
from haystack import Pipeline
pipe = Pipeline()
pipe.add_component("tts", GandrTTS())
pipe.run({"tts": {"text": "Hello from Haystack."}})| Parameter | Default | Notes |
|---|---|---|
api_key |
Secret.from_env_var("GANDR_API_KEY") |
Keys start with gnd_ |
voice |
gandr-mia |
Also gandr-ava, gandr-jenny, gandr-dane, gandr-leo, gandr-lewis |
language |
en |
ISO code |
sample_rate |
24000 |
One of 8000, 16000, 22050, 24000 |
url |
https://tts.gandr.ai/v1/tts/bytes |
Override to pin a region |
timeout |
60.0 |
Seconds |
run() returns {"audio": bytes, "path": str | None}. Pass path to write the
WAV to disk as well as returning it.
The component serializes with to_dict() and from_dict(), and the key is held
as a Haystack Secret read from the environment, so saved pipelines never carry
the token.
Haystack will not deserialize a third-party component unless its module is allowlisted. That is Haystack's security model, not a quirk of this package, and it applies to every community integration:
from haystack.core.serialization import allow_deserialization_module
allow_deserialization_module("gandr_haystack.tts")Or set HAYSTACK_DESERIALIZATION_ALLOWLIST=gandr_haystack.tts in the environment.
Saving with to_dict() needs nothing.
An HTTP failure raises RuntimeError carrying the API's own status and message,
so a 401 (key) and a 402 (quota) are told apart rather than guessed at.
$10 per million tokens, or $150 a month for one unlimited concurrent stream. Free key, 50,000 tokens: gandr.ai
MIT.