Einbinden eines ESP32 S3 als Audio Player in Music Assistant

Hallo zusammen,
eigentlich hatte ich den kühnen Plan, mit zwei ESP32 S3 und jeweils einem PCM5102A ein paar dumme Aktivboxen smart zu machen und sie in Music Assistant einzubinden. Dazu wollte ich - eigentlich - squeezelite ESP32 nutzen. Aber die offiziellen Version unterstützt den S3 (noch?) nicht und diese Versionen hier: ESP Audio Dock Squeezelite-ESP32 Installer
habe ich auch nicht sauber zum laufen bekommen. Kennt irgendjemand einen Weg, das umzusetzen oder hat es selbst schon einmal gemacht?

Gibt es nicht eine Testversion für den S3?

Ich habe so etwas mit einem Raspi Zero 2W mit einem AMP-HAT in alten Lautsprecherboxen gemacht. Als Software habe ich Volumio installiert.

Ich habe sie zumindest nicht gefunden. Was nicht ausschließt, dass ich einfach nur zu blöd war/bin. Hast du vielleicht einen Link?

Ja, das wäre die “einfache” Lösung. Darauf würde auch Snapcast problemlos laufen. Aber einerseits habe ich die S3 hier liegen und andererseits kosten die mal eben 25 EUR pro Stück, also zusammen 50 Piepen für eine kleine Bastelei. Aber mal sehen, vielleicht mach ich es irgendwann doch mal: das funktioniert wenigstens :wink:

Hi,

ich hatte mir aus den ESP32 S3 super mini´s eigene Voice Lautsprecher gebaut. Den grundsätlichen code und die Form der Schaltung hatte ich hier übernommen:

Hierbei ist interessant, dass sowohl der Voice-Assistant darauf läuft als auch diese Schaltung direkt im MusicAssistant als Wiedergabegerät gefunden wird (ggf. für Dich eine Idee).

Die Squeezelite Lösung hatte ich nur für die Wlan-BT Brücke eingesetzt - Dazu war aber ein ESP32 Wroover notwendig - kein reines S3.

Die ESP32 S3 (supermini) gibts eigentlich günsig be Aliexpress (im Choice):

als “großes” Modul mit R16N8:

oder als Supermini:

Grüße

Thomas

Die S3 habe ich ja schon hier. Aber genau das werde ich wohl auch machen: einen oder zwei Voice-Assistenten bauen, denn die squeezlite-Geschichte oder auch snapclient ESP32 (zumindest die, die ich gefunden habe), funktionieren zumindest im Moment auf dem S3 garnicht oder nur zum Teil, aber dann bescheiden. Aber vielleicht kommt da ja noch was.

@Retrogamer Hast du die Audioausgabe denn schon am Start? Ich habe einen ESP32-S3 und PCM 5102 und komme über stotterndes Audio nicht hinaus. Habe schon 3 KI´s verschlissen :wink: Ich wollte dann auch gerne via music assistant mit voice, welches auf einem 2. ESP32-S3 läuft lokale musik abspielen.

Nein, mir fehlen noch ein paar Teile (eigentlich die meisten: Mikrophone, Verstärker und Lautsprecher). Sobald das Zeug hier ist, werde ich langsam anfanfen.

Ok. also ich habe bereits voice am laufen “hey Jarvis” spielt soweit. dann wollte ich auf dem gleichen ESP auch die Audio Ausgabe implementieren. Das hat die KI völlig überfordert. Nun arbeite ich schon echt lange an unterbrechungsfreiem Audio über ESP-S3 und PCM 5102 und bin gespannt ob ich zu einem Ergebnis komme.

Postest du hier dein Fortkommen? Vielleicht hänge ich ja immer noch und bin dankbar über menschliche Erfahrungen.

