Skip to content

Releases: n-IA-hane/esphome-intercom

2026.8.2-dev pre-release: WE HAVE A F...ING ESPHOME VIDEOPHONE!

Choose a tag to compare

@n-IA-hane n-IA-hane released this 12 Aug 14:23

2026.8.2-dev pre-release: WE HAVE A F...ING ESPHOME VIDEOPHONE!

2026.8.2-dev remains an active pre-release and work in progress. The tag and
HACS archive may be refreshed while field qualification continues. Use
2026.8.0 when you need the current stable release.

🔧 What 2026.8.2-dev adds

The original P4 videophone milestone is all still here. Since that first
development candidate, the project has also received a deep consolidation of
the PBX, SIP and media lifecycles:

  • one generation-owned call session now governs direct, trunk, forwarded,
    grouped, conference, browser and Assist calls;
  • answer, bridge activation, losing-leg settlement, projection, rollback and
    termination now use shared authoritative primitives instead of parallel call
    paths;
  • public idle is published only after call-scoped tasks, media owners, relays,
    sockets and RTP reservations have crossed the cleanup barrier;
  • SIP interoperability now includes reliable provisional responses and PRACK,
    initial and in-dialog delayed offers, RFC 4028 session refresh, remote forks
    and late 2xx settlement, REFER/NOTIFY, stronger Digest authentication,
    RFC 3263 discovery, TLS and IPv6;
  • registered clients, trunks and local endpoints share the same atomic
    audio/video renegotiation mechanics, including audio-first video add, remove
    and re-add without sacrificing the established audio call;
  • forwarding, ring groups, conference calls, DTMF routing and browser phones
    retain one call owner and release failed or losing destinations without
    disturbing the remaining members;
  • the P4 JPEG and H.264 paths gained bounded presentation work, bidirectional
    cadence stabilization, post-call LVGL recovery and one-shot framebuffer
    capture for direct physical-panel verification;
  • the ESP voice assistant is now documented as an independent optional device
    capability, separate from a SIP call to Home Assistant Assist;
  • the local qualification toolkit now covers real Home Assistant, Chromium,
    SIPp, baresip, registered clients, trunks, S3/P4 hardware, firmware metadata
    and post-call quiescence without running jobs automatically on GitHub pushes.

This is still a development release. The stable baseline remains 2026.8.0.

🏠 Home Assistant and VoIP Stack

  • The Home Assistant audio and video media paths now share one lifecycle for
    authenticated ownership, replacement barriers, live-session resolution,
    bridge leases, cleanup and final state publication.
  • Physical ESPHome phones and Home Assistant softphones now use the same
    device_id source selector. The service dispatches each phone through its
    native adapter, and an ESP service response is no longer resolved again as
    a browser phone.
  • The new packages/voip/ha_phone.yaml package provides the complete physical
    phone surface in one include: discovery entities, native call-control
    actions and the Home Assistant managed phonebook.
  • SIP routing identity and presentation identity remain separate. Stable URI
    users route calls, while standard quoted display names preserve spaces from
    ESP friendly names, local accounts and external callers. RFC 4916 connected
    identity lets the caller learn the resolved callee after answer.
  • SIP-to-SIP bridges negotiate each leg independently. Compatible codecs stay
    on direct RTP, while the optional bounded FFmpeg fallback converts an
    incompatible active direction to H.264, VP8 or RTP/JPEG as required by the
    receiving endpoint.
  • An established audio call can add, remove and add video again through
    standard in-dialog re-INVITE without restarting its audio relay. RTP profile,
    direction, payload type and codec changes commit as one media generation.
  • Transcoded SIP audio is paced by its negotiated packet time, and immediate
    redial waits for the previous bounded transcoder to release its slot.
  • Negotiated RFC 4733 DTMF payload types and media direction are retained
    through direct, bridged and trunk call paths.
  • Browser ownership follows the logical phone, committed SIP transaction,
    active call and media direction. Dashboard reloads and multiple cards can
    hand media over without creating a second call owner.
  • Mixed browser and SIP ring groups let the first valid answer win, cancel the
    losing INVITEs and settle every remaining leg.
  • Inbound routing, forwarding, conference ringing, SIP bridge handling and
    browser media claims now use focused lifecycle owners while CallRegistry
    remains the observable compatibility index.
  • In-dialog video activation now follows the bridge relay that is actually active, not merely the presence of a dormant recvonly SDP media line. Re-INVITEs preserve the negotiated RTP audio codec and payload instead of accidentally changing PCMA, PCMU, G.722 or Opus into L16.
  • Completed dialogs retain a bounded SIP transaction tombstone. A delayed retransmission of the original INVITE now receives 481 Call/Transaction Does Not Exist and cannot reclaim a softphone after BYE.
  • Unexpected teardown failures are surfaced instead of being silently hidden,
    and completed calls release their sessions, sockets, bridges and RTP ports.
  • FRITZ!Box REGISTER now uses the bare registrar URI, keeps the account AOR in
    To and From, refreshes CSeq and Via branch after authentication, follows SIP
    Timer F and runs without blocking Home Assistant setup.
  • FRITZ!Box interoperability has been improved for authenticated registration
    and internal service dial strings such as **621. Thanks to
    @ruedigerhanses-stack for the careful hardware testing and iterative
    validation in issue #95.
  • RTP audio with valid packet boundaries different from negotiated ptime is
    accumulated and reframed by the shared PCM converter. This fixes the
    reported FRITZ!Box PCMA/16000 320-byte input without forcing a codec change.
  • ESPHome phonebook delivery now tracks exact content per device. Reconnects
    restore only the restarted phone, while duplicate callbacks and unchanged
    setup retries no longer republish the roster to every ESP.

🎬 Browser video worker and card

  • JPEG encoding and decoding, plus H.264 and VP8 WebCodecs decoding when the
    browser supports it, can run in a dedicated worker instead of blocking the
    card UI.

  • Worker generations prevent stale frames from a replaced call from reaching
    the screen. VideoFrame and ImageBitmap objects are closed on success,
    replacement and error paths.

  • The card editor and view builder are now focused modules without changing
    the public card configuration.

  • The card remains the GUI and media surface of a logical softphone. The
    softphone itself continues to exist and ring independently of an open card.

  • Browser calls verify secure context, Web Audio support and microphone access
    before signaling. A web view without getUserMedia no longer accepts a call
    and immediately tears it down with BYE.

  • Thanks to @csfrussa, browser microphone downsampling now applies a
    fourth-order Butterworth anti-alias filter before decimation. In Chromium
    validation it reduced a 12 kHz tone folding into 4 kHz by 23.4 dB while the
    wanted 1 kHz signal remained unchanged.

  • A Microphone anti-alias filter switch in the card's idle Options panel
    lets each browser and logical phone compare the filtered and legacy paths.
    It is enabled by default, applies from the next call and adds no filtering
    cost when the browser and negotiated transmit rates already match.

  • Browser softphones can now enumerate and remember the preferred microphone,
    speaker and camera for each browser and logical phone. If no preference has
    been selected, the existing browser defaults remain unchanged.

  • Media devices can be changed while a call is ringing or established. Camera
    replacement preserves the active SIP session and disposes the superseded
    capture track instead of creating a parallel sender lifecycle.

  • The card keeps one responsive Options surface in idle, audio calls and
    video calls. During video it becomes a compact settings icon inside the call
    bar, while the opaque options view replaces the card content for clear and
    accessible device selection.

  • The existing hangup control now reacts subtly to received audio level without
    overriding its responsive dimensions or adding a second audio capture path.

A live P4 camera call in the Home Assistant softphone card

🎥 WE HAVE A F...ING ESPHOME VIDEOPHONE!

Everything started when @Psix-anp shared a working ESP32-P4 camera build based
on the ESPHome camera work by @youkorr. What can I say, half a second later I
was already experimenting with bidirectional SIP video on ESPHome.

And we made it. A P4 can now be a real audio and video SIP endpoint, including
bidirectional video on its own display. Better still, the JPEG path is light
enough to live inside the full P4 profile alongside Micro Wake Word, Voice
Assistant, AFE echo cancellation, LVGL, TTS and Sendspin.

This opens the door to custom ESPHome videophones and doorbells with echo
cancellation, full P4 voice-assistant tablets, and direct room-to-room audio
and video calls between P4 devices.

Two P4 videophone use cases, a door call and a room-to-room call

The implementation stays close to the accelerated Espressif media paths:

  • esp_video 2.3.0 owns the MIPI-CSI and V4L2 camera pipeline. JPEG SIP TX
    borrows the camera's already encoded access unit, so it does not capture or
    encode the same frame a second time.
  • The JPEG camera follows Espressif's V4L2 startup practice and discards the
    first two CSI buffers after STREAMON. Cross-codec calls therefore begin
    with a color-stable JPEG and VP8 keyframe instead of publishing a transient
    ISP startup frame.
  • The H...
