ESP32 running out of RAM / crashing on recent ESPHome versions (I2S Media Player works fine in 2025.10) — Is this fixable?

Hi everyone,

I’m struggling with an issue regarding an I2S Media Player setup on an ESP32.

My hardware and YAML configuration work perfectly under ESPHome version 2025.10. However, updating to any recent/latest version of ESPHome results in the ESP32 either crashing or having no audio output.

It seems that newer ESPHome core/component updates introduce higher memory consumption (RAM), causing the ESP32 to run out of heap memory during playback or initialization. Since the exact same hardware runs flawlessly on 2025.10, I know the hardware itself is fine.

I’ve been trying to migrate this setup for a long time (2years ) (including testing various suggestions from AI models, Reddit, and forum posts), but haven’t found a working solution to get this I2S media player running on modern ESPHome releases.

Question:

  1. Is there a known fix or a way to reduce the memory footprint of the newer ESPHome core / I2S media player stack?

Hardware & Configuration Details:

  • Board: ESP32-WROOM-32)*

  • I2S DAC / Hardware: * PCM5102 / I2S DAC board*

i2s_audio:
  i2s_lrclk_pin: GPIO15
  i2s_bclk_pin: GPIO4

media_player:
  - platform: i2s_audio
    name: Voice Assistant Speaker
    dac_type: external
    i2s_dout_pin: GPIO14
    mode: mono
    on_pause: 
      then:
        #- media_player.stop: 



button:
  - platform: template
    name: stubru
    id: stubrudrukknop
    # Optional variables:
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "stubru pressed"  
      - media_player.stop
      - media_player.volume_set: 0.4
      - delay: 0.1s
      - media_player.play_media: 'http://icecast.vrtcdn.be/stubru-mid.mp3'

Thanks in advance for any insights or suggestions!

Share your full config.

Did you read this section of the docs:

Does your esp32 board have PSRAM?
Is it explicitly configured?

hello , this code works fine in esphome2025.10

esphome:
  name: mac5060
  friendly_name: mac5060
  #min_version: "2025.3.0" #2025 
  on_boot: 
    then:
      - rtttl.play:  "two_short:d=4,o=5,b=100:16e6,16e6"
 
 
    
esp32:
  board: esp32dev
  framework:
    type:  arduino


substitutions:
  device_name: mac5060      

# Enable logging 
logger:


http_request:
  useragent: esphome/device
  timeout: 10s  
  verify_ssl: false  

# Enable Home Assistant API
api:  
  encryption:
    key: "1A79q+SCGygjqY1PP8ITC6UlelCHr5ln8jjSmCQMMEk="

ota:
  - platform: esphome
    password: "d125ba4bc02c669bcc9fe1f4ee45876f"



wifi:
  reboot_timeout : 9min
  fast_connect: True  
  power_save_mode: none
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password
  

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "mac5060 Hotspot"
    password: "kipkipkip" 
 

 #######gasmeter 
globals:
  - id: total_pulses
    type: int
    restore_value: false
    initial_value: '0'

 
 

 
 


one_wire:
  - platform: gpio
    pin: 22
    

sensor:


# Individual sensors
#sensor:mac5060  
  - platform: dallas_temp
    #address:   0x5ec1e3a308646128  #0x708acea308646128 #zie log tijdens het opstarten wat je adres is0x3ac7f0a308646128 
    name: "Garage Temperature"  
    id: mac5060ds1820
    update_interval:  20s  #190s
 


 
 


 



# Example configuration entry
output:
  - platform: ledc
    pin: GPIO27
    id: buzzer_output


rtttl:
  output: buzzer_output
  


  
 

## blauwe builtin Led op gpio_2
switch:
  - platform: gpio
    pin: GPIO2  # Change this to the GPIO pin you want to control
    name: "indicatorledblauw"
    id : indicatorledblauw
    icon: "mdi:led-outline"   
    inverted: False   