Es gibt ein kleine Update: ich habe nach etwas Anpassung eine Squeezelite-Firmware von Sonocotta auf dem S3 zum Laufen bekommen. Ist zwar alles nicht ganz sauber: man kann z. B. nicht benutzte Dienste wie spotify oder AirPlay nicht abschalten. Auch BT nicht, obwohl es mit dem S3 derzeit überhaupt nicht funktioniert. Bzw. kann man es schon, aber dann geht das Teil in einen Bootloop und muss neu geflasht werden. Beim Booten wird das Vorhandensein abgefragt… Ein echter Designfehler in der Firmware. Aber da ich zu blöd bin, mir selbst eine zusammenzubauen, muss ich nehmen, was es gibt.

Ich habe jetzt testweise mal zwei S3 und einen normalen ESP32WROVER mit Squeezelite geflasht. Der alte ESP32WROVER läuft deutlich stabiler, ein echter Kaltstart (also Strom weg) ist bei den S3 immer ein Abenteuer: mal loggen sie sich sofort wieder ins WLAN ein, mal brauchen sie Anschub in Form von Drücken der Boot- und der Reset-Taste. Ist natürlich bescheiden, wenn sie irgendwo fest eingebaut werden… Mal sehen, vielleicht kommt da noch etwas stabileres. Das Multiroom klappt auch, allerdings braucht das System manchmal 5 - 10 Sekunden, bis es sich eingeschwungen hat und tasächlich 100 % synchron läuft. Teilweise kommt es nach ca. 30 Minuten kurz aus dem Tritt (wahrscheinlich muss in meinem Unifi noch etwas nachschauen), fängt sich dann aber meist wieder. Alles noch nicht wirklich 100 % zufriedenstellend. Ist aber eh ein Bastelprojekt…

Dann habe ich tatsächlich auch geschafft, die S3 in ESPHome mit Sendspin zu flashen. Wenn sie mal laufen, ist der Klang schon etwas besser, aber derzeit ist das Reboot-Problem dabei quasi unlösbar: teilweise muss ich eine neue IP vergeben, damit sie gefunden werden. Meist funktioniert es aber auch damit nicht. Es völlig random, ob man sie zum funktionieren bewegen kann. Also für den Praxis-Einsatz (noch) nicht geeignet.

Ich lass die S3 jetzt mal ein wenig mit Squeezelite laufen. Sie steuern jeweils einen kleinen MAX98357A, an dem alte Monitor-Boxen von mir hängen. Die MAX98357A habe ich mal in einem größeren Posten für 3,50 pro Stück gekauft. Dafür sind die Teile höchst erstaunlich. Ich letztens irgendwo gelesen, dass man zwei auch parallel schalten kann auf einen Lautsprecher, Vielleicht test ich das auch mal.

Ansonsten kommt als nächstes das Voice-Assistant Projekt…

Es gibt wieder ein Update, dieses Mal von der Sendspin Front. Ich habe im Moment zwei ESP32 S3 mit Sendspin in ESPHome. Als Klangererzeuger dient ein kleiner MAX98537A, der mit ca. 3 Watt zwar keinen Fisch vom Teller zieht, aber für eine angenehme Hörlautstärek an meinen kleinen Magnat-Monitor Lautsprechern reicht’s. Der Vorteil ist halt die sehr einfache Konfiguration, weil der alle I2S Komponenten an Board hat, man braucht keinen gesonderten DAC. Die aktuelle Version des ESPHome Builder Dev. funktioniert mit folgendem Code erstaunlich stabil bei mir:

substitutions:
  # Hardware-Pins
  i2s_lrclk: GPIO11
  i2s_bclk: GPIO09
  spk: GPIO07
  ledpin: GPIO48
  red: 100%
  green: 0%
  blue: 0% 
  reda: 0%
  greena: 100%
  bluea: 0% 
  rgb: GRB
  chip: WS2812  #WS2812 / APA106  
  
  # Audio-Settings
  volmin: "0.4"
  volmax: "0.85"
  bufsize: "512000"
  bufdur: 4000ms
  task: "true" # Wichtig für S3 PSRAM Stabilität

esphome:
  name: sendspin-2-test
  friendly_name: Sendspin 2 Test

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  framework:
    type: esp-idf
    sdkconfig_options:
      # Optimierungen für S3 Octal PSRAM & mDNS-Stabilität
      CONFIG_SPIRAM_FETCH_INSTRUCTIONS: "y"
      CONFIG_SPIRAM_RODATA: "y"
      CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
      CONFIG_LWIP_TCP_MSS: "1460"
      CONFIG_LWIP_TCP_MSL: "30000"
      CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y"