Read more

2026.8.1-dev pre-release: consolidated calls and the P4 videophone

Choose a tag to compare

@n-IA-hane n-IA-hane released this 25 Jul 18:56

2026.8.1-dev pre-release: consolidated calls and the P4 videophone

2026.8.1-dev remains an active pre-release and work in progress. The tag and
HACS archive may be refreshed while field qualification continues. Use
2026.8.0 when you need the current stable release.

🏠 Home Assistant and VoIP Stack

  • The Home Assistant audio and video media paths now share one lifecycle for
    authenticated ownership, replacement barriers, live-session resolution,
    bridge leases, cleanup and final state publication.
  • Physical ESPHome phones and Home Assistant softphones now use the same
    device_id source selector. The service dispatches each phone through its
    native adapter, and an ESP service response is no longer resolved again as
    a browser phone.
  • The new packages/voip/ha_phone.yaml package provides the complete physical
    phone surface in one include: discovery entities, native call-control
    actions and the Home Assistant managed phonebook.
  • SIP routing identity and presentation identity remain separate. Stable URI
    users route calls, while standard quoted display names preserve spaces from
    ESP friendly names, local accounts and external callers. RFC 4916 connected
    identity lets the caller learn the resolved callee after answer.
  • SIP-to-SIP bridges negotiate each leg independently. Compatible codecs stay
    on direct RTP, while the optional bounded FFmpeg fallback converts an
    incompatible active direction to H.264, VP8 or RTP/JPEG as required by the
    receiving endpoint.
  • An established audio call can add, remove and add video again through
    standard in-dialog re-INVITE without restarting its audio relay. RTP profile,
    direction, payload type and codec changes commit as one media generation.
  • Transcoded SIP audio is paced by its negotiated packet time, and immediate
    redial waits for the previous bounded transcoder to release its slot.
  • Negotiated RFC 4733 DTMF payload types and media direction are retained
    through direct, bridged and trunk call paths.
  • Browser ownership follows the logical phone, committed SIP transaction,
    active call and media direction. Dashboard reloads and multiple cards can
    hand media over without creating a second call owner.
  • Mixed browser and SIP ring groups let the first valid answer win, cancel the
    losing INVITEs and settle every remaining leg.
  • Inbound routing, forwarding, conference ringing, SIP bridge handling and
    browser media claims now use focused lifecycle owners while CallRegistry
    remains the observable compatibility index.
  • In-dialog video activation now follows the bridge relay that is actually active, not merely the presence of a dormant recvonly SDP media line. Re-INVITEs preserve the negotiated RTP audio codec and payload instead of accidentally changing PCMA, PCMU, G.722 or Opus into L16.
  • Completed dialogs retain a bounded SIP transaction tombstone. A delayed retransmission of the original INVITE now receives 481 Call/Transaction Does Not Exist and cannot reclaim a softphone after BYE.
  • Unexpected teardown failures are surfaced instead of being silently hidden,
    and completed calls release their sessions, sockets, bridges and RTP ports.
  • FRITZ!Box REGISTER now uses the bare registrar URI, keeps the account AOR in
    To and From, refreshes CSeq and Via branch after authentication, follows SIP
    Timer F and runs without blocking Home Assistant setup.
  • FRITZ!Box interoperability has been improved for authenticated registration
    and internal service dial strings such as **621. Thanks to
    @ruedigerhanses-stack for the careful hardware testing and iterative
    validation in issue #95.
  • RTP audio with valid packet boundaries different from negotiated ptime is
    accumulated and reframed by the shared PCM converter. This fixes the
    reported FRITZ!Box PCMA/16000 320-byte input without forcing a codec change.
  • ESPHome phonebook delivery now tracks exact content per device. Reconnects
    restore only the restarted phone, while duplicate callbacks and unchanged
    setup retries no longer republish the roster to every ESP.

🎬 Browser video worker and card

  • JPEG encoding and decoding, plus H.264 and VP8 WebCodecs decoding when the
    browser supports it, can run in a dedicated worker instead of blocking the
    card UI.
  • Worker generations prevent stale frames from a replaced call from reaching
    the screen. VideoFrame and ImageBitmap objects are closed on success,
    replacement and error paths.
  • The card editor and view builder are now focused modules without changing
    the public card configuration.
  • The card remains the GUI and media surface of a logical softphone. The
    softphone itself continues to exist and ring independently of an open card.
  • Browser calls verify secure context, Web Audio support and microphone access
    before signaling. A web view without getUserMedia no longer accepts a call
    and immediately tears it down with BYE.
  • Thanks to @csfrussa, browser microphone downsampling now applies a
    fourth-order Butterworth anti-alias filter before decimation. In Chromium
    validation it reduced a 12 kHz tone folding into 4 kHz by 23.4 dB while the
    wanted 1 kHz signal remained unchanged.
  • A Microphone anti-alias filter switch in the card's idle Options panel
    lets each browser and logical phone compare the filtered and legacy paths.
    It is enabled by default, applies from the next call and adds no filtering
    cost when the browser and negotiated transmit rates already match.

A live P4 camera call in the Home Assistant softphone card

🎥 WE HAVE A F...ING ESPHOME VIDEOPHONE!

Everything started when @Psix-anp shared a working ESP32-P4 camera build based
on the ESPHome camera work by @youkorr. What can I say, half a second later I
was already experimenting with bidirectional SIP video on ESPHome.

And we made it. A P4 can now be a real audio and video SIP endpoint, including
bidirectional video on its own display. Better still, the JPEG path is light
enough to live inside the full P4 profile alongside Micro Wake Word, Voice
Assistant, AFE echo cancellation, LVGL, TTS and Sendspin.

This opens the door to custom ESPHome videophones and doorbells with echo
cancellation, full P4 voice-assistant tablets, and direct room-to-room audio
and video calls between P4 devices.

Two P4 videophone use cases, a door call and a room-to-room call

The implementation stays close to the accelerated Espressif media paths:

  • esp_video 2.3.0 owns the MIPI-CSI and V4L2 camera pipeline. JPEG SIP TX
    borrows the camera's already encoded access unit, so it does not capture or
    encode the same frame a second time.
  • The JPEG camera follows Espressif's V4L2 startup practice and discards the
    first two CSI buffers after STREAMON. Cross-codec calls therefore begin
    with a color-stable JPEG and VP8 keyframe instead of publishing a transient
    ISP startup frame.
  • The H.264 profile uses esp_h264 1.3.6 for the ESP32-P4 hardware encoder and
    software decoder, with esp_image_effects 1.1.0 for its optimized I420
    conversion.
  • ESP-IDF PPA handles scaling, rotation and color conversion. Hardware JPEG
    decode and direct MIPI DSI presentation keep the P4 display path lean.
  • JPEG and H.264 are gated at compile time. A JPEG firmware does not include
    the H.264 media path, and the H.264 firmware does not include JPEG SIP video.

The P4 profiles are now:

  • the canonical full AFE JPEG videophone,
    waveshare-p4-touch-full-afe-landscape-videophone-jpeg.yaml;
  • the lightweight bidirectional RTP/JPEG videophone,
    waveshare-p4-touch-videophone-jpeg.yaml;
  • the experimental bidirectional H.264 videophone,
    waveshare-p4-touch-videophone-h264.yaml.

H.264 remains experimental in this pre-release. JPEG is the current full P4
baseline.

⌨️ Smaller ESPHome improvements

The compact Spotpear profile now has a dedicated touch keypad that keeps
contact navigation and direct extension dialing on the device.

The Spotpear touch keypad

Existing ESP audio profiles keep their native PCM transport and audio-stack
behavior. This update does not replace the audio backend or reduce configured
sample rates. P4 codec selection remains compile-time gated and its media tasks
remain event driven.

⚠️ Breaking change

The former P4 full landscape profile was promoted to the canonical full JPEG
videophone and renamed:

yamls/full-experience/single-bus/waveshare-p4-touch-full-afe-landscape.yaml

is now:

yamls/full-experience/single-bus/waveshare-p4-touch-full-afe-landscape-videophone-jpeg.yaml

Review the complete
breaking changes
before updating an existing installation.

✅ Qualification

  • 1351 Python tests plus 126 subtests passed.
  • Ruff passed for the custom component, ESPHome components, tests and tools.
  • Every shipped JavaScript file passed syntax validation.
  • The canonical full JPEG profile completed repeated real HA-to-P4 calls with
    bidirectional audio and video, zero reported RTP loss or media drops, clean
    BYE handling and quiescent call-scoped resource cleanup.
  • A Zoiper-style PCMA and VP8 call completed audio-to-video re-INVITE through
    the HA B2BUA and its JPEG fallback. The first returned VP8 frame was a valid,
    color-stable keyframe; all four audio/video RTP flows reported zero packet
    loss and both JPEG depacketizers reported zero dropped access units.
  • The dedicated JPEG and experimental H.264 P4 profiles have both completed
    real bidirectional audio and video calls on hardware.
  • Real voip_stack.call ser...