#switch:
  - platform: output 
    name: 'buzzer'
    id: buzzer
    output: buzzer_output
    on_turn_on: 
      then:
        - rtttl.play:  'mission_imp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d'
    on_turn_off:
      then:
        - output.turn_off: buzzer_output



button:
  - platform: template
    name: buzzerpieppiep
    id: buzzerpieppiep
    icon: "mdi:emoticon-outline"
    on_press:
      - rtttl.play: 'locked:d=4,o=5,b=140:32d6,32p,32d6'
        
  - platform: template
    name: tuuttuut
    id: tuuttuut
    icon: "mdi:emoticon-outline"
    on_press:
      - rtttl.play:  "two_short:d=4,o=5,b=100:16e6,16e6"

 
  - platform: restart
    name: ${device_name}_restart    

  - platform: template
    name: buzzerstarwars
    id: my_drukknop

    # Optional variables:
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "Button buzzerstarwars pressed"  
      - rtttl.play:  'LastChri:d=4,o=5,b=112:16d6,e6,e6,8d6,a,8e6,8e6,8f#6,d.6,8b,8b,8e6,8e6,f#6,d.6,8b,8c#6,8d6,8c#6,2b,16e6,f#6,e.6,8b,8f#6,8g6,8f#6,2e6,8d6,8c#6,8d6,8c#6,c#6,8d6,8c#6,2a,16d6,e6,e6,8d6,8a,8e6,8e6,8f#6,d.6,8b,8b,8e6,8e6,f#6,d6,8b,8c#6,8d6,8c#6,b,16e6,f#6,e.6,8b,8f#6,8g6,8f#6,2e6,8d6,8c#6,8d6,8c#6,c#6,8d6,8c#6,a'


#button:
  - platform: template
    name: buzzerCarolBells
    id: buzzerCarolBells
    icon: "mdi:emoticon-outline"
    on_press:
      - rtttl.play:  'CarolBells:d=8,o=5,b=180:4a,g#,a,4f#,4a,g#,a,4f#,4f#6,f#6,f#6,e6,d6,4c#6,c#6,c#6,b,a,4b,b,b,c#6,b,4f#,f#,f#,4f#,c#,d#,e,f#,g#,a,b,c#6,4b,4a,c#,d#,e,f#,g#,a,b,c#6,4b,4a,4a,g#,a,4f#,4a,g#,a,4f#'



#button:
  - platform: template
    name: radio1
    id: radio1drukknop

    # Optional variables:
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "radio 1 pressed"  
      - media_player.stop
      - delay: 0.1s
      - media_player.play_media: 'http://icecast.vrtcdn.be/radio1-mid.mp3'


#button:
  - platform: template
    name: radio2
    id: radio2drukknop

    # Optional variables:
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "radio 2 pressed"  
      - media_player.stop
      - delay: 0.1s
      - media_player.play_media: 'http://icecast.vrtcdn.be/ra2wvl-mid.mp3'

#button:
  - platform: template
    name: stubru
    id: stubrudrukknop
    # Optional variables:
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "stubru pressed"  
      - media_player.stop
      - media_player.volume_set: 0.4
      - delay: 0.1s
      - media_player.play_media: 'http://icecast.vrtcdn.be/stubru-mid.mp3'

#button:
  - platform: template
    name: joe8090
    id: joe8090drukknop
    # Optional variables:
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "joe8090 pressed"  
      - media_player.stop
      - media_player.volume_set: 0.4
      - delay: 0.1s
      - media_player.play_media: 'https://streams.radio.dpgmedia.cloud/redirect/joe_80s_90s/mp3'  
 

#button:
  - platform: template
    name: stop
    id: my_drukknop1
    on_press:
      - logger.log: "stop pressed"  
      - media_player.stop


#button:
  - platform: template
    name: volup
    id: my_drukknop8
    on_press:
      - logger.log: "+++++++"  
      - media_player.volume_up:  
  