psram:
  mode: octal
  speed: 80MHz

logger:
  level: DEBUG

api:
  encryption:
    key: "xxx"

ota:
  - platform: esphome
    password: "xxx"

wifi:
  ssid: !secret wifi_ssid_4
  password: !secret wifi_password_4
  power_save_mode: NONE
  output_power: 20dBm
  ap:
    ssid: "Sendspin-2-Test"
    password: "xxx"

mdns:
  disabled: false

http_request:
  timeout: 10s

captive_portal:

# --- Externe Komponenten (Sendspin & Audio Stack) ---
external_components:
  - source: github://pr#12284
    components: [generic_image, mdns, sendspin]
    refresh: 0s
  - source: github://pr#13190
    components: [i2s_audio]
    refresh: 0s
  - source: github://pr#12429
    components: [media_source, http_request, speaker_source]
    refresh: 0s
  - source: github://pr#12258
    components: [ media_player ]
  - source: github://pr#12253
    components: [ mixer ]
  - source: github://pr#12254
    components: [ resampler ]

globals:
  - id: current_volume
    type: float
    initial_value: '0.2'
  - id: announcement_triggered
    type: bool
    initial_value: 'false'
# --- Audio Setup ---
i2s_audio:
  - id: i2s_bus
    i2s_lrclk_pin: ${i2s_lrclk}
    i2s_bclk_pin: ${i2s_bclk}

speaker:
  - platform: i2s_audio
    id: i2s_audio_speaker
    i2s_dout_pin: ${spk}
    dac_type: external
    channel: stereo
    bits_per_sample: 16bit
    sample_rate: 48000
    buffer_duration: ${bufdur}

  - platform: mixer
    id: mixing_speaker
    output_speaker: i2s_audio_speaker
    num_channels: 2
    task_stack_in_psram: ${task}
    source_speakers:
      - id: announcement_mixing_input
        timeout: never
      - id: media_mixing_input
        timeout: never

  - platform: resampler
    id: announcement_resampling_speaker
    output_speaker: announcement_mixing_input
    sample_rate: 48000
    bits_per_sample: 16
  - platform: resampler
    id: media_resampling_speaker
    output_speaker: media_mixing_input
    sample_rate: 48000
    bits_per_sample: 16

# --- Medien Quellen ---
media_source:
  - platform: sendspin
    id: sendspin_source
  - platform: http_request
    id: http_source
    buffer_size: ${bufsize}

# --- Media Player ---
media_player:
  - platform: sendspin
    id: player
    name: ALF Sendspin 1
  - platform: speaker_source
    id: external_media_player
    name: Player
    internal: False
    announcement_speaker: announcement_resampling_speaker
    media_speaker: media_resampling_speaker
    volume_increment: 0.05
    volume_min: ${volmin}
    volume_max: ${volmax}
    sources:
      - http_source
      - sendspin_source
    announcement_pipeline:
      format: FLAC
      num_channels: 1
      sample_rate: 48000
    media_pipeline:
      format: FLAC
      num_channels: 2
      sample_rate: 48000

    on_play:               
        then:
        - light.turn_on:
            brightness: 60%
            red: ${red}
            green: ${green}
            blue: ${blue}
            id: led
            effect: none

    on_idle:              
        then:
        - light.turn_off:
            id: led   

    on_announcement:
        then:
        - light.turn_on:
            brightness: 60%
            red: ${reda}
            green: ${greena}
            blue: ${bluea}
            id: led
            effect: fast pulse
        - mixer_speaker.apply_ducking:
            id: media_mixing_input
            decibel_reduction: 20
            duration: 0.0s


    on_state:
      if:
        condition:
          and:
            - lambda: return (!id(announcement_triggered));
            - not:
                media_player.is_announcing: external_media_player
        then:
          - mixer_speaker.apply_ducking:
              id: media_mixing_input
              decibel_reduction: 0
              duration: 1.0s      