Read more

2026.8.0: Native HA Video Phones, Multi-Room Calling And PBX Routing

Choose a tag to compare

@n-IA-hane n-IA-hane released this 23 Jul 10:29

2026.8.0: Native HA Video Phones, Multi-Room Calling And PBX Routing

Important

Read the Breaking Changes
before upgrading. This
release deliberately removes development-only aliases and may require
reconfiguring VoIP Stack and updating existing automations.

2026.8.0 is the release where VoIP Stack stops looking like one clever
intercom and starts behaving like a small, Home Assistant-native communications
system. ESP devices, browser phones, wall tablets, standard SIP accounts,
Assist, ring groups, conference rooms and an optional provider trunk now share
one local roster and one standards-based SIP/SDP/RTP call model.

This note contains only the user-visible delta since stable 2026.7.1.

Video doorbell and private room-to-room calls through Home Assistant

🏠 One Home Assistant, Every Phone

Home Assistant can now host multiple logical browser phones. Keep the migrated
default phone, then add Kitchen, Reception, Office or any other room from
Settings > Devices & services > VoIP Stack > Add phone. Bind one
ha_softphone card and one real browser/tablet session to each Device.

  • Every HA phone has its own name, extension, DND, availability, groups, video
    capability and call state.
  • Browser phones and registered SIP accounts are native integration Devices
    with scoped state, connectivity, controls and call Event Entities.
  • ESP phones remain their existing ESPHome Devices. VoIP Stack discovers and
    routes them without creating duplicates.
  • Logical phones share the same SIP listeners and dynamic RTP pool; they do not
    reserve one server port set per room.
  • Two browser phones can call each other locally with independent audio and
    video. External legs remain normal SIP/SDP/RTP.
  • One endpoint owns one call. A second caller receives 486 Busy Here, while
    calls to other phones continue independently.
  • A logical phone may keep ringing while its kiosk browser is offline, allowing
    missed-call, timeout and fallback automations to remain meaningful.

Home Assistant as the local SIP and PBX hub

🎥 SIP Video Calling

SIP video is supported in web browsers, the Home Assistant Companion app,
standard SIP video door stations, SIP video phones and softphones, including
compatible routes through a PBX or trunk. ESPHome endpoints intentionally
remain audio-only.

  • Direct receive supports H.264, VP8 and RTP/JPEG without decoding or
    re-encoding video on the HA server.
  • Compatible H.264 and VP8 calls can send the browser camera when both the
    integration-wide permission and that phone's persistent Send Camera
    switch are on. Auto Answer and Send Camera are phone settings stored
    by the integration, so clearing browser cache does not reset them; microphone
    and camera permission remains local to the browser that owns the call media.
  • Optional bounded FFmpeg receive converts H.263, H.263-1998 or H.265 to VP8.
    It is receive-only, single-slot and never records an intermediate file.
  • Incoming and outgoing calls support sendrecv, sendonly, recvonly and
    inactive directions.
  • Direct calls and video-capable trunk/PBX routes use the same media contract.
    Authenticated retries preserve the complete audio/video offer.
  • A direct HA-browser dialog can accept compatible peer-initiated video
    add/remove, hold/resume and RTP endpoint changes through re-INVITE or UPDATE.
  • RTP/AVP remains the compatible default. Negotiated AVPF adds compound RTCP
    reports and bounded PLI/FIR key-frame recovery.
  • Camera denial, decoder failure, unsupported video or optional transcoder
    failure does not tear down compatible audio.
  • The card keeps video inside its configured Lovelace geometry, preserves the
    native aspect ratio and moves identity, duration and Hang Up into a compact
    translucent bottom bar.
  • Detailed media counters appear only with backend debug and Extended
    information
    enabled.

Live SIP video in the Home Assistant softphone card

Video remains opt-in and requires HTTPS, a compatible browser and an RTP path
permitted by the local firewall. Read
SIP Video
for codec, network and privacy requirements.

🧭 Initial Preview: Automation-Native PBX Routing

Home Assistant automations can now influence an inbound call at explicit
decision points instead of replacing the normal dial plan.

Warning

This is a preliminary, disabled-by-default API. Event fields, decision
timing and service semantics may change in a future release while more real
PBX installations shape the final contract. The central phonebook, explicit
extensions and configured fallback destination remain the stable default.

  • Direct inbound mode can expose a short route_requested decision before the
    configured target.
  • DTMF mode gives explicit extension digits priority and exposes automation
    routing only when no digits were entered.
  • ingress and origin distinguish provider/PBX trunk calls from local
    extension calls without relying on internal ownership fields.
  • voip_stack.select_inbound_destination selects the initial target.
  • voip_stack.forward moves an already ringing or connected HA-owned call to
    another phone, ESP, registered endpoint, group or Assist pipeline.
  • Forward failures can resume, terminate or return busy; a replaced ringing
    SIP leg receives a real CANCEL.
  • Per-phone state Sensor and call Event Entities support native HA triggers
    such as ringing for 30 seconds, without helper timers or Call-ID templates
    for the ordinary single-call case.
  • Once Assist owns the call, compatible in-dialog audio updates remain live;
    video re-offers are answered explicitly with m=video 0 because the Assist
    endpoint is audio-only, rather than interrupting TTS or stranding the dialog.
  • Revision and sequence guards remain available for concurrent or multi-stage
    routing policies.

Assist answers an unattended delivery call

Yes: an unanswered door station can now be forwarded to Assist. What Assist
says is controlled by your pipeline prompt. Good judgement is still not
included.

Copyable native-UI automation examples are in
Automation Dial Plan.

👥 Ring Groups And Conference Groups

Groups now re-enter the same canonical PBX dispatcher as every other target.
They are no longer special routing shortcuts with subtly different media or
ownership rules.

  • A ring group calls all eligible members in parallel.
  • The first answer wins; losing early dialogs receive CANCEL and a confirmed
    losing dialog receives BYE.
  • The originating endpoint is excluded when it is also a group member.
  • DND, disabled endpoints, busy state and endpoint capability are applied
    before fan-out.
  • Browser phones, ESP endpoints and registered SIP accounts can share one
    group without forcing audio-only members to negotiate video.
  • A conference group is a real HA-hosted focus: members join the same mixed
    room, optional invitees ring, and the room closes when the last participant
    leaves.

Ring group first-answer-wins and conference group behavior

☎️ A More Predictable SIP/PBX Core

Most of this release is invisible when it works, which is precisely the point.
The former monolithic runtime has been decomposed around explicit call,
transaction, dialog, route and media ownership primitives.

  • A logical call owns its generation, legs, tasks, media reservations and one
    cancellation-safe cleanup barrier.
  • SIP dialogs follow Call-ID and tags, not the lifetime or source port of one
    TCP connection. Established trunk calls survive a replacement flow.
  • Inbound answer is transactional: prepare resources, send the final response,
    commit media or roll everything back.
  • Audio and video media updates commit atomically against the current call
    generation. A late re-INVITE cannot leave the two directions on different
    revisions.
  • State transitions are monotonic. Late provisional responses or stale browser
    callbacks cannot resurrect a terminated card.
  • Hang Up remains available through calling, connecting and remote ringing.
    SIP CANCEL, 487 Request Terminated, ACK and crossed-200 BYE handling now
    share one lifecycle.
  • Remote Contact and Record-Route state are retained for correct in-dialog ACK,
    BYE, INFO, UPDATE and re-INVITE routing through proxies.
  • Cleanup is idempotent and releases dialogs, tasks, media owners, relays, RTP
    reservations and optional transcoder slots before the endpoint returns idle.

🔢 DTMF, Registered Phones And Trunks

  • Initial trunk extension selection supports negotiated RFC 4733
    telephone-event and compatible SIP INFO digits.
  • Established HA-owned bridges publish one experimental voip_stack.dtmf
    occurrence per RFC 4733 or SIP INFO key for door/gate automations.
  • Direct ESP-to-ESP m...
Read more

2026.7.1: Assist By Phone, Groups And A Stronger VoIP Stack

Choose a tag to compare

@n-IA-hane n-IA-hane released this 12 Jul 01:34

2026.7.1: Assist By Phone, Groups And A Stronger VoIP Stack

2026.7.1 contains the changes made after stable 2026.7.0. It expands
the Home Assistant phone system with real ring groups and conference rooms,
makes the Lovelace card more useful for both HA and ESP phones, and hardens the
call and audio paths for everyday use.