#button:
  - platform: template
    name: voldown
    id: my_drukknop9
    on_press:
      - logger.log: "----"  
      - media_player.volume_down:   




#button:
  - platform: template
    name: mp3
    id: waakhond
    # Optional variables:
    icon: "mdi:dog"
    on_press:
      - logger.log: "waakhond wakker maken"  
      - media_player.stop
      - delay: 2.1s
      - rtttl.stop
      - delay: 1.1s

      #- media_player.volume_set: 0.9
      - media_player.play_media: 
          media_url:  'http://xxxxx/local/waakhond.mp3'
      #- media_player.volume_set: 0.9    



i2s_audio:
  i2s_lrclk_pin: GPIO15
  i2s_bclk_pin: GPIO4

media_player:
  - platform: i2s_audio
    name: Voice Assistant Speaker
    dac_type: external
    i2s_dout_pin: GPIO14
    mode: mono
    on_pause: 
      then:
        #- media_player.stop: 


text_sensor:
 
 

#text_sensor:
  - platform: wifi_info
    ip_address:
      name: "${device_name}_IP"
  

 


Time perhaps to move to ESP-IDF from arduino

Review your partition sizes when you do. A wipe and re-upload via USB may be required. A one-off, fortunately.

Um, time to catch up?

thats the reason of the topic ,

i dont have the yaml to catch up , to have my online radio working

the hardware is capable , when i use esphome 2025.10
i dont get my yaml updated whithout errors , so im stuck at esphome v2025.10

i tried 20 differant yamls , none of them worked yet ( aduino and idf )

this is a non working code that i tried

esphome:
  name: mac5060
  friendly_name: mac5060
  on_boot: 
    then:
      - rtttl.play: "two_short:d=4,o=5,b=100:16e6,16e6"

esp32:
  board: esp32dev
  framework:
    type: esp-idf

substitutions:
  device_name: mac5060     

logger:

# Voorkomt dat de netwerkstack alle RAM opslokt op ESP32 zonder PSRAM
network:
  enable_high_performance: false

http_request:
  useragent: esphome/device
  timeout: 10s  
  verify_ssl: false  

api:  
  encryption:
    key: "1A79q+SCGygjqY1PP8ITC6UlelCHr5ln8jjSmCQMMEk="

ota:
  - platform: esphome
    password: "d125ba4bc02c669bcc9fe1f4ee45876f"

wifi:
  reboot_timeout: 9min
  fast_connect: True  
  power_save_mode: none
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
  ap:
    ssid: "mac5060 Hotspot"
    password: "kipkipkip" 

globals:
  - id: total_pulses
    type: int
    restore_value: false
    initial_value: '0'

one_wire:
  - platform: gpio
    pin: 22

sensor:
  - platform: dallas_temp
    name: "Garage Temperature"  
    id: mac5060ds1820
    update_interval: 20s

output:
  - platform: ledc
    pin: GPIO27
    id: buzzer_output

rtttl:
  output: buzzer_output

switch:
  - platform: gpio
    pin: GPIO2
    name: "indicatorledblauw"
    id: indicatorledblauw
    icon: "mdi:led-outline"   
    inverted: False   

  - platform: output 
    name: 'buzzer'
    id: buzzer
    output: buzzer_output
    on_turn_on: 
      then:
        - rtttl.play: 'mission_imp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d'
    on_turn_off:
      then:
        - output.turn_off: buzzer_output