sendspin:
  id: sendspin_hub
  task_stack_in_psram: ${task}

# --- Sonstiges ---
light:
  - platform: esp32_rmt_led_strip
    rgb_order: GRB
    pin: ${ledpin}
    num_leds: 4
    chipset: WS2812
    name: "Test LED"
    id: led
    disabled_by_default: false
    #entity_category: diagnostic
    icon: mdi:led-on
    default_transition_length: 0s
    effects:
      - pulse:
          name: "Slow Pulse"
          transition_length: 150ms
          update_interval: 150ms
          min_brightness: 20%
          max_brightness: 80%
      - pulse:
          name: "Fast Pulse"
          transition_length: 150ms
          update_interval: 150ms
          min_brightness: 20%
          max_brightness: 80%
switch:
  - platform: restart
    name: "Reboot Test-ESP"

sensor:
  - platform: wifi_signal
    name: WiFi
    update_interval: 60s 
    on_value:
      then:
        - lambda: |-

Es sind zwar immer noch external components enthalten, aber der “offizielle” Code ist halt noch nicht so weit. Die beiden Player lassen sich zu einer Stereo-Gruppe verbinden und die Synchronität ist deutlich besser als bei den ESP32WROVER Playern mit Squeezelite: ich teste jetzt seit drei Stunden und es kam zu keinem einzigen Drift. Das ist bei Squeezelite deutlich anders: da kommen die Player doch ab und zu aus dem Tritt. Also: wenn es jemand auch testen möchte, dann bitte gerne hier ein Feedback hinterlassen, würde mich freuen!

2 „Gefällt mir“

Läuft auch bei mir absolut perfekt! Danke für Deine Arbeit! :+1: Habe bei mir das ganze mit einem ESP32 S3 N16R8 und einem PCM5102A am laufen.

Das freut mich. Ich habe den Code noch mal ein wenig angepasst, läuft jetzt mMn noch etwas runder. Der Buffer war mit 4 Sekunden auch etwas zu hoch: das Umschalten auf eine andere Quelle dauert dann halt immer ca. 4 Sekunden, was für Mitbewohner dann doch immer etwas irritierend war.

Ich habe bei mir auch einen PCM5102A dran, an dem dann ein TPA3118 60W Mono hängt. Da habe ich allerdings das Problem, dass der Gain nicht “mal eben” am Verstärker runtergesetzt werden kann und die smd-Widerstände auf dem Board sind mir zu winzig, als dass ich daran etwas löten/austauschen könnte. Er rauscht halt leicht (hört man aber nur, wenn man direkt das Ohr dranhält) und ich habe jetzt zur Überbrückung bis eine andere Lösung da ist, in Music Assistant in den DSP-Einstellungen des Players die Verstärkung auf -10dba gestellt.

Hier ist mein aktueller Code für den ESP32 S3:

substitutions:
  # Hardware-Pins
  i2s_lrclk: GPIO11
  i2s_bclk: GPIO09
  spk: GPIO07
  ledpin: GPIO48
  red: 0%
  green: 0%
  blue: 100% 
  reda: 0%
  greena: 100%
  bluea: 0% 
  rgb: GRB
  chip: WS2812  #WS2812 / APA106  
  
  # Audio-Settings
  volmin: "0.1"
  volmax: "0.95"
  bufsize: "512000"
  bufdur: 1000ms
  task: "true" # Wichtig für S3 PSRAM Stabilität

esphome:
  name: sendspin-2-test
  friendly_name: Sendspin 2 Test

esp32:
  board: esp32-s3-devkitc-1
  cpu_frequency: 240MHz
  variant: esp32s3
  flash_size: 16MB
  framework:
    type: esp-idf
    sdkconfig_options:
      # Optimierungen für S3 Octal PSRAM & mDNS-Stabilität
      CONFIG_SPIRAM_FETCH_INSTRUCTIONS: "y"
      CONFIG_SPIRAM_RODATA: "y"
      CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
      CONFIG_LWIP_TCP_MSS: "1460"
      CONFIG_LWIP_TCP_MSL: "30000"
      CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y"