🏠 VoIP Stack / Home Assistant

  • ☎️ The existing HA softphone can now publish its own extension, ring-group
    membership, conference-group membership and conference-ringing preference.
  • 🔄 Changes made from the card or services are reflected through HA's virtual
    endpoint and republished to the shared phonebook.
  • 💾 HA softphone extension, DND and group settings are persisted in the
    integration config entry. The card writes through the softphone service and
    reads the canonical snapshot back; the values survive integration reloads
    and full Home Assistant restarts.
  • 🧑‍💼 Registered SIP phones are first-class endpoints. Their accounts can use
    extensions and join the same ring or conference groups as HA and ESP devices.
  • 🌍 Incoming calls are not limited to callers stored in the phonebook.
    Reachable and protocol-compatible SIP callers can ring HA or an ESP, subject
    to normal destination, busy and DND checks.
  • 🧭 Extensions, group contacts, registered phones, ESP endpoints and optional
    trunk routes all resolve through the same dial plan.
  • 🧹 Endpoint departure, reboot and roster-service timing are handled
    automatically, so stale contacts and missed phonebook pushes are less likely.

🗣️ Call Home Assistant Assist By Phone

Enable Include voice assistant, choose HA's preferred Assist pipeline or a
specific one, and assign an extension. The selected assistant appears in the
same phonebook used by every other destination; no extension is assumed or
reserved automatically.

Voice assistant extension and Assist pipeline configuration

The optional second setup step keeps the SIP extension explicit and supports
both HA's preferred Assist pipeline and a specifically selected pipeline.

  • 📞 ESP phones, locally registered SIP clients, direct compatible SIP callers
    and external callers arriving through a trunk can call the assistant.
  • 👋 The assistant receives the SIP caller identity as its first turn and can
    greet first. A matching phonebook name is used when available; otherwise the
    original caller string or number is preserved.
  • 🔁 After speaking, it listens for the caller, runs STT and the conversation
    agent, streams the TTS reply back into the same call, and repeats until the
    caller hangs up. Conversation context is retained between turns.
  • 🧩 VoIP Stack runs the selected native HA pipeline, so its existing STT,
    conversation agent, TTS, language and voice settings remain authoritative.
    Piper, Wyoming, cloud providers and local HA agents use the same route without
    provider-specific code.
  • 🏠 No separate Home Assistant VoIP integration, second SIP port or generated
    Assist satellite is required.

🎛️ Lovelace Card

  • 🪞 ESP mirror cards keep their original meaning: each card represents one ESP
    phone and uses that ESP's own call controls and synchronized phonebook.
  • ⌨️ ESP mirror cards now include a keypad for a manual phonebook name, SIP URI,
    extension or number without overwriting the contact selected on the device.
  • ⚙️ The Options view exposes Auto Answer, DND, extension, ring groups,
    conference groups and conference ringing when the selected endpoint supports
    them.
  • 📐 Option labels share one left edge; fields, selectors and checkboxes share a
    clean right-hand control column.
  • 🏠 HA softphone cards expose the same HA-owned extension and group settings
    without creating a second routing or call-state engine in the browser.
  • 📒 The main card now has a phonebook mode backed by the canonical HA roster.
    It sorts contacts alphabetically, uses the available Sections grid area and
    scrolls only when the roster is longer than that area.
  • ↔️ ESP mirror, HA softphone and phonebook modes support native Home Assistant
    Sections resizing. Their controls respond to both card width and height, and
    an omitted name or title leaves no empty header row.
  • 🔔 Ringtone, DND and terminal call state no longer race normal card refresh or
    cleanup paths.
  • 🔌 ESP mirror availability follows the bound Home Assistant entity live. A
    card becomes unavailable when its ESP leaves and recovers when it returns,
    without a dashboard refresh or polling timer.
  • 🖱️ Internal card scrolling hands the remaining wheel/trackpad movement back
    to the dashboard at the card boundary.
  • 🎨 Native contact selectors remain readable on both light and dark themes,
    including the operating-system popup rows.
  • 🔒 Caller and destination labels are inserted as text, so SIP display strings
    cannot become card markup.

ESP mirror card with keypad and endpoint options

ESP mirror card with keypad, Auto Answer, DND, extension and group controls
expanded.

🔔 Ring Groups

Call a group such as RG Home and every available member rings together.
Home Assistant, ESP phones, registered SIP endpoints and manual contacts can all
participate.

The first member to answer wins. Other early legs are cancelled, and a late
answer cannot steal or duplicate the established call. Group contacts are
created from live membership and disappear when no endpoint declares them. The
card keeps the group name while dialing/ringing, then shows the actual endpoint
that answered, including the Home Assistant softphone.

🎙️ Conference Groups

Home Assistant can now host SIP conference rooms. Calling a contact such as
CG Home joins that room; members with conference ringing enabled can also be
invited when the room starts.

The conference focus mixes the active participants, applies additional headroom
as the room grows and cleans up invited legs and media ports when the owner or
last participant leaves.

📒 Phonebook And Dial Plan

  • Group fields accept comma-separated membership, so one phone can belong to
    more than one room or ring group.
  • The roster advertises directional media capabilities and the fields needed by
    HA, ESP and registered endpoints.
  • Numeric inbound routing uses the same phonebook extensions instead of a
    separate static route table.
  • HA refreshes the roster when an ESP's phonebook service appears after reboot,
    closing the window where discovery could finish before the service was ready.
  • SIP authentication retries rebuild the transaction correctly for stricter
    PBX and FRITZ!Box implementations.

📞 More Predictable Calls

  • SIP transactions now match the correct Call-ID, CSeq, branch, dialog tags and
    peer before changing a call.
  • Retransmissions, decline, cancel, busy, answer, hangup and immediate redial
    have deterministic ownership and cleanup.
  • The Hang Up action remains available while an outbound call is still in
    calling, including unreachable or slow external destinations.
  • A cancel that crosses a successful answer is completed with the proper
    acknowledgement and teardown instead of leaving a ghost call.
  • Reused SIP/TCP connections serialize outgoing messages and keep pending work
    bounded.
  • Unsupported hold or codec-changing re-INVITE requests receive 488 Not Acceptable Here without destroying the call already in progress.
  • Incoming digit routing accepts both standard RTP telephone-event and the
    widely deployed legacy SIP INFO DTMF representation, including four-digit
    trunk destinations entered at human speed.
  • During an established HA-bridged call, each RFC 4733 or compatible SIP INFO
    DTMF key is also exposed as voip_stack.dtmf for automations. This event
    path is separate from pre-answer extension routing and never transfers the
    call by itself.
  • Ring-group legs, conference members, RTP ports, registrations and transaction
    caches all have explicit limits instead of growing without bound.

🧪 Experimental: Use Phone Keys In Home Assistant Automations

Caution

In-call DTMF automation events are experimental in 2026.7.1. Validate the
caller/source filters and the target action in a safe environment before
using phone keys for gates, locks or other security-sensitive controls.

During a call bridged by Home Assistant, every DTMF key now fires one
voip_stack.dtmf event. This makes practical actions such as press 1 to open
the gate
possible while the conversation and audio continue normally.

triggers:
  - trigger: event
    event_type: voip_stack.dtmf
    event_data:
      source: Cordless
      digit: "1"
actions:
  - action: cover.open_cover
    target:
      entity_id: cover.gate

Events include caller, callee, source leg, digit, both call IDs and transport,
so automations can be restricted to the intended phone and active call. This is
not a second dial plan: initial extension collection remains separate and an
in-call key never transfers a call by itself. Detection is entirely HA-side;
no parser or additional real-time work is added to ESP firmware.

🔊 Audio And ESP Real-Time Performance

  • Browser audio has one owner per call and uses stateful codecs, absolute pacing
    and bounded queues. A short FIFO jitter buffer smooths Chrome microphone
    bursts instead of discarding adjacent speech frames.
  • PCMA 8 kHz, L16 48 kHz and Opus 48 kHz paths are used where the endpoints on
    that leg support them.
  • PCMA/G.711 handset audio now preserves the source speech level...
Read more

2026.7.0

Choose a tag to compare

@n-IA-hane n-IA-hane released this 04 Jul 15:49

2026.7.0: ESPHome devices are VoIP phones now

This release contains the largest call-control change
in the project so far: ESP devices and Home Assistant have been migrated from
the old project call model to SIP/SDP/RTP VoIP.

Use it when you are ready to move to the SIP/VoIP stack. If a device is
installed somewhere where temporary audio glitches or call-routing regressions
would be a problem, test the matching YAML on spare hardware first.

This release changes the project category

