Skip to main content
Version: QTrobot V3

TTS

robot.tts lets QTrobot speak — plain text or SSML, across multiple engines, with full control over voice, language, rate, and pitch. These examples assume you already have a connected robot — see Connection if you haven't set one up yet.

QTrobot ships with Acapela configured as the default TTS engine.

Setup

mkdir ~/example
cd ~/example
python -m venv .venv
# or: uv venv .venv

source .venv/bin/activate

pip install luxai-robot
# or: uv pip install luxai-robot

Connect

from luxai.robot.core import Robot

robot = Robot.connect_zmq(robot_id="QTRD000123")
print(f"connected to {robot.robot_id} ({robot.robot_type})")

See Connection for MQTT, WebRTC, and other connection options.

List engines

# List all loaded/available TTS engine ids
engines = robot.tts.list_engines()
Logger.info(f"Available TTS engines: {engines}")

Languages and voices

# List supported languages for the acapela engine
langs = robot.tts.get_languages(engine="acapela")
Logger.info(f"acapela languages: {langs}")

# List available voices for the acapela engine
voices = robot.tts.get_voices(engine="acapela")
Logger.info(f"acapela voices ({len(voices)}):")
for v in voices:
Logger.info(f" {v}")

Each robot ships with a set of pre-installed Acapela voices, listed above. If you need a voice that isn't installed:

  1. Pick one from the Acapela voice repertoire.
  2. Contact support@luxai.com for instructions on installing it on your robot.

Engine configuration

# Read the current config for the acapela engine
cfg = robot.tts.get_config(engine="acapela")
Logger.info(f"acapela config: {cfg}")

# Update the acapela engine with pitch and rate adjustments
robot.tts.set_config({"pitch": 1.0, "rate": 0.8}, engine="acapela")

Default engine

# Get the current default engine
engine = robot.tts.get_default_engine()
Logger.info(f"Current default TTS engine: {engine}")

# Switch the default engine to 'acapela'
robot.tts.set_default_engine("acapela")

Say text

# Say a simple phrase using the default engine
ret = robot.tts.say_text("Hello, This is spoken with the default settings.")
Logger.info(f"Return {ret}")

# Say text with rate and pitch adjustments
robot.tts.say_text("This is spoken slower at a higher pitch.", engine="acapela", rate=0.85, pitch=1.2)

# Say text with explicit voice override
robot.tts.say_text("This is spoken with the Rosie voice.", engine="acapela", voice="Rosie")

# Say text with an inline Acapela voice tag to adjust speed mid-utterance
robot.tts.say_text(
"I will speak with different speed. \\rspd=130\\ for example now I'm speaking faster. \\rspd=70\\ And now I'm speaking slower.",
engine="acapela",
)

\rspd=130\ above is an Acapela voice tag, not SSML — see SSML below for the distinction.

Cancel speech

import time

# Start a long utterance in non-blocking mode and cancel it after 2 seconds
h = robot.tts.say_text_async("This is a very long sentence. That will be interrupted before it finishes.", engine="acapela")
time.sleep(2)
h.cancel()

SSML

Acapela does not support SSML. Instead, it has its own set of special voice tags (like the \rspd=...\ speed tag used above) — see the Acapela voice tag reference for the full list. SSML is supported by other engines, such as Azure below.

# Check whether each engine supports SSML
engines = robot.tts.list_engines()
for engine in engines:
supported = robot.tts.supports_ssml(engine=engine)
Logger.info(f" {engine}: SSML supported = {supported}")
# Say SSML markup using the azure engine
ssml = (
'<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="en-US">'
' <voice name="en-US-MultiTalker-Ava-Andrew:DragonHDLatestNeural">'
' <mstts:dialog>'
' <mstts:turn speaker="ava">Hello, Andrew! How is your day going?</mstts:turn>'
' <mstts:turn speaker="andrew">Hey Ava! It has been great, just exploring some new features in QTrobot.</mstts:turn>'
' <mstts:turn speaker="ava">That sounds interesting! I believe we are both working on exciting projects.</mstts:turn>'
' </mstts:dialog>'
' </voice>'
'</speak>'
)
ret = robot.tts.say_ssml(ssml, engine="azure")
Logger.info(f"Return {ret}")

Azure TTS

Azure Text-to-Speech is a cloud-based engine offering hundreds of neural voices across 140+ languages, full SSML control (pitch, rate, volume, pauses, pronunciation), and even custom voice cloning. It's a good option when you need a voice, language, or SSML feature Acapela doesn't provide.

1. Get an Azure subscription key

Follow Microsoft's Azure AI Speech documentation to create a free Azure subscription and get your speech resource's subscription key and region.

2. Configure the key on QTRP

From QTPC:

ssh qtrp
sudo nano /opt/luxai/qtrobot_service_hub/etc/tts/azure.yaml

Set your region and subscription key:

parameters:
- name: region
type: string
value: "westeurope" # your Azure resource region

- name: subscription_key
type: string
value: "" # your Azure subscription key

3. Enable the Azure engine

sudo nano /opt/luxai/qtrobot_service_hub/etc/tts/tts.yaml

Add azure to the list of enabled engines:

  - name: engines
type: list[string]
value: [acapela, azure]
scope: cli

4. Restart the service

sudo systemctl restart qtrobot-service-hub.service
sudo systemctl status qtrobot-service-hub.service

Once restarted, azure will show up in robot.tts.list_engines() and is ready to use with say_text(..., engine="azure") or say_ssml(..., engine="azure").

Next steps

Continue with the Face and Emotion tutorial, or see the full robot.tts namespace in the Python API Reference.