Skip to content

Commit

Permalink
refactor(tts): use bitbots_tts consistently (#529)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaagut authored Jul 14, 2024
2 parents b697c82 + 6735a66 commit cecd25a
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 59 deletions.
44 changes: 13 additions & 31 deletions bitbots_misc/bitbots_tts/bitbots_tts/tts.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import rclpy
import requests
from ament_index_python import get_package_prefix
from rcl_interfaces.msg import Parameter, SetParametersResult
from rclpy.node import Node
from rclpy.publisher import Publisher
Expand All @@ -24,6 +25,13 @@ def speak(text: str, publisher: Publisher, priority: int = 20, speaking_active:
publisher.publish(msg)


def say(text: str) -> None:
"""Start the shell `say.sh` script to output given text with mimic3. Beware: this is blocking."""
script_path = os.path.join(get_package_prefix("bitbots_tts"), "lib/bitbots_tts/say.sh")
process = subprocess.Popen((script_path, text))
process.wait()


class Speaker(Node):
"""
Uses tts to say messages from the speak topic.
Expand All @@ -50,17 +58,6 @@ def __init__(self) -> None:
# Callback for parameter changes
self.add_on_set_parameters_callback(self.on_set_parameters)

# Mapping from robot name to voice name
self.robot_voice_mapping = {
"amy": "en_US/vctk_low",
"donna": "en_US/vctk_low",
"jack": "en_UK/apope_low",
"melody": "en_US/vctk_low",
"rory": "en_UK/apope_low",
}

self.robot_speed_mapping = {"amy": 2.2, "donna": 2.2, "jack": 1.0, "melody": 2.2, "rory": 1.0}

# Subscribe to the speak topic
self.create_subscription(Audio, "speak", self.speak_cb, 10)

Expand Down Expand Up @@ -92,30 +89,15 @@ def on_set_parameters(self, parameters: List[Parameter]) -> SetParametersResult:
return SetParametersResult(successful=True)

def run_speaker(self) -> None:
"""Continously checks the queue and speaks the next message."""
"""Continuously checks the queue and speaks the next message."""
# Check if there is a message in the queue
if len(self.prio_queue) > 0:
# Get the next message and speak it
text, _ = self.prio_queue.pop(0)
self.say(text)

def say(self, text: str) -> None:
"""Speak this specific text."""
# Get the voice name from the environment variable ROBOT_NAME or use the default voice if it's not set
voice = self.robot_voice_mapping.get(os.getenv("ROBOT_NAME"), "en_US/vctk_low")
# Get the speed for the given robot or use the default speed if no robot name is set
speed = self.robot_speed_mapping.get(os.getenv("ROBOT_NAME"), 2.2)
try:
# Generate the speech with mimic
mimic_subprocess = subprocess.Popen(
("mimic3", "--remote", "--voice", voice, "--length-scale", str(speed), text), stdout=subprocess.PIPE
)
# Play the audio from the previous process with aplay
aplay_subprocess = subprocess.Popen(("aplay", "-"), stdin=mimic_subprocess.stdout, stdout=subprocess.PIPE)
# Wait for the process to finish
aplay_subprocess.wait()
except OSError:
self.get_logger().error(str(traceback.format_exc()))
try:
say(text)
except OSError:
self.get_logger().error(str(traceback.format_exc()))

def speak_cb(self, msg: Audio) -> None:
"""Handles incoming msg on speak topic."""
Expand Down
4 changes: 3 additions & 1 deletion bitbots_misc/bitbots_tts/launch/tts.launch
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<launch>
<executable cmd="mimic3-server --preload-voice en_US/vctk_low --cache-dir $(env HOME)/.cache/mimic3/" name="mimic3-server" output="screen"/>
<!-- Do not launch mimic3-server on robot, as it is running as a systemd service -->
<executable unless="$(env IS_ROBOT)" cmd="mimic3-server --preload-voice en_US/vctk_low --preload-voice en_UK/apope_low --cache-dir $(env HOME)/.cache/mimic3/" name="mimic3-server" output="screen"/>

<node name="bitbots_tts" pkg="bitbots_tts" exec="tts">
<param from="$(find-pkg-share bitbots_tts)/config/tts_config.yaml"/>
</node>
Expand Down
30 changes: 30 additions & 0 deletions bitbots_misc/bitbots_tts/scripts/say.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -eEuo pipefail

ROBOT_NAME="${ROBOT_NAME:-}"

# Mapping robot name to voice and speed
case "$ROBOT_NAME" in
"jack"|"rory")
voice="en_UK/apope_low"
speed=1.0
;;
"amy"|"donna"|"melody"|"rose")
voice="en_US/vctk_low"
speed=1.7
;;
*)
echo "Unknown robot: '$ROBOT_NAME', using default female voice"
voice="en_US/vctk_low"
speed=1.7
;;
esac

text="$1"
if [ -z "$text" ]; then
echo "No text provided!"
exit 1
fi

# Generate the speech with mimic and play it with alsa
mimic3 --remote --voice "$voice" --length-scale "$speed" "$text" | aplay -q -
19 changes: 19 additions & 0 deletions bitbots_misc/bitbots_tts/scripts/speak_ip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3

import os
from socket import gethostname

from bitbots_tts.tts import say
from netifaces import AF_INET, ifaddresses, interfaces

ip_address = "not set"

wifi_interface = next(filter(lambda i: i.startswith("wlp"), interfaces()), None)
if wifi_interface and AF_INET in ifaddresses(wifi_interface):
ip_address = ifaddresses(wifi_interface)[AF_INET][0]["addr"]

ip = " dot ".join(ip_address.split("."))

robot_name = os.getenv("ROBOT_NAME") or gethostname()
msg = f"Startup complete: {robot_name}. My wifi IP is {ip}."
say(msg)
2 changes: 1 addition & 1 deletion bitbots_misc/bitbots_tts/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
install_requires=[
"setuptools",
],
scripts=["scripts/send_text.py"],
scripts=glob.glob("scripts/*"),
entry_points={
"console_scripts": [
"tts = bitbots_tts.tts:main",
Expand Down
26 changes: 0 additions & 26 deletions bitbots_misc/bitbots_utils/scripts/speak_ip.py

This file was deleted.

0 comments on commit cecd25a

Please sign in to comment.