psram:
  mode: octal
  speed: 80MHz
  ignore_not_found: false

logger:
  level: DEBUG

network:
  enable_high_performance: true

api:
  encryption:
    key: "XXX"
  reboot_timeout: 0s
  
ota:
  - platform: esphome
    password: "XXX"

wifi:
  ssid: !secret wifi_ssid_4
  password: !secret wifi_password_4
  power_save_mode: NONE
  fast_connect: true
  output_power: 20dBm
  ap:
    ssid: "Sendspin-2-Test"
    password: "XXX"

mdns:
  disabled: false

http_request:
  timeout: 10s

captive_portal:

# --- Externe Komponenten (Sendspin & Audio Stack) ---
external_components:
  - source:
      # https://github.com/esphome/esphome/pull/12256
      type: git
      url: https://github.com/esphome/esphome
      ref: a2d98e1d5e020200db8f3caf27a74a939a661dc4
    components: [audio]
  - source:
      # https://github.com/esphome/esphome/pull/12258
      type: git
      url: https://github.com/esphome/esphome
      ref: b4b7c5b25ebe0f2ab988f700219fa3c57b2377b7
    components: [media_player]
  - source:
      # https://github.com/esphome/esphome/pull/12284
      type: git
      url: https://github.com/esphome/esphome
      ref: d48058e140c98f5c2d902661d851a6b712d62434
    components: [sendspin]
  - source:
      # https://github.com/esphome/esphome/pull/14013
      type: git
      url: https://github.com/esphome/esphome
      ref: 51dcce3d1f22865ebb458a5447bbc877ac946b5a
    components: [mdns]
  - source:
      # https://github.com/esphome/esphome/pull/12429
      type: git
      url: https://github.com/esphome/esphome
      ref: b49b09b6ae56502aa3ce51be86f90d732d019b2c
    refresh: 0s
    components: [file, http_request, media_source, speaker_source]
globals:
  - id: current_volume
    type: float
    initial_value: '0.2'
  - id: announcement_triggered
    type: bool
    initial_value: 'false'
# --- Audio Setup ---
i2s_audio:
  - id: i2s_bus
    i2s_lrclk_pin: ${i2s_lrclk}
    i2s_bclk_pin: ${i2s_bclk}

speaker:
  - platform: i2s_audio
    id: i2s_audio_speaker
    i2s_dout_pin: ${spk}
    dac_type: external
    channel: stereo
    bits_per_sample: 16bit
    sample_rate: 48000
    buffer_duration: ${bufdur}

  - platform: mixer
    id: mixing_speaker
    output_speaker: i2s_audio_speaker
    num_channels: 2
    task_stack_in_psram: ${task}
    source_speakers:
      - id: announcement_mixing_input
        timeout: never
      - id: media_mixing_input
        timeout: never

  - platform: resampler
    id: announcement_resampling_speaker
    output_speaker: announcement_mixing_input
    sample_rate: 48000
    bits_per_sample: 16
  - platform: resampler
    id: media_resampling_speaker
    output_speaker: media_mixing_input
    sample_rate: 48000
    bits_per_sample: 16

# --- Medien Quellen ---
media_source:
  - platform: sendspin
    id: sendspin_source
  - platform: http_request
    id: http_source
    buffer_size: ${bufsize}

# --- Media Player ---
media_player:
  - platform: sendspin
    id: player
    name: Sendspin 2
  - platform: speaker_source
    id: external_media_player
    name: Player
    internal: False
    announcement_speaker: announcement_resampling_speaker
    media_speaker: media_resampling_speaker
    volume_increment: 0.05
    volume_min: ${volmin}
    volume_max: ${volmax}
    sources:
      - http_source
      - sendspin_source
    announcement_pipeline:
      format: FLAC
      num_channels: 1
      sample_rate: 48000
    media_pipeline:
      format: FLAC
      num_channels: 2
      sample_rate: 48000

    on_play:               
        then:
        - light.turn_on:
            brightness: 60%
            red: ${red}
            green: ${green}
            blue: ${blue}
            id: led
            effect: none

    on_idle:              
        then:
        - light.turn_off:
            id: led   

    on_announcement:
        then:
        - light.turn_on:
            brightness: 60%
            red: ${reda}
            green: ${greena}
            blue: ${bluea}
            id: led
            effect: fast pulse
        - mixer_speaker.apply_ducking:
            id: media_mixing_input
            decibel_reduction: 20
            duration: 0.2s


    on_state:
      if:
        condition:
          and:
            - lambda: return (!id(announcement_triggered));
            - not:
                media_player.is_announcing: external_media_player
        then:
          - mixer_speaker.apply_ducking:
              id: media_mixing_input
              decibel_reduction: 0
              duration: 1.0s      