Yes, you read that correctly. ESP devices are now SIP phones and Home Assistant
is now a SIP softphone, router/B2BUA, RTP bridge/resampler and optional trunk
client. VoIP Stack has been migrated with them, so Home Assistant is not a
sidecar around an intercom protocol anymore: it participates in real VoIP call
flows.

This does not remove the simple door intercom use case. An ESP can still be a
one-button door intercom or room intercom with the same user workflow: call, answer,
talk, hang up. It is now a real SIP/VoIP phone underneath, so the same device
can also join direct SIP calls, HA-routed calls, registered softphone calls and
trunk calls when those paths are configured.

That means this release can do things that previously required an external PBX
such as Asterisk:

  • ESP devices can call each other with SIP identities from the shared
    phonebook.
  • ESP devices can call Home Assistant as an independent softphone.
  • Home Assistant can call ESP devices from the Lovelace softphone card,
    automations, Assist intents or services.
  • Home Assistant can bridge calls between ESPs, registered softphones and trunk
    legs while preserving SIP call state and terminal reasons.
  • A standard softphone such as Zoiper, Linphone, baresip or pjsua can register
    to Home Assistant as a local SIP account and become a phonebook contact.
  • Home Assistant can register one optional provider/PBX trunk. External numbers
    and provider inbound calls can be routed through VoIP Stack.
  • With a trunk configured, ESPs and Home Assistant can place and receive
    external calls without carrying Asterisk beside the integration.
  • Audio quality is negotiated per direction. A device can receive the best
    compatible speaker format available on that leg while transmitting whatever
    its microphone path can actually produce, for example 48 kHz receive audio
    with a 16 kHz AFE/AEC microphone return.
  • SIP status, DND, busy, decline, cancel, BYE, incompatible media and routing
    failures are propagated as call reasons instead of being hidden behind a
    project-specific state machine.

This is intentionally a breaking migration. ESP firmware does not REGISTER to a
provider/PBX and does not require SIP auth. ESPs are local SIP user agents; HA
is the central router/B2BUA and optional trunk endpoint. The old proprietary
VoIP call-control path is not a compatibility layer.

🏠 VoIP Stack / Home Assistant

Home Assistant is now a real SIP softphone, not only a controller for ESP
devices. It can place and receive calls for itself, place calls on behalf of ESP
endpoints, ring from ESP calls, ring from standard SIP clients such as Zoiper,
Linphone or bareSIP, and ring from a public phone number when an optional SIP
trunk is registered. The card shows those incoming calls, answers or declines
them, and can open a keypad/manual target view for a phonebook name, SIP URI,
extension or number.

Home Assistant VoIP softphone card

VoIP Stack keypad

  • 🗣️ VoIP Stack now is able to call other VoIP contacts via Voice
    Assistant.
    An optional Assist intent adapter can be enabled from the
    VoIP Stack setup/reconfigure dialog. With the provided custom sentences,
    voice satellites can call a phonebook contact, hang up, answer or decline
    using the satellite that heard the sentence. Spoken contact names are resolved
    dynamically against the live phonebook, so call kitchen speaker can resolve
    to the canonical Kitchen Speaker contact without changing low-level
    VoIP contact matching. If no phonebook contact matches, the adapter can also call
    the single VoIP device assigned to a matching Home Assistant area name.
    Multiple VoIP devices per area are intentionally not voice-dialed in this
    release; group/area calls are left for a later release.
  • 🧬 Added negotiated PCM audio formats to the HA SIP softphone/bridge stack.
  • 🔁 Audio formats are now per direction, not one global device format:
    tx_format describes device-to-wire audio and rx_format describes
    wire-to-device audio.
  • 🎚️ HA can bridge endpoints with different TX/RX formats by converting the
    audio explicitly instead of pretending every call is 16 kHz/s16/mono.
  • 🧮 HA bridge conversion is vectorized through NumPy and uses anti-aliased
    sample-rate conversion for downsampling.
  • 🧩 SIP/SDP offer-answer now carries explicit PCM audio capabilities.
  • 🧭 HA now validates endpoint-declared formats before routing calls. Incompatible
    peers fail with a readable incompatible_audio_format reason instead of
    producing distorted audio.
  • 📡 SIP/TCP and SIP/UDP endpoints understand the negotiated format selected
    for each call leg.
  • 🌉 HA SIP bridge legs preserve the original call identity when routing toward
    the destination, so caller/destination labels stay stable across TCP ↔ UDP
    and mixed-format bridges.
  • 🚪 Inbound SIP INVITE messages do not require the caller to exist in the
    callee phonebook. The phonebook is the outbound dial plan; inbound
    caller/destination identity comes from SIP headers. This keeps VPN/routed
    callers and HA bridges working without pre-seeding every callee phonebook.
  • ☎️ VoIP Stack can optionally register one SIP trunk account. When
    disabled, trunk code is inactive. When enabled, unresolved outbound numbers
    can route through the trunk and inbound provider calls can select HA or a
    local phonebook target with RFC2833/telephone-event DTMF.
  • 🧭 VoIP Stack now exposes Home Assistant's native Reconfigure flow. You
    can change ports, debug mode, Assist intents, local SIP registrar support and
    the optional trunk without deleting and recreating the integration.
  • 📴 The trunk setup is truly optional. A fresh setup starts with trunk disabled,
    and an empty trunk page is treated as "no trunk" instead of failing validation.
  • 🔌 HA local SIP transport toggles were removed from setup. The user configures
    ports and optional features; only provider/PBX trunk transport remains
    configurable.
  • 🛡️ Browser audio WebSocket sessions remain server-authoritative: if the socket
    is truly gone, the server ends the call.
  • 🔄 Browser/card reload during an active HA softphone call can explicitly rebind
    to the existing server session within a short grace window, avoiding the old
    "dashboard refresh killed or desynced the softphone call" behavior.
  • 📞 ESP -> HA browser-answer calls now initialize the browser audio pipeline
    only after the HA SIP answer/control reply carries the negotiated TX/RX formats.
    This keeps the ESP-caller / HA-responder path aligned with HA-originated
    calls and avoids deep/slow audio caused by a browser worklet using stale
    16 kHz framing against a negotiated 48 kHz leg.
  • 🧭 ESP caller devices now also apply the selected RX speaker format before
    activation and again when the SIP answer arrives. ESP-originated calls answered
    by HA therefore use the negotiated speaker rate instead of a stale/default
    playback format.
  • 🚫 Duplicate terminal/bridge events were tightened so cards should see one
    final reason instead of compensating for repeated disconnected events.
  • 🧪 SIP negotiated-format testing now expects a standard external softphone or
    private local debug helper, rather than a distributed project softphone.

🎛️ Lovelace Card

  • 🧠 The card keeps the page-level audio engine model from the previous dev
    cycle: one browser audio engine per page, cards as views.

  • 🔌 Audio still uses the dedicated binary WebSocket, not the shared HA frontend
    WebSocket.

  • 📦 The card receives the negotiated effective formats and configures capture
    and playback from that contract.

  • 🎧 Capture and playback worklets support dynamic PCM settings instead of
    assuming 16 kHz Int16Array everywhere.

  • 🧯 Browser playback now uses an adaptive jitter buffer with lightweight packet
    loss concealment instead of fixed startup/drop thresholds. Remote HA app and
    browser sessions tolerate normal websocket/RTP jitter without periodic
    audio-gap artifacts.

  • 🔄 Softphone calls survive normal Lovelace reload/reconnect flows when the
    browser rebinds inside the server grace window.

  • 🧭 Device identity remains device_id based in the frontend. Legacy
    name/esphome-id matching is resolved server-side, once.

  • 🔔 HA softphone has an idle-only Options panel for Auto Answer, DND and
    browser ringtone. Ringtone is a per-browser preference; HA softphone DND is
    stored in HA state.

  • ⌨️ HA softphone also has a keypad/manual target view for calling a phonebook
    name, extension, SIP URI or external number directly from the card.

  • 🪞 Hybrid cards keep the original mirror semantics: the card represents the
    selected ESP, mirrors ESP ringing/in_call state, and becomes the HA
    softphone leg only when that ESP is calling Home Assistant. A separate
    ha_softphone card represents HA itself and shows Answer/Decline only for
    calls addressed to HA.

  • 🧹 Ringing/In-call screens hide runtime options, so only the call actions
    relevant to the current state are visible.

  • 🧾 Terminal text uses the active call peer. A card or display no longer reports
    the currently selected phonebook contact as the call...

Read more

2026.6.2: HA softphone and audio runtime stabilization

Choose a tag to compare

@n-IA-hane n-IA-hane released this 07 Jun 15:37

2026.6.2: HA softphone, runtime audio stability and full UI state cleanup

