Hello,
I have been working over the past few days on creating a voice assistant using the following hardware:
- ESP32‑S3
- MAX98357 (amp I2S)
- INMP441 (mic I2S)
The voice commands work without any problems, the LED on the ESP32 controller lights up, but there is no sound. I’ve already replaced the amplifier and the speakers, and the dashboard shows that something is playing, but there is no audio.
In other words, I’ve tried everything — even several different configurations — but nothing seems to work. Could someone help me with this problem? I would greatly appreciate it
P.S.: All assistant pipeline are installed and no errors in the log files.
Below you can config used:
esphome:
name: esp-voiceassistant-2
friendly_name: esp-voiceassistant-02
'''
esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
flash_size: 16MB
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret api_voice_2
ota:
- platform: esphome
password: !secret ota_voice_2
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Static IPs
manual_ip:
static_ip: !secret ip_voice_2
gateway: !secret gtw_wifi
subnet: 255.255.255.0
dns1: !secret dns1_wifi
psram:
mode: octal
speed: 80MHz
# -----------------------
# -----------------------
# I2S BUS
# -----------------------
i2s_audio:
- id: bus
i2s_bclk_pin: GPIO5
i2s_lrclk_pin: GPIO4
# -----------------------
# MICROPHONE
# -----------------------
microphone:
- platform: i2s_audio
id: echo_microphone
i2s_audio_id: bus
i2s_din_pin: GPIO6
adc_type: external
sample_rate: 16000
bits_per_sample: 32bit
channel: left
#use_apll: True
# -----------------------
# SPEAKER
# -----------------------
speaker:
- platform: i2s_audio
id: echo_speaker
i2s_audio_id: bus
i2s_dout_pin: GPIO7
dac_type: external
channel: left
bits_per_sample: 16bit
buffer_duration: 80ms
media_player:
- platform: speaker
name: None
id: echo_media_player
announcement_pipeline:
speaker: echo_speaker
format: FLAC
codec_support_enabled: False
buffer_size: 6000
volume_min: 0.5
volume_increment: 0.25
on_volume:
then:
- light.turn_on:
id: led
effect: "Volume Level Display"
- delay: 1s
- light.turn_off:
id: led
files:
- id: mute_switch_on_sound
file: https://github.com/WarLion/wakeword-files/raw/refs/heads/main/mute_switch_on.wav
- id: mute_switch_off_sound
file: https://github.com/WarLion/wakeword-files/raw/refs/heads/main/mute_switch_off.wav
- id: timer_finished_wave_file
file: https://github.com/WarLion/wakeword-files/raw/refs/heads/main/timer_finished.wav
- id: boot
file: https://github.com/WarLion/wakeword-files/raw/refs/heads/main/wake_word_triggered.wav
on_announcement:
- if:
condition:
- microphone.is_capturing:
then:
- script.execute: stop_wake_word
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_idle:
- script.execute: start_wake_word
- script.execute: reset_led
voice_assistant:
id: va
micro_wake_word:
microphone:
microphone: echo_microphone
channels: 0
gain_factor: 4
media_player: echo_media_player
noise_suppression_level: 2
auto_gain: 31dBFS
on_listening:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Slow Pulse"
on_stt_vad_end:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Fast Pulse"
on_tts_start:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_end:
# Handle the "nevermind" case where there is no announcement
- wait_until:
condition:
- media_player.is_announcing:
timeout: 0.5s
# Restart only mWW if enabled; streaming wake words automatically restart
- if:
condition:
- lambda: |-
return id(wake_word_engine_location).current_option() == "On device";
then:
- wait_until:
- and:
- not:
voice_assistant.is_running:
- not:
speaker.is_playing:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- script.execute: reset_led
on_error:
- light.turn_on:
id: led
red: 100%
green: 0%
blue: 0%
brightness: 100%
effect: none
- delay: 2s
- script.execute: reset_led
on_client_connected:
- delay: 2s # Give the api server time to settle
- script.execute: start_wake_word
on_client_disconnected:
- script.execute: stop_wake_word
on_timer_finished:
- script.execute: stop_wake_word
- wait_until:
not:
microphone.is_capturing:
- switch.turn_on: timer_ringing
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 0%
brightness: 100%
effect: "Fast Pulse"
- wait_until:
- switch.is_off: timer_ringing
- light.turn_off: led
- switch.turn_off: timer_ringing
light:
- platform: esp32_rmt_led_strip
id: led
name: None
disabled_by_default: true
entity_category: config
pin: GPIO48
default_transition_length: 0s
chipset: WS2812
num_leds: 1
rgb_order: grb
effects:
- pulse:
name: "Slow Pulse"
transition_length: 250ms
update_interval: 250ms
min_brightness: 50%
max_brightness: 100%
- pulse:
name: "Fast Pulse"
transition_length: 100ms
update_interval: 100ms
min_brightness: 50%
max_brightness: 100%
script:
- id: reset_led
then:
- if:
condition:
- lambda: |-
return id(wake_word_engine_location).current_option() == "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 100%
green: 89%
blue: 71%
brightness: 60%
effect: none
else:
- if:
condition:
- lambda: |-
return id(wake_word_engine_location).current_option() == "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 100%
brightness: 60%
effect: none
else:
- light.turn_off: led
- id: start_wake_word
then:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: |-
return id(wake_word_engine_location).current_option() == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: |-
return id(wake_word_engine_location).current_option() == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- id: stop_wake_word
then:
- if:
condition:
lambda: |-
return id(wake_word_engine_location).current_option() == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- if:
condition:
lambda: |-
return id(wake_word_engine_location).current_option() == "On device";
then:
- micro_wake_word.stop:
switch:
- platform: template
name: Use listen light
id: use_listen_light
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
entity_category: config
on_turn_on:
- script.execute: reset_led
on_turn_off:
- script.execute: reset_led
- platform: template
id: timer_ringing
optimistic: true
restore_mode: ALWAYS_OFF
on_turn_off:
# Turn off the repeat mode and disable the pause between playlist items
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 0);
# Stop playing the alarm
- media_player.stop:
announcement: true
on_turn_on:
# Turn on the repeat mode and pause for 1000 ms between playlist items/repeats
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 1000);
- media_player.speaker.play_on_device_media_file:
media_file: timer_finished_wave_file
announcement: true
- delay: 15min
- switch.turn_off: timer_ringing
select:
- platform: template
entity_category: config
name: Wake word engine location
id: wake_word_engine_location
optimistic: true
restore_value: true
options:
- In Home Assistant
- On device
initial_option: On device
on_value:
- if:
condition:
lambda: return x == "In Home Assistant";
then:
- micro_wake_word.stop:
- delay: 500ms
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- if:
condition:
lambda: return x == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- delay: 500ms
- micro_wake_word.start:
micro_wake_word:
on_wake_word_detected:
- voice_assistant.start:
wake_word: !lambda return wake_word;
vad:
models:
- model: okay_nabu
- model: hey_mycroft
- model: hey_jarvis