Hi.
Have someone made their own tts-speaker that works with HA, using Raspberry Pi or similar?
I know that I could use google mini/Amazon Echo/Sonos as speaker. But in this case is not what Im looking for. I only need a speaker that play the tts when activated by HA. So if someone would like to share their project I will appreciate it.
- CPU: ESP32-S3 N16R8
- Amp: MAX98357A
- Led: The onboard LED is used
substitutions:
name: "espeaker"
friendly_name: ESPeaker
esp_speaker_connect_sound: "http://x.x.x.x:8123/local/sounds/esp_speaker_started.mp3"
# ================================
# === Please do not edit below ===
# ================================
music_player_idle_id: "1"
music_player_playing_id: "2"
music_player_muted_id: "3"
esp_speaker_not_ready_phase_id: "10"
esp_speaker_error_phase_id: "11"
esphome:
name: ${name}
friendly_name: ${friendly_name}
min_version: 2024.6.0
name_add_mac_suffix: false
project:
name: AA_van_Zoelen.ESPeaker
version: '1.1.0'
on_boot:
priority: 600
then:
- script.execute: control_led
- delay: 30s
- if:
condition:
lambda: return id(init_in_progress);
then:
- lambda: id(init_in_progress) = false;
- script.execute: control_led
esp32:
board: esp32-s3-devkitc-1
variant: esp32s3
framework:
type: arduino
psram:
mode: quad # Please change this to quad for N8R2 and octal for N16R8
speed: 80MHz
globals:
- id: init_in_progress
type: bool
restore_value: false
initial_value: "true"
- id: esp_speaker_phase
type: int
restore_value: false
initial_value: ${esp_speaker_not_ready_phase_id}
- id: played_startup
type: bool
restore_value: false
initial_value: "false"
logger:
api:
encryption:
key: !secret api_key
on_client_connected:
- script.execute: control_led
on_client_disconnected:
- script.execute: control_led
ota:
platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
on_connect:
- script.execute: control_led
on_disconnect:
- script.execute: control_led
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: !secret fallback_ssid
password: !secret fallback_password
captive_portal:
i2s_audio:
- id: i2s_audio_bus
i2s_lrclk_pin: GPIO6
i2s_bclk_pin: GPIO7
media_player:
- platform: i2s_audio
id: media_out
name: ESP Speaker
dac_type: external
i2s_audio_id: i2s_audio_bus
i2s_dout_pin: GPIO8
mode: stereo #mono
on_play:
- logger.log: "Playback started!"
- lambda: id(esp_speaker_phase) = ${music_player_playing_id};
- if:
condition:
switch.is_on: status_led
then:
- script.execute: control_led
on_pause:
- logger.log: "Playback paused!"
- lambda: id(esp_speaker_phase) = ${music_player_muted_id};
- if:
condition:
switch.is_on: status_led
then:
- script.execute: control_led
on_idle:
- logger.log: "Playback finished!"
- lambda: id(esp_speaker_phase) = ${music_player_idle_id};
- if:
condition:
switch.is_on: status_led
then:
- script.execute: control_led
switch:
- platform: template
name: "Status LED"
id: status_led
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
icon: mdi:bell
on_turn_off:
- light.turn_off:
id: onboard_led
on_turn_on:
- script.execute: control_led
light:
- platform: esp32_rmt_led_strip
id: onboard_led
rgb_order: GRB
pin: GPIO48
num_leds: 1
rmt_channel: 0
chipset: ws2812
effects:
- pulse:
name: "Slow Pulse"
transition_length: 250ms
update_interval: 250ms
min_brightness: 60%
max_brightness: 80%
- pulse:
name: "Fast Pulse"
transition_length: 100ms
update_interval: 100ms
min_brightness: 60%
max_brightness: 80%
- pulse:
name: "Playing"
min_brightness: 20%
max_brightness: 40%
transition_length: 3s # defaults to 1s
update_interval: 3s
script:
- id: control_led
then:
- if:
condition:
lambda: return !id(init_in_progress);
then:
- if:
condition:
wifi.connected:
then:
- if:
condition:
api.connected:
then:
- lambda: |
switch(id(esp_speaker_phase)) {
case ${music_player_idle_id}:
id(media_player_idle_state).execute();
break;
case ${music_player_playing_id}:
id(media_player_playing_state).execute();
break;
case ${music_player_muted_id}:
id(media_player_muted_state).execute();
break;
case ${esp_speaker_not_ready_phase_id}:
id(control_led_esp_speaker_not_ready_phase).execute();
break;
case ${esp_speaker_error_phase_id}:
id(control_led_esp_speaker_error_phase).execute();
break;
default:
break;
}
else:
- script.execute: control_led_no_ha_connection_state
else:
- script.execute: control_led_no_ha_connection_state
else:
- script.execute: control_led_init_state
# Media player stated playing displayed via the on board LED
- id: media_player_playing_state
then:
- light.turn_on:
id: onboard_led
blue: 5%
red: 5%
green: 0%
brightness: 5%
effect: "Playing"
# Media player stated muted displayed via the on board LED
- id: media_player_muted_state
then:
- light.turn_on:
id: onboard_led
blue: 60%
red: 0%
green: 0%
brightness: 65%
effect: "Fast Pulse"
# Media player stated idle displayed via the on board LED
- id: media_player_idle_state
then:
- light.turn_on:
id: onboard_led
blue: 0%
red: 15%
green: 15%
brightness: 15%
effect: "None"
# Script executed during initialisation
- id: control_led_init_state
then:
- light.turn_on:
id: onboard_led
blue: 0%
red: 0%
green: 100%
brightness: 50%
effect: "Fast Pulse"
- if:
condition:
lambda: return !id(played_startup);
then:
- media_player.volume_set:
id: media_out
volume: 50%
- media_player.play_media: ${esp_speaker_connect_sound}
- lambda: id(played_startup) = "true";
# Script executed when the device has no connection to Home Assistant
- id: control_led_no_ha_connection_state
then:
- light.turn_on:
id: onboard_led
blue: 0%
red: 50%
green: 0%
brightness: 50%
effect: "Slow Pulse"
# Script executed when the esp speaker is not ready
- id: control_led_esp_speaker_not_ready_phase
then:
- light.turn_off:
id: onboard_led
# Script executed when the esp speaker encounters an error
- id: control_led_esp_speaker_error_phase
then:
- light.turn_on:
id: onboard_led
blue: 0%
red: 100%
green: 0%
brightness: 98%
effect: "none"
# Diagnosics
sensor:
- platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
name: "WiFi Signal dB"
id: wifi_signal_db
update_interval: 60s
entity_category: "diagnostic"
- platform: copy # Reports the WiFi signal strength in %
source_id: wifi_signal_db
name: "WiFi Signal Percent"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "Signal %"
entity_category: "diagnostic"
device_class: ""
- platform: uptime
name: Uptime Sensor
# Diagnosics
button:
- platform: restart
id: "restart_device"
name: "Restart"
entity_category: "diagnostic"
# - platform: safe_mode
# id: "restart_device_safe_mode"
# name: "Restart (Safe Mode)"
# entity_category: "diagnostic"
# Diagnosics
text_sensor:
# Expose WiFi information as sensors.
- platform: wifi_info
ip_address:
name: IP
ssid:
name: SSID
bssid:
name: BSSID
Nice!
Think I will give it a try. Do you also have some recommendation for speaker to use?
Guess a 4ohm speaker at max 2-3watt?
Is it something else that I should be aware of?
thanks in advance and for that you sharing your project
A small speaker in a small housing will give you a flimsy sound. That said make sure you have a reasonable volume in your housing. Also make the outside sturdy. So when using a 3W 4-8ohm speaker the sound will have more body to it. More bass.
The last picture is a very small speaker and it will mainly produce mid and high tones while the other are larger and have also bass tones
The last one is a 3D resin print
The cilindercal version is just a pvc pipe
The round one is made from 2 bamboe snack bowls. The bottle on top contains ferrofluid and it ‘dance’ on the ritme of the music. This one is the largest. The speaker comes from a old pc speaker box bought for €5,- at a 2nd hand store