🏠 Intercom Native / Home Assistant

  • 🧩 Home Assistant can now be represented as its own PBX-lite softphone endpoint.
  • 📞 Home Assistant can receive valid PBX-lite calls addressed to HA itself, not only bridge calls toward ESP devices.
  • 🚫 Added independent HA softphone Do Not Disturb state.
  • ✅ Added independent HA softphone Auto Answer state.
  • 🔁 Improved HA softphone session tracking for inbound, outbound and terminal call events.
  • 🧭 Preserved intercom runtime state across HA reconnects more reliably.
  • 🌐 Improved endpoint republish/reconnect behavior so ESP endpoints and HA routing state recover more cleanly after API/Wi-Fi churn.
  • 🧪 Expanded tools/intercom_softphone_probe.py for diagnostic calls, synthetic caller testing, tone/WAV injection and received-audio WAV capture.
  • 📡 External PBX-lite callers can call HA directly when they send valid protocol messages.

🎛️ Lovelace Card

  • 🏠 Added the new Home Assistant softphone card mode requested in #46.
  • 🔀 The existing Hybrid card mode remains the default and keeps the previous behavior: the card is attached to one ESP endpoint and mirrors/controls that ESP.
  • 📞 In Hybrid mode, if the selected destination is Home Assistant, the browser/card acts as the Home Assistant audio leg and starts a call toward the attached ESP. The ESP will ring, or answer automatically if its Auto Answer is enabled.
  • 🏠 In Home Assistant softphone mode, the card represents Home Assistant as an independent intercom endpoint instead of mirroring an ESP.
  • 📲 The HA softphone card can call discovered ESP endpoints from its selector.
  • 🔔 The HA softphone card rings only for calls addressed to Home Assistant itself, useful for clean dashboards where HA behaves like one standalone desk phone.
  • 🚫 HA softphone mode has its own Do Not Disturb control.
  • ✅ HA softphone mode has its own Auto Answer control.
  • 🎯 HA softphone mode does not use device_id; Hybrid mode still requires an ESP device_id.
  • 🎨 Card controls, selectors and buttons were polished to match the Home Assistant card surface better.

Home Assistant softphone card

🔊 ESP Audio Runtime

  • 🧱 AFE output now uses frame-atomic buffering, so consumers receive complete processed frames or silence, not short partial reads.
  • 🧠 AFE reconfigure/fetch paths were hardened for cleaner runtime mode switching and shutdown/restart behavior.
  • 🧩 Dual-mic AFE was realigned with the Espressif GMF element output path.
  • 🧼 Ring buffer helpers now expose explicit type/placement logging and NOSPLIT frame-safe behavior where needed.
  • 🔊 Added the project-local speaker media-player fork with pause_releases_pipeline.
  • ⏸️ Paused media now releases the playback pipeline before TTS, timer alarms or intercom audio need the same speaker graph.
  • 📦 esp_audio_stack gained cleaner generated-code gating for TDM paths and codec backend setup.
  • 📡 Intercom TX/audio paths were tightened for cleaner buffering and transport lifecycle behavior.

⏲️ Timers and Full UI State

  • ⏲️ Added optional Voice Assistant timer package.
  • 🖥️ Timer-finished UI now owns the display while the alarm sound plays.
  • 🧭 Full display YAMLs now use a centralized reducer-style UI priority model instead of duplicating screen priority logic per callback.
  • 🧼 Media playback, timer alarms, Voice Assistant states and intercom pages no longer overwrite each other opportunistically.
  • 💡 LED/UI state handling is cleaner across full-experience YAMLs.

🧠 P4 Touch Stabilization

  • 🚀 P4 full AFE profiles now use a cleaner SDK baseline.
  • ✅ PSRAM XIP remains enabled on P4.
  • 🧹 Removed aggressive Wi-Fi/LWIP IRAM overrides from the P4 baseline.
  • 🎧 Kept hot AFE/intercom bridge buffers internal where contiguous heap allows it.
  • 📈 Improved largest-free-block headroom observed on P4 during media, TTS, intercom and repeated runtime use.
  • 🖥️ Reduced P4 display flicker/audio glitches seen with the previous tuning set.
  • 🧪 P4 landscape/portrait TCP/UDP full AFE YAMLs were kept aligned with the new state model.

📦 YAML Presets

  • 🧩 Full-experience YAMLs that use media playback now include the local speaker component where needed.
  • 🎚️ Full AFE profiles boot with aligned runtime defaults for AEC/VAD/FD mode.
  • 📡 TCP/UDP variants were kept paired across maintained presets where supported.
  • 🧪 Generic S3 full AEC UDP was added/aligned for the dual-bus/full-experience test matrix.
  • ⚠️ Generic S3 full AFE presets are documented as untested and live under yamls/untested/.

📚 Documentation

  • 📖 README updated for HA softphone mode, card behavior, timer UI ownership, speaker fork and P4 runtime tuning.
  • 📘 Added documentation for the project-local speaker component.
  • 🧭 Updated architecture/reference docs around the current audio stack and UI state model.
  • 🧰 Updated troubleshooting docs for current HA/card/intercom routing behavior.
  • 🖼️ Prepared wiki content with visual pages for getting started, YAML selection, HA integration, Lovelace card, phonebook/routing, audio stack, devices, P4 notes and troubleshooting.

⚠️ Breaking / Upgrade Notes from 2026.6.1

  • HA softphone cards should use mode: ha_softphone and should not set device_id.
  • Hybrid cards still require an ESP device_id and remain the ESP-mirroring mode.
  • Copied Lovelace card YAML should use show_extended_info; the previous extended-info key is not kept as a compatibility alias.
  • Custom full-experience YAMLs using platform: speaker media playback should include the project-local speaker component and set pause_releases_pipeline: true.
  • Custom display YAMLs with timers should treat timer_ringing as the authoritative timer UI owner.
  • Custom YAMLs copied from older full-experience profiles should be refreshed if they duplicate the old per-callback UI priority logic.

v2026.6.1 - Native intercom modes, routing and phonebook cleanup

Choose a tag to compare

@n-IA-hane n-IA-hane released this 01 Jun 16:14

🧭 v2026.6.1 - Native intercom modes, stronger routing and phonebook cleanup

This is a focused follow-up to v2026.6.0.

2026.6.0 shipped the Espressif GMF / esp_audio_stack migration. 2026.6.1 tightens the intercom layer above it: Home Assistant routing, standalone ESPHome-native audio, one-way endpoint modes and safer reconnect behavior.

📞 Intercom Native / Home Assistant

🗂️ Phonebook moved to an attribute

The full roster is now stored in:

sensor.intercom_phonebook.attributes.phonebook

The entity state is now only a short summary such as 5 entries.

This removes the old 255-character state limit, which was too small for larger installs such as apartments, offices or multi-room deployments.

Maintained YAMLs already subscribe to the new attribute. Custom YAMLs must update their Home Assistant text sensor subscription accordingly.

🌐 Better HA recognition across subnets and NAT

The Home Assistant integration now handles routed networks more reliably.

Test coverage for this release included:

  • ESP and HA on the same subnet
  • ESP on a routed secondary subnet
  • TCP calls across subnets
  • UDP calls with NAT return paths
  • mixed TCP/UDP endpoints
  • HA PBX mode enabled and disabled

The goal is that HA is recognized as HA, not as a generic ESP peer, even when the ESP is on another routed network.

🔀 Stronger UDP return-path handling

UDP peers can now be matched by the observed packet source when NAT changes the apparent return address.

The phonebook still keeps the real endpoint identity; the transport layer only uses the observed source as the return path when needed.

🧩 Card config rename

The Lovelace card option was renamed:

show_protocol: true

becomes:

show_extended_info: true

The old key is intentionally not kept. The option now shows more than the protocol, so the YAML name was updated to match what the UI does.

🎙️ Intercom API

🎧 ESPHome-native audio is supported again

intercom_api can now run directly on standard ESPHome microphone and speaker components.

This is important for hardware that already performs audio processing itself, for example XMOS-style front-ends or other DSP/codec paths that provide echo-cancelled microphone audio before ESPHome sees it.

In that case you do not need esp_audio_stack just to use Intercom Native.

↔️ Full-duplex, mic-only and speaker-only endpoints

intercom_api now supports three endpoint capabilities:

  • full_duplex: microphone + speaker
  • mic_only: microphone only, useful for listening/monitoring endpoints
  • speaker_only: speaker only, useful for announcement endpoints

The capability is derived from the declared audio components. Users do not need to set a separate mode flag.

🧹 Removed legacy intercom-side AEC plumbing

The old intercom fallback AEC/audio-processor path has been removed.

Current model:

  • use native ESPHome audio when the hardware already gives you processed audio
  • use esp_audio_stack full profiles when you need software AEC/AFE