button:
  - platform: template
    name: buzzerpieppiep
    id: buzzerpieppiep
    icon: "mdi:emoticon-outline"
    on_press:
      - rtttl.play: 'locked:d=4,o=5,b=140:32d6,32p,32d6'
        
  - platform: template
    name: tuuttuut
    id: tuuttuut
    icon: "mdi:emoticon-outline"
    on_press:
      - rtttl.play: "two_short:d=4,o=5,b=100:16e6,16e6"

  - platform: restart
    name: ${device_name}_restart    

  - platform: template
    name: buzzerstarwars
    id: my_drukknop
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "Button buzzerstarwars pressed"  
      - rtttl.play: 'LastChri:d=4,o=5,b=112:16d6,e6,e6,8d6,a,8e6,8e6,8f#6,d.6,8b,8b,8e6,8e6,f#6,d.6,8b,8c#6,8d6,8c#6,2b,16e6,f#6,e.6,8b,8f#6,8g6,8f#6,2e6,8d6,8c#6,8d6,8c#6,c#6,8d6,8c#6,2a,16d6,e6,e6,8d6,8a,8e6,8e6,8f#6,d.6,8b,8b,8e6,8e6,f#6,d6,8b,8c#6,8d6,8c#6,b,16e6,f#6,e.6,8b,8f#6,8g6,8f#6,2e6,8d6,8c#6,8d6,8c#6,c#6,8d6,8c#6,a'

  - platform: template
    name: buzzerCarolBells
    id: buzzerCarolBells
    icon: "mdi:emoticon-outline"
    on_press:
      - rtttl.play: 'CarolBells:d=8,o=5,b=180:4a,g#,a,4f#,4a,g#,a,4f#,4f#6,f#6,f#6,e6,d6,4c#6,c#6,c#6,b,a,4b,b,b,c#6,b,4f#,f#,f#,4f#,c#,d#,e,f#,g#,a,b,c#6,4b,4a,c#,d#,e,f#,g#,a,b,c#6,4b,4a,4a,g#,a,4f#,4a,g#,a,4f#'

  - platform: template
    name: radio1
    id: radio1drukknop
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "radio 1 pressed"  
      - media_player.stop
      - delay: 0.1s
      - media_player.play_media: 'http://icecast.vrtcdn.be/radio1-mid.mp3'

  - platform: template
    name: radio2
    id: radio2drukknop
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "radio 2 pressed"  
      - media_player.stop
      - delay: 0.1s
      - media_player.play_media: 'http://icecast.vrtcdn.be/ra2wvl-mid.mp3'

  - platform: template
    name: stubru
    id: stubrudrukknop
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "stubru pressed"  
      - media_player.stop
      - media_player.volume_set: 0.4
      - delay: 0.1s
      - media_player.play_media: 'http://icecast.vrtcdn.be/stubru-mid.mp3'

  - platform: template
    name: joe8090
    id: joe8090drukknop
    icon: "mdi:emoticon-outline"
    on_press:
      - logger.log: "joe8090 pressed"  
      - media_player.stop
      - media_player.volume_set: 0.4
      - delay: 0.1s
      - media_player.play_media: 'https://streams.radio.dpgmedia.cloud/redirect/joe_80s_90s/mp3'  

  - platform: template
    name: stop
    id: my_drukknop1
    on_press:
      - logger.log: "stop pressed"  
      - media_player.stop

  - platform: template
    name: volup
    id: my_drukknop8
    on_press:
      - logger.log: "+++++++"  
      - media_player.volume_up:  

  - platform: template
    name: voldown
    id: my_drukknop9
    on_press:
      - logger.log: "----"  
      - media_player.volume_down:   

  - platform: template
    name: mp3
    id: waakhond
    icon: "mdi:dog"
    on_press:
      - logger.log: "waakhond wakker maken"  
      - media_player.stop
      - delay: 2.1s
      - rtttl.stop
      - delay: 1.1s
      - media_player.play_media: 
          media_url: 'http:/xxxxxt:8123/local/waakhond.mp3'

# 1. Base I2S Bus configuration
i2s_audio:
  i2s_lrclk_pin: GPIO15
  i2s_bclk_pin: GPIO4

# 2. Hardware Speaker & Virtual Mixer configuration
speaker:
  - platform: i2s_audio
    id: i2s_speaker
    dac_type: external
    i2s_dout_pin: GPIO14
    channel: mono
    sample_rate: 44100
    bits_per_sample: 16bit

  - platform: mixer
    id: mixer_speaker_id
    output_speaker: i2s_speaker
    source_speakers:
      - id: announcement_spk_mixer_input
      - id: media_spk_mixer_input