sendspin:
  id: sendspin_hub
  task_stack_in_psram: ${task}
  kalman_process_error: 0.01  

# --- Sonstiges ---
light:
  - platform: esp32_rmt_led_strip
    rgb_order: GRB
    pin: ${ledpin}
    num_leds: 4
    chipset: WS2812
    name: "Test LED"
    id: led
    disabled_by_default: false
    #entity_category: diagnostic
    icon: mdi:led-on
    default_transition_length: 0s
    effects:
      - pulse:
          name: "Slow Pulse"
          transition_length: 150ms
          update_interval: 150ms
          min_brightness: 20%
          max_brightness: 80%
      - pulse:
          name: "Fast Pulse"
          transition_length: 150ms
          update_interval: 150ms
          min_brightness: 20%
          max_brightness: 80%
switch:
  - platform: restart
    name: "Reboot Test-ESP"

sensor:
  - platform: wifi_signal
    name: WiFi
    update_interval: 60s 
    on_value:
      then:
        - lambda: |-

Hallo Zusammen, habe mich auch mal an das Projekt gewagt aber ein bisschen andere Komponenten.

Ich hatte einen Blackmore BB 860 welcher nur über Aux, BT und USB verfügte. Mit Claude hab ich dann die Pins auf der Platine ausgemacht welche wir nutzen können um den Lautsprecher auf WiFi umzurüsten.

Jetzt habe ich hier erfolgreich einen Esp32 N16R8 liegen mit einem PCM5102A üner I2S verbunden und mit deinem letzten Code bespielt.

Geklappt hat das alles, nur hat mein ESP recgelmäsig relativ starke Aussetzer und ich habe fast das Gefühl, dass sich das immer etwas hoch schaukelt und dann irgendwann garnix mehr ankommt.

Könnt ihr euch da nen reim drauf machen ?

WiFi ist mit -50dB eigentlich gut und auch stabil.

[14:39:30.947\]\[W\]\[sendspin.hub:572\]\[httpd\]: Failed to send audio chunk
[14:39:30.948\]\[W\]\[sendspin.hub:572\]\[httpd\]: Failed to send audio chunk
[14:39:31.791\]\[W\]\[sendspin.hub:572\]\[httpd\]: Failed to send audio chunk
[14:39:31.839\]\[W\]\[sendspin.hub:572\]\[httpd\]: Failed to send audio chunk

:crayon:by HarryP: Code-/Logzeilen formatiert (bitte immer in </> einbinden)
s.a.: (Neues Update & Features - Hier in der Community 🫶)

1 „Gefällt mir“

Hallo zusammen,

ich verzweifel seit mehreren Wochen bei dem Projekt.

Hardware ist ein ESP S3 WROOM -1 und ein PCM 5102.

Mit dem geposteten Code laufe ich immer wieder auf Fehlermeldungen. Mit Gemini habe ich einen Code zustande gebracht der den ESP zwar als Mediaplayer im Music Assistant erkennt aber ich erhalte kein Ton.

Was mache ich falsch?

Bei mir ruht das Projekt seit vielen Wochen, weil ich gerade andere Prioritäten habe. Der Code ist für den ESP32S3, dass der mit der WROOM Variante des normalen ESP32 nicht läuft, ist eigentlich klar. Ich hatte einen WROOM mal mit Sqeezelite ESP geflasht, das lief ganz gut und ließ sich auch als Player in Music Assistant einbinden. Ist aber auch schon länger her.

1 „Gefällt mir“