This keeps intercom_api focused on call signaling and audio transport instead of duplicating audio processing.

🧪 New YAML Profiles

New ESPHome-native YAMLs are provided as starting points for native audio hardware:

yamls/full-experience/esphome-native/
yamls/intercom-only/esphome-native/

The tested generic native example uses INMP441 microphone + MAX98357-style I2S amplifier on separate I2S buses through ESPHome native microphone and speaker components.

Important: plain native INMP441 + MAX98357 does not provide echo cancellation by itself. For AEC you need either:

  • hardware/DSP AEC, such as an XMOS-style front-end, or
  • the maintained full esp_audio_stack profiles with software AEC/AFE.

The native profiles are not a ready-made Voice PE profile yet, but they are the base for that class of hardware. Feedback from users with native processed audio hardware is welcome.

🛡️ Runtime Stability

Full audio/LVGL profiles no longer run HA disconnect cleanup actions that could destabilize devices during a Home Assistant restart.

This avoids devices getting stuck or rebooting simply because HA was restarted during normal operation.

🧰 Upgrade Notes

After updating the Home Assistant integration:

  1. Restart Home Assistant.
  2. Hard-refresh dashboards using intercom-card.
  3. Update card YAML from show_protocol to show_extended_info if you used that option.
  4. Recompile maintained ESP YAMLs.
  5. For custom YAMLs, update the phonebook subscription to read the phonebook attribute.

Minimum versions remain:

  • ESPHome: 2026.5.x or newer
  • Home Assistant Core: 2026.5.0 or newer

v2026.6.0 - Intercom Native polish and Espressif GMF audio stack

Choose a tag to compare

@n-IA-hane n-IA-hane released this 29 May 14:16

🚀 v2026.6.0 - Intercom Native polish and Espressif GMF audio stack

Hotfix after initial 2026.6.0 publication

Published on May 30, 2026 after field testing the first 2026.6.0 build.

  • esp_afe now uses a compile-time split between single-mic and dual-mic targets.
  • Single-mic AFE profiles use the official ESP-SR direct feed/fetch path instead of the GMF AFE element path.
  • Dual-mic AFE profiles keep the GMF manager/element path and raw-output selection behavior.
  • Spotpear full AFE TCP/UDP profiles keep AFE VAD restore disabled by default to avoid restoring an unstable VAD state at boot.
  • The full MWW safe-start logic now uses the Intercom API idle condition instead of string-matching the state name.

This hotfix keeps the public YAMLs pointed at main and removes local debug/telemetry from production profiles.

This release is the next major step after the 2026.5.0 PBX-lite migration.

2026.5.x introduced the new call model: ESP devices as independent extensions, Home Assistant as a peer/bridge, unified phonebook, TCP/UDP routing and browser softphone support.

2026.6.0 keeps that model and rebuilds the audio foundation under it.

🏠 Home Assistant / Intercom Native

The Home Assistant side has been cleaned up around the unified PBX-lite event model.

🔁 Unified call event model

The integration and Lovelace card now use the unified:

intercom_native.call_event

event shape for session, bridge and forward updates.

This gives automations and the card a more consistent view of:

  • call scope
  • event type
  • call state
  • hangup / decline / failure reason
  • bridge and forward lifecycle

The older split event behavior is no longer the preferred model.

📵 Better unavailable-device handling

The card now handles unavailable ESP devices more explicitly instead of showing stale call controls as if the device were still reachable.

This should make dashboard state clearer when an ESP is offline, rebooting, being flashed, or temporarily disconnected from Home Assistant.

⚡ Safer fast hangup / redial behavior

The browser softphone path has been hardened for fast user actions.

If a call is ended and another call starts immediately after, browser audio cleanup no longer tears down the new call's microphone/audio path by mistake.

This fixes a class of "second call has no browser audio" style problems.

📱 Mobile notification answer flow

The documented mobile flow now supports real Answer / Decline actions:

  • Answer opens the dashboard view containing intercom-card with ?intercom_answer=1
  • the card requests microphone permission and starts the full-duplex browser/app audio path
  • Decline stays in Home Assistant automation logic and calls intercom_native.decline

This is the supported way to answer an ESP-originated call from the Home Assistant Companion app.

🧹 Versioned card cache behavior

The card is registered with a versioned frontend URL derived from the installed integration version.

After upgrading, hard-refresh the dashboard page or clear the Companion app cache if the card still shows an old version.

✅ Minimum Versions

This release requires:

  • ESPHome: 2026.5.x or newer
  • Home Assistant Core: 2026.5.0 or newer

HACS metadata now declares the Home Assistant minimum version accordingly.

⚠️ Breaking Changes

Custom YAMLs that still use the old audio component/package layout need to be migrated.

Main migration points:

  • maintained YAMLs now use esp_audio_stack
  • old i2s_audio_duplex packages are no longer the supported path
  • some YAML options were renamed:
    • speaker_volume -> master_volume
    • mic_attenuation -> input_gain
    • frame_buffers_in_psram -> buffers_in_psram
    • audio_stack_in_psram -> audio_task_stack_in_psram
  • Generic full profiles are split into AEC and AFE variants
  • full audio/LVGL profiles include OTA maintenance handling
  • old copied Lovelace card files should be replaced by the bundled card

After upgrading, clear ESPHome build caches once before compiling.

find . -type d -name .esphome -prune -exec rm -rf {} +

🎧 Audio Stack Migration

The biggest internal change in 2026.6.0 is the migration from the old custom duplex audio path to the new:

esp_audio_stack

backend.

This replaces the maintained i2s_audio_duplex path.

The goal is not just a component rename. The new backend is built around Espressif / ESP-IDF audio components that are designed to work together:

  • esp_driver_i2s for official I2S channel ownership
  • esp_codec_dev for codec-backed devices
  • gmf_io / io_codec_dev for codec IO
  • esp_audio_effects for rate, bit-depth and layout conversion
  • esp-sr for Acoustic Echo Cancellation
  • gmf_ai_audio / esp_gmf_afe_manager for the full Audio Front-End pipeline

This means the project now carries less custom audio infrastructure and relies more directly on the Espressif audio ecosystem.

💡 Why This Matters

Earlier versions had custom code for a lot of low-level audio work:

  • I2S lifecycle
  • speaker/microphone glue
  • AEC reference routing
  • rate conversion
  • bit-depth conversion
  • channel layout conversion
  • ring buffers
  • processor feed/fetch timing
  • codec-specific assumptions

That worked, but it created too much maintenance pressure and too many board-specific edge cases.

With esp_audio_stack, the project is closer to the native ESP-IDF audio model while still exposing normal ESPHome surfaces above it:

  • microphone
  • speaker
  • media player
  • mixer
  • Voice Assistant
  • Micro Wake Word
  • intercom API
  • Home Assistant entities

🧩 Supported Audio Shapes

The maintained profiles now cover these layouts through the new stack:

  • single-bus codec boards
  • single-bus no-codec boards
  • dual-bus MEMS mic + I2S amplifier boards
  • ES8311 stereo playback-reference boards
  • ES7210 + ES8311 TDM reference boards
  • dual-mic AFE boards
  • lightweight AEC-only Generic S3 profiles
  • full AFE profiles for larger flash/RAM layouts

Codec-backed devices use esp_codec_dev.

No-codec devices use official esp_driver_i2s channels directly, avoiding unnecessary codec/GMF IO dependencies on smaller builds.

🎙️ AEC and AFE Profiles

Profiles are now split more clearly.

🪶 esp_aec

Use this for lightweight echo cancellation.

It is the default direction for:

  • intercom-only devices
  • Generic S3 full-experience profiles that need to fit smaller flash layouts
  • users who want Acoustic Echo Cancellation without the full Audio Front-End cost

🧠 esp_afe

Use this for the full Espressif Audio Front-End path.

It adds:

  • Acoustic Echo Cancellation
  • Noise Suppression
  • Automatic Gain Control
  • Voice Activity Detection
  • Speech Enhancement / Blind Source Separation on supported dual-mic boards

It is heavier, but it is the right direction for boards with enough flash/RAM and for full voice-device profiles.

📦 Generic Profile Split

Generic S3 full-experience YAMLs are now split by intended target:

  • generic-s3-full-aec-*

    • lightweight path
    • intended for 4 MB-friendly builds
    • uses standalone esp_aec
    • uses the lighter previous_frame reference
  • generic-s3-full-afe-*

    • full Audio Front-End path
    • intended for larger flash layouts
    • uses esp_afe
    • uses TYPE2-style software reference

This avoids pretending one Generic YAML can fit every board and every flash layout.

🔊 Better AEC Reference Handling

Echo cancellation quality depends heavily on the playback reference.

The new stack handles reference routing per topology:

  • ES8311 boards can use stereo digital feedback
  • ES7210 TDM boards can use a hardware TDM reference slot
  • no-codec Generic AEC profiles can use previous_frame
  • Generic AFE profiles can use TYPE2-style software reference

This is one of the main reasons for the audio migration. AEC quality depends on reference timing, channel layout and conversion path, not only on enabling a library.

🧠 Runtime and Memory Improvements

The migration also cleaned up runtime behavior:

  • large buffers and task stacks are allocated earlier
  • repeated heap churn during call/media transitions has been reduced
  • microphone and speaker wrapper loops wake on real events instead of spinning
  • intercom_api parks its loop when idle
  • intercom TX uses lower-copy reads where possible
  • full profiles place selected buffers/stacks in PSRAM
  • full LVGL/audio profiles enter OTA maintenance mode before flashing

This helps demanding full-experience devices where media playback, Piper TTS, Micro Wake Word, Voice Assistant, AFE/AEC and intercom all coexist.

🧭 Maintained Board Direction

Current maintained baseline:

  • Waveshare ESP32-S3 Audio Board: full AFE, dual mic, TDM reference
  • Spotpear Ball v2: codec-backed AFE/intercom profiles
  • Generic S3 AEC: lightweight 4 MB-friendly full-experience profiles
  • Generic S3 AFE: larger flash full AFE profiles
  • Generic dual-bus: maintained intercom profiles
  • Waveshare P4 Touch: present and improving, still board-specific/experimental

🧪 Validation

Before this release, the public YAMLs were switched to remote release mode so users can download only the YAML and let ESPHome fetch packages, assets and external components from main.

Validation performed:

  • HACS validation passes
  • hassfest validation passes
  • generic-s3-full-afe-tcp.yaml compiles successfully with ESPHome 2026.5.1
  • ESPHome fetches this repository from main
  • Espressif managed components resolve and build correctly

Generic full AFE firmware size from the validation build is about 2.1 MB.

⬆️ Upgrade Notes

Recommended upgrade path:

  1. Update the Home Assistant integration through HACS.
  2. Restart Home Assistant.
  3. Hard-refresh the dashboard page containing intercom-card.
  4. Clear ESPHome build cache once.
  5. Recompile from the updated YAMLs.
  6. Flash the ESP firmware.

If you maintain custom YAMLs, start from the closest maintained profile and reapply only your board-specif...

Read more

2026.5.0 - From PBX-like to PBX-lite

Choose a tag to compare

@n-IA-hane n-IA-hane released this 14 May 14:00

Release notes 2026.5.0

From PBX-like to PBX-lite

This release changes the shape of ESPHome Intercom.

It is no longer only an ESPHome audio experiment that can place a full-duplex
call. It now has a small but real PBX-lite model: every ESP is treated as an
independent extension, Home Assistant can join as another extension, the
browser card can act as a softphone, and HA can bridge calls when the two sides
cannot talk directly.

The important part: the simple doorbell and intercom use case is still simple.
If you want one ESP button that rings Home Assistant, start from
yamls/intercom-only/, adapt the board pins, install intercom_native, add the
ESP through the ESPHome integration, and call the HA destination. PBX-lite is
the model underneath, not a requirement to design a phone system.

What PBX-lite means here

  • ESPs own their own call state: idle, ringing, outgoing, in call, declined,
    busy and ended.
  • Devices dial by phonebook name, not by hardcoded IP glue.
  • Same-transport ESPs can call each other directly.
  • Home Assistant can act as a peer, a phonebook publisher and a bridge.
  • TCP and UDP devices can live in the same setup, with HA bridging incompatible
    legs.
  • The Lovelace card can ring, answer, decline and hang up as a browser
    softphone.
  • Call reasons and errors are propagated through ESP sensors, HA state and the
    card UI.

This is why the release moves from PBX-like behavior to PBX-lite architecture.
The protocol is still intentionally small, but the pieces that matter for a
home intercom are now there.

What this unlocks

You can now build:

  • a one-button full-duplex doorbell that rings Home Assistant;
  • room-to-room ESP intercoms;
  • direct ESP-to-ESP calls on the same transport;
  • HA-bridged calls across TCP, UDP and browser audio;
  • a browser or mobile dashboard softphone;
  • full voice devices with intercom, media player, Piper TTS, Micro Wake Word,
    Voice Assistant, AFE/AEC and ducking on the same ESP;
  • ESP-only discovery setups with optional mDNS packages when HA is not meant to
    be the phonebook authority.

The same firmware model scales from "press a GPIO and talk to Home Assistant"
to a multi-room intercom where ESPs call each other, Home Assistant bridges
mixed transports, and the dashboard can participate as a call endpoint.

Transport model

TCP and UDP are both first-class presets.

TCP is the safer default for routed networks, VLANs, containers, filtered Wi-Fi
and setups where packet delivery matters more than the lowest possible latency.

UDP is useful on simple LANs where latency is the priority and packet loss is
under control. It is lighter, but routing and firewall mistakes show up faster
as audible glitches.

Both transports expose the same PBX-lite behavior. You do not need to choose a
different product mode, only the transport that fits the network.

mode: raw_udp remains available as an explicit audio-only path for go2rtc and
raw PCM links. It bypasses PBX-lite signaling on purpose.

Home Assistant integration

intercom_native has been reworked into the PBX-lite hub:

  • TCP listener;
  • UDP socket manager;
  • HA endpoint advertisement;
  • phonebook publisher;
  • bridge sessions;
  • WebSocket state for the Lovelace card;
  • validated services and clearer failure handling.

Home Assistant is no longer just a helper around ESPHome. In PBX mode it
becomes an active call participant and bridge, while direct ESP-to-ESP calls can
still avoid HA in the media path.

The HA peer name is hass.config.location_name, so the firmware does not need a
hardcoded "Home Assistant" label. Standard HA-managed YAMLs use HA as the
phonebook authority; ESP-side mDNS announce and discovery remain opt-in for
setups that deliberately run without HA managing the roster.

Lovelace card and frontend

The dashboard card now follows the PBX-lite state model instead of only
mirroring a narrow direct-call path.

It can show ringing, outgoing, in-call and ended states, surface hangup reasons,
call ESP contacts by name, and participate in HA-bridged calls. The current
README media was refreshed around this model so the visible demo matches the
runtime behavior of the release.

Audio engine rebuild

The audio side was almost completely rebuilt.

The full-experience devices now keep media playback, Piper TTS, Voice
Assistant, wake word, AFE/AEC and intercom in the same runtime instead of
treating them as isolated demos.

Main changes:

  • early allocation of large stacks and buffers to preserve contiguous internal
    RAM;
  • retained working buffers instead of repeated allocation during audio
    transitions;
  • cleaner I2S lifecycle with hot-path enable and disable;
  • native ESPHome speaker and microphone semantics wherever possible;
  • improved mixer, ducking and AEC reference behavior;
  • better socket accounting for overlapping HA API, logging, media HTTP, TTS
    HTTP and intercom sockets;
  • media playback can be paused from Home Assistant and resumed later;
  • barge-in, TTS, media pause and assistant responses were validated together
    instead of as separate happy paths.

Board audio improvements

  • Codec-backed boards keep their hardware codec path.
  • Codec-less Generic S3 boards use the duplex software volume path.
  • Media volume and Master Volume now behave as a cascade.
  • Software attenuation is real across the range, not just mute versus full
    scale.
  • AEC reference capture, FIR decimation and single-bus duplex handling were
    tightened across supported boards.
  • ES7210 TDM reference-slot behavior is documented and guarded with runtime
    warnings.

i2s_audio_duplex is not only for intercom. If you are building your own
ESPHome Voice Assistant and need a shared microphone and speaker I2S path,
speaker reference handling, or a cleaner audio lifecycle, the component can be
used as part of that build too.

YAML and release packaging

The public YAMLs are intended to be downloadable presets. A user should be able
to download one YAML, adjust the hardware options that are meant to be changed,
and let ESPHome fetch packages and external components from this repository.

For release, the managed YAMLs point to main. Local development can still use
the path-switching script to compile against the working tree.

Validated release targets

Validated targets for this release:

  • Waveshare S3 Audio full AFE TCP and UDP;
  • Spotpear Ball v2 full AFE TCP and UDP;
  • Generic ESP32-S3 full AEC UDP as the codec-less reference target;
  • Home Assistant OS with the native integration and Lovelace card.

Waveshare P4 Touch remains experimental in this release. The UI and audio stack
are present, but the ESP32-P4 runtime profile still deserves a separate
validation pass.

Upgrade note

This is a breaking release for 4.x users. Read
docs/BREAKING_CHANGES.md before upgrading firmware or
Home Assistant integration files.