# 3. Speaker Media Player configuration
media_player:
  - platform: speaker
    name: "Voice Assistant Speaker"
    id: voice_assistant_speaker
    buffer_size: 20000
    announcement_pipeline:
      speaker: announcement_spk_mixer_input
      format: MP3
      sample_rate: 44100
      num_channels: 1
    media_pipeline:
      speaker: media_spk_mixer_input
      format: MP3
      sample_rate: 44100
      num_channels: 2

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "${device_name}_IP"

When you write “this is the non working code” the meaning is confused. Do you mean it compiles and uploads then the esp runs it and at some point it stops working with you seeing an error that says it has run out of RAM? Or something else?
If the former is the case then remove the rtttl code and dallas stuff and compile again.

Perhaps your varient of esp32 hasnt enough ram to run new version. Try esp32 with more RAM. You could always go back to 2025.10 esphome and compile on that.
I had to do that for bluetooth_proxy to 2026.1 for other reasons

Are you really sure?

It was capable with the older version of esphome you used. Perhaps it was just over the edge of capable/not capable. With the newer versions of firmware (and all the underlying libraries) it appears to have firmly crossed over into the land of not capable.

Based on your YAML, you have a standard esp32. It is clearly listed as marginal (at best) in the docs for i2s speaker.

You can fight it or you can stay on the old esphome (if it meets your needs) or you can get an esp32 with PSRAM that is more likely to meet your needs.

So what you get on esphome logs?

off course im sure
i use my internet radio esp32 yaml for more then 3years ( via esphome2025.10 )

the topic is : how make my yaml working into the recent esphome version

the audio plays but is kind a slowmotion , for 45seconds and then stops

[17:10:18.724][D][speaker_media_player.pipeline:118]: Reading MP3 file type
[17:10:18.728][D][ring_buffer:035][med_read]: Created ring buffer with size 20000
[17:10:18.843][D][speaker_media_player.pipeline:128]: Decoded audio has 2 channels, 44100 Hz sample rate, and 16 bits per sample
[17:10:18.843][D][ring_buffer:035]: Created ring buffer with size 17640
[17:10:18.851][D][speaker_mixer:369]: Starting
[17:10:18.876][D][i2s_audio.speaker:063]: Starting
[17:10:18.879][E][i2s_audio.speaker.std:401]: Parent bus is busy
[17:10:18.879][E][i2s_audio.speaker:115]: Driver failed to start; retrying in 1 second
[17:10:18.888][E][component:297]: i2s_audio.speaker set Error flag: unspecified
[17:10:18.898][D][ring_buffer:035][speaker_task]: Created ring buffer with size 44100
[17:10:19.453][S][media_player]: 'Voice Assistant Speaker' >> PLAYING
[17:10:19.453][S][media_player]:   Volume: 97%
[17:10:19.887][E][component:322]: i2s_audio.speaker cleared Error flag
[17:10:25.487][D][dallas.temp.sensor:053]: 'Garage Temperature': Got Temperature=26.812500°C
[17:10:25.591][S][sensor]: 'Garage Temperature' >> 26.8 °C

it appears (to me at least) the answer is very clear: you can’t because your esp is not capable enough to run newer versions of the underlying software.

Maybe somebody else knows of a way to do that.

strange that esphome bricks projects due to updating .
also strange that im the only person in the world that uses online radio via a esp32
and also strange , that is its not the philosophy of esphome and homeassitant to create electronic waste

Decoding audio files is CPU and memory intensive. PSRAM external memory is strongly recommended. To use the component on a memory constrained device, define only the announcement pipeline, decrease the buffer size, and set the pipeline transcode setting format to WAV with a low sample rate and only 1 channel.

Your approach is asking quite a lot from esp, maybe simply too much.
Try how it goes without mixer pipeline.
Also read the performance section of docs: