VoIP stack for Home assistant and ESPHome

:telephone: VoIP Stack for Home Assistant and ESPHome

Current stable release: 2026.9.0

VoIP Stack turns Home Assistant, ESPHome devices and standard SIP phones into a
real local communications system.

Home Assistant is not merely controlling a few call buttons. It can act as a
SIP endpoint, browser softphone host, call router, media bridge, local SIP
registrar, conference focus and optional SIP trunk endpoint.

ESPHome devices become local SIP phones. Depending on their hardware and
firmware profile, they can provide audio intercom, Voice Assistant features or
complete bidirectional audio and video on ESP32-P4.

The simple use case is still simple:

Door button → Home Assistant rings → answer → talk → hang up.

But the same installation can grow into a local house phone system, a video
doorbell, room-to-room calling, registered SIP phones, ring groups,
conferences, external calls and an Assist-powered answering machine.

For normal local installations, no separate Asterisk or FreeSWITCH server is
required.

Built for people who would rather call an ESP32 than another human being.
Entirely understandable.


What can you build?

Scenario What happens
Video doorbell A SIP video door station calls Home Assistant. Answer from a browser, wall tablet or Companion app with audio and video.
ESPHome door intercom An ESP button calls Home Assistant, another ESP, a room phone, a ring group or an external destination.
ESPHome videophone A supported ESP32-P4 sends its camera, receives remote video and displays the caller on its physical screen while bidirectional audio remains active.
Room-to-room phones Give Kitchen, Bedroom, Reception or Warehouse their own HA browser phone or ESPHome device. Call between rooms by name or extension.
ESP-to-ESP intercom ESPHome endpoints discover the shared phonebook and call each other through standard SIP/SDP/RTP.
Home Assistant softphones Create one or more logical HA phones, each with its own Device, state, extension, DND, groups, camera policy and Lovelace card.
Existing SIP equipment Register Zoiper, Linphone, baresip, pjsua, an ATA or a standard SIP phone directly to Home Assistant.
External calls Connect an optional provider or PBX trunk and route calls between external networks and local endpoints.
Ring groups Call several HA phones, ESPs and registered SIP clients together. The first answer wins and the remaining phones stop ringing.
Conference rooms Home Assistant hosts an audio conference and mixes participating HA, ESP and registered SIP endpoints.
Call Home Assistant Assist Give an Assist pipeline a phonebook name and extension, then call it from an ESP, SIP phone, HA softphone or external trunk.
Automated answering Let phones ring first, then forward the same unanswered call to Assist using a normal Home Assistant automation.

One Home Assistant, many real phones

VoIP Stack can host multiple logical Home Assistant phones.

Keep the default phone, then open:

Settings → Devices & services → VoIP Stack → Add phone

Create phones such as Home, Kitchen, Reception, Workshop, a bedroom tablet or
a warehouse kiosk.

Every browser phone is a native Home Assistant config subentry and Device. It
has its own:

  • optional extension;
  • call state and connectivity;
  • call Event Entity;
  • Do Not Disturb;
  • Auto Answer and Send Camera settings;
  • ring-group and conference-group membership;
  • preferred microphone, speaker and camera.

Bind one VoIP Stack card to the intended Device using the visual card editor.
The card, Device controls and Home Assistant actions all update the same
persisted backend configuration.

A logical phone can still ring while its tablet is temporarily offline. This
allows missed-call, timeout and forwarding automations to work even when a
kiosk browser is not open.

For a real room-to-room call, use two different browser sessions or devices.
Two cards in the same browser tab cannot represent two independent rooms
because one browser tab owns one microphone, speaker and camera pipeline.


Native SIP video in Home Assistant

Live SIP video call in the Home Assistant softphone

Home Assistant browser phones can negotiate standard SIP video with compatible
phones, PBXs and video door stations.

The browser path supports:

  • H.264, VP8 and JPEG;
  • bidirectional and one-way video;
  • calls that begin with audio and add video later;
  • browser camera return on compatible calls;
  • live microphone, speaker and camera selection.

An optional bounded FFmpeg receive path can convert H.263, H.263-1998 or H.265
for display in the browser.

The card preserves the native aspect ratio inside its assigned Lovelace slot,
so video does not expand into neighbouring dashboard columns. Audio remains
active if video is unavailable or rejected.

Video requires HTTPS, browser permission, a compatible browser and a reachable
RTP path.


ESPHome has a videophone now

The maintained ESP32-P4 profiles turn a development board into a complete SIP
videophone.

The P4 can transmit its own camera, receive the remote RTP video stream, decode
it and display the other party on its physical MIPI DSI panel while
bidirectional audio remains active.

Calls can start directly with audio and video, or begin as ordinary audio calls
and enable video later. When the call ends, the device returns to its normal
LVGL interface.

Separate JPEG and H.264 profiles keep each firmware focused on the selected
codec. The full JPEG profile can combine the videophone with AFE echo
cancellation, Micro Wake Word, Voice Assistant, LVGL, TTS, HTTP media and
Sendspin.

JPEG is the stable full-device baseline. H.264 remains experimental in
2026.9.0.

This opens the door to custom ESPHome videophones, video doorbells and
room-to-room devices that remain completely local.


One shared phonebook and dial plan

The central phonebook can contain:

  • Home Assistant browser phones;
  • discovered ESPHome VoIP endpoints;
  • registered SIP accounts;
  • Home Assistant Assist pipelines;
  • manual SIP contacts and internal extensions;
  • external destinations reached through an optional trunk;
  • dynamic ring groups and conference groups.

Dial a destination by friendly name, extension, SIP URI or telephone number.
VoIP Stack resolves the route and media capabilities centrally.

Registered SIP accounts appear only while their registration is valid.
Discovered ESPHome contacts follow device availability, while static contacts
and browser phones remain available independently.

ESP endpoints can use direct local SIP/RTP where appropriate. Home Assistant
can bridge calls when the route, transport or media formats require it.


Ring groups and conference rooms

A ring group may contain browser phones, ESP endpoints, registered SIP clients
and manual contacts.

VoIP Stack checks DND, busy state, availability and endpoint capabilities
before making the phones ring. The first valid answer wins and the remaining
destinations are cancelled.

Conference groups are different: participants join the same HA-hosted mixed
audio room. Optional members can ring when the room starts, and resources are
released when the last participant leaves.


Home Assistant Assist becomes a telephone destination

Assist can appear in the same phonebook as every other endpoint.

Give a pipeline a name and optional extension, then call it from an ESPHome
phone, a Home Assistant browser phone, a registered SIP client or an external
trunk.

The telephone call remains open for a normal multi-turn conversation:

  1. STT listens to the caller;
  2. the configured conversation agent processes the request;
  3. the selected TTS provider streams its reply into the same call;
  4. Assist returns to listening;
  5. the conversation continues until hangup.

The assistant’s behaviour belongs in the selected pipeline prompt. It can be a
polite receptionist, a domestic secretary or something considerably less
respectable.

Optional VoIP Stack Assist intents also let Voice Assistant satellites control
calls with phrases such as Call Kitchen, Answer, Decline and
Hang up.

A normal Home Assistant automation can let a door or room phone ring for a
chosen period and then forward the same unanswered call to Assist. Presence,
schedules and caller identity can all become automation conditions.

The ordinary phonebook, extensions, groups and configured fallback destination
remain the stable default. Automation-native routing is an optional layer for
more advanced installations.


ESPHome endpoints and full voice devices

ESPHome endpoints advertise the media they actually have:

Derived role Media
full_duplex Microphone TX and speaker RX
mic_only Microphone TX only
speaker_only Speaker RX only

Maintained full-experience profiles can combine:

  • media playback and Music Assistant or Sendspin;
  • TTS, Micro Wake Word and Voice Assistant;
  • ringtone and VoIP calls;
  • LVGL controls and call state;
  • lightweight AEC or full ESP-SR AFE;
  • camera capture and physical video presentation on supported ESP32-P4
    profiles.

Playback feeds one coordinated output and one phase-coherent echo reference.
Micro Wake Word, Voice Assistant and VoIP TX consume the same cleaned post-AEC
microphone instead of creating competing audio paths.

The project is split into reusable components:


Installation

Home Assistant through HACS

  1. Open HACS and search for VoIP Stack.
  2. Download the latest stable release.
  3. Restart Home Assistant.
  4. Open Settings → Devices & services → Add integration.
  5. Search for VoIP Stack and complete the setup flow.
  6. Add additional browser phones or standard SIP accounts with Add phone.

The integration registers the Lovelace card automatically.

Default ports:

Purpose Default
SIP signaling 5060
RTP base 40000

ESPHome

Start from a maintained YAML matching your board and use case:

The maintained YAMLs reference the stable main branches of the project
components.


Important limits and security notes

  • Local SIP and RTP are plaintext. Use a trusted LAN, VLAN or VPN.
  • Do not expose ESP SIP/RTP listeners directly to the public Internet.
  • Assist and normal ESP32-S3 profiles are audio-only.
  • Video requires a browser phone, compatible SIP device or supported ESP32-P4
    videophone profile.
  • Conference video mixing is not implemented.
  • There is no SRTP, SIP/TLS on ESP, ICE/STUN/TURN or call recording.
  • H.264 on ESP32-P4 remains experimental in 2026.9.0.
  • Provider, PBX, NAT and third-party door-station behaviour can vary.
  • Read the breaking changes before upgrading custom YAMLs or automations.

Links

Feedback wanted

Compatibility reports are especially useful for SIP video devices, real PBX
and provider trunks, registered SIP clients, ESP32-S3 and ESP32-P4 hardware,
and room-to-room installations.

When reporting a problem, please include the exact call path, SIP transport,
offer and answer SDP, endpoint models and negotiated codecs where possible.

This started as an ESPHome intercom.

Now Home Assistant has a local phone system living inside it, and apparently
the ESP32-P4 demanded a screen too. :telephone: :house: :guitar:

6 Likes

Can I use this project out of the box in order to set up Assist to be my answering machine when I'm away?

1 Like

Yes, with the version that has just been released, this is exactly what I focused on.

My friends are currently hammering my VoIP Stack because they find it hilarious to call my phone number and talk to the assistant, since it swears at them and tells them to fuck off.

You can create an automation so that, when an incoming call arrives, it is not sent directly to the Home Assistant softphone but is immediately routed to the Voice Assistant instead.

The assistant now has its own extension, which you can choose. You can also call it directly from a softphone by using its name. For testing, I use Zoiper: if I enter “Troiaio”, which is the name of my assistant, as the destination and place the call, I can talk to it.

I am pointing this out because, despite having worked with PBXs for years, I did not know that VoIP could use a literal string as the called destination. I had always assumed that everything had to be based on numeric extensions. This may be useful information for other users reading this as well.

In VoIP Stack, you can place SIP calls to both numeric extensions and literal string destinations. Alternatively, you can assign the assistant a conventional extension such as 1001 and call it from any VoIP endpoint known to Home Assistant.

You can also reach it through an external phone call. You call the number associated with your trunk, and the call reaches the Home Assistant VoIP Stack. It then waits for a configurable number of seconds for DTMF input before forwarding the call to the Home Assistant softphone.

If, during that time window, you enter 1001 from the calling phone, the call is routed to the Voice Assistant and you can talk to it.

1 Like

:telephone: VoIP Stack 2026.7.1: Call Home Assistant Assist, Ring Groups, Conferences And A Better Phone UI

VoIP Stack 2026.7.1 is now available through HACS.

This release turns Home Assistant’s voice assistant into a real telephone destination, adds ring groups and conference rooms, improves the Lovelace phone experience
and hardens the SIP, RTP and ESPHome audio paths for everyday use.

The short version:

You can now call your Home Assistant voice assistant from an ESP device, a SIP softphone or a real external phone number — and have a normal multi-turn spoken
conversation with it.

VoIP Stack dashboard in action


:speaking_head: Call Home Assistant Assist By Phone

VoIP Stack can now expose any Home Assistant Assist pipeline as a normal phonebook destination.

Enable Include voice assistant, choose either HA’s preferred Assist pipeline or a specific pipeline, then assign it an extension.

No extension is reserved automatically: you choose one that fits your own dial plan.

The assistant can then be called from:

  • an ESPHome VoIP device;
  • Home Assistant’s softphone;
  • Zoiper, Linphone, bareSIP or another registered SIP client;
  • another compatible SIP endpoint;
  • an external mobile or landline through an optional SIP trunk;
  • an initial Home Assistant inbound routing decision.

The assistant appears in the same shared phonebook as every other destination. You can call it by its numeric extension or, where supported by the client, directly
by its name.

The assistant can greet the caller first

When a call starts, Assist receives the original SIP caller identity as its first textual turn.

If the caller matches a phonebook entry, its friendly name is used. Otherwise, the original SIP caller string or telephone number is preserved.

This makes prompts such as these possible:

  • greet family members by name;
  • answer a door station differently from a normal internal phone;
  • act as a polite answering machine for direct Assist calls;
  • behave differently when called from a specific ESP or SIP extension.

After the initial greeting, the same telephone call stays open:

  1. Home Assistant listens through the selected STT provider;
  2. the configured conversation agent processes the request;
  3. the configured TTS provider streams the reply into the call;
  4. Assist returns to listening;
  5. the conversation continues until the caller hangs up.

Conversation context is retained between turns.

This uses the selected native Home Assistant Assist pipeline. It is not tied to a particular provider or to my own test setup: Piper, Wyoming services, local or
cloud STT/TTS providers and other HA conversation agents follow the pipeline already configured in Home Assistant.

No second SIP port, generated satellite or separate Home Assistant VoIP integration is required.


:office_worker:Voice Assistant Calls Today Automated Secretary Scenarios Next

Calling Home Assistant Assist by phone is already fully available in 2026.7.1.

The assistant is a normal destination in the shared phonebook and can already be called:

  • directly from an ESPHome VoIP device;
  • from Home Assistant’s softphone;
  • from a registered client such as Zoiper or Linphone;
  • by its phonebook name or numeric extension;
  • from an external mobile or landline through an optional SIP trunk;
  • from an initial Home Assistant inbound routing decision.

The call remains open for a normal multi-turn conversation. Assist receives the caller identity, greets the caller, listens through the selected STT provider and
streams each TTS response back into the same telephone call until the caller hangs up.

Coming in the next versions

The next step is exposing all the remaining hooks required to build advanced answering-machine and domestic-secretary scenarios entirely with normal Home Assistant
automations.

The intended automation model is:

Incoming call
     ↓
Ring Home Assistant, a ring group or selected house phones
     ↓
Wait for a user-defined period
     ↓
If the same call is still unanswered
     ↓
Forward that existing call to Voice Assistant

The automation will be able to retain the original SIP dialog, Call-ID and caller identity while forwarding the still-ringing call to Assist.

This will make scenarios such as these possible:

Nobody answers within 30 seconds → forward the existing call to Assist
At night → ring briefly, then let Assist answer
Away from home → use Assist as an answering machine
Door station unanswered → let Assist greet the visitor
External caller unanswered → let Assist collect a message

The goal is not to introduce a second hard-coded fallback engine.

VoIP Stack will expose the necessary call events, state and forwarding actions, while the user defines the actual policy with standard Home Assistant building blocks
such as conditions, timers, presence, schedules and wait_for_trigger.

The phonebook remains the default dial plan, and Home Assistant automations become an optional programmable layer above it.

Direct internal and external calls to the Voice Assistant are already supported in 2026.7.1. Only the delayed ring first, then forward the same unanswered call
automation contract is planned for a future release.


:bell: Real Ring Groups

Endpoints can now join one or more ring groups.

Call a contact such as RG Home and all available members ring together. A group can contain:

  • Home Assistant’s softphone;
  • ESPHome phones;
  • registered SIP clients;
  • manual SIP contacts.

The first endpoint to answer wins. The remaining legs are cancelled, and late answers cannot steal or duplicate the established call.

After the call is answered, the Lovelace card shows the endpoint that actually answered instead of continuing to display only the group name.

Group contacts are generated from live membership and disappear automatically when no endpoint declares them.


:studio_microphone: Home Assistant Conference Rooms

Home Assistant can now host SIP conference rooms.

Calling a destination such as CG Home joins that conference. Endpoints with Ring on conference enabled can also be invited automatically when the room starts.

The conference focus:

  • mixes active participants;
  • applies additional audio headroom as the room grows;
  • manages invited call legs;
  • releases calls and RTP resources when participants leave.

Home Assistant, ESP devices and registered SIP phones can participate in the same conference.


:house: Home Assistant And Registered SIP Phones Are First-Class Endpoints

Home Assistant’s softphone can now publish and persist:

  • its own extension;
  • Do Not Disturb;
  • ring-group membership;
  • conference-group membership;
  • whether it should ring when a conference starts.

These values can be changed from the card or through Home Assistant services. They are stored by the integration and survive integration reloads and complete Home
Assistant restarts.

Registered clients such as Zoiper and Linphone can also have:

  • a friendly display name;
  • an extension;
  • ring-group membership;
  • conference-group membership;
  • conference-ringing preferences.

Extensions, groups, ESP endpoints, registered phones and optional trunk destinations all resolve through the same shared phonebook and dial plan.

Incoming callers do not need to exist in the phonebook. Unknown but reachable and protocol-compatible SIP callers can still ring HA or an ESP, subject to the
usual destination, DND and busy checks.


:control_knobs: A More Useful Lovelace Phone Card

The Lovelace card received a substantial usability pass.

Manual keypad

HA and ESP mirror cards can dial:

  • a phonebook name;
  • an extension;
  • a full SIP URI;
  • a telephone number.

ESP endpoint options

The ESP mirror Options view exposes supported endpoint settings such as:

  • Auto Answer;
  • Do Not Disturb;
  • extension;
  • ring groups;
  • conference groups;
  • Ring on conference.

The card remains a mirror and controller: the selected ESP is still the real owner of its call state and settings.

Shared phonebook mode

The same card can render the canonical Home Assistant VoIP phonebook.

Contacts are sorted alphabetically, the view uses the available Home Assistant Sections grid space, and longer lists scroll inside the assigned card area.

Sections and live availability

HA softphone, ESP mirror and phonebook modes respond to the width and height assigned by Home Assistant Sections.

If no card name or title is configured, the header row is omitted completely.

ESP mirror cards also follow the bound endpoint live:

  • ESP disconnects → card becomes unavailable;
  • ESP reconnects → card recovers automatically.

No dashboard reload or polling timer is required.

Scrolling at the end of a card is handed back to the surrounding dashboard, and native selectors remain readable in both light and dark themes.


:mobile_phone: Waveshare P4 Touch Phone UI

The maintained Waveshare P4 Touch profile now has an on-device telephone interface.

Its VoIP panel can switch explicitly between:

  • Contacts
  • Keyboard

The local keypad calls through the same phonebook and dial plan as the rest of the system. Calls are not implemented through a second parallel routing path.

Assist, media, timers, calls, ringtone, LEDs, display state and ducking now converge through the shared runtime controller.

This removes several “last callback wins” races that could previously leave the display, LED or audio policy in the wrong state.


:telephone_receiver: More Predictable SIP Calls

A large part of this release is less visible but important during real use.

Call setup and teardown now match the correct:

  • Call-ID;
  • CSeq;
  • SIP branch;
  • dialog tags;
  • remote peer.

Cancellation, decline, busy, answer, hangup and immediate redial have deterministic ownership and cleanup.

The Hang Up action remains available while a call is still in calling, including slow or unreachable external destinations.

A cancellation that crosses a successful answer is completed with the proper acknowledgement and teardown instead of leaving a ghost call.

Unsupported hold or codec-changing re-INVITE requests receive 488 Not Acceptable Here without destroying the existing call.

SIP authentication retries were also corrected for stricter PBX and FRITZ!Box implementations.

Home Assistant calling an   ESPHome VoIP endpoint

Cross-transport SIP call bridged by   Home Assistant


:1234: Better DTMF Routing

Initial extension routing supports:

  • standard RTP telephone-event;
  • compatible legacy SIP INFO DTMF;
  • digits entered at normal human speed.

This is the path used, for example, when an external caller reaches the trunk and enters the extension of an ESP, registered phone or Voice Assistant.

:test_tube: Experimental: DTMF Events During A Call

During an already established call bridged by Home Assistant, every DTMF key can also fire a voip_stack.dtmf event.

This enables automations such as:

Press 1 during the intercom call to open the gate.

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 the caller, callee, source leg, digit, call identifiers and transport.

This path is deliberately separate from initial extension routing:

  • an in-call key does not transfer the call;
  • audio continues normally;
  • detection happens entirely in Home Assistant;
  • no additional real-time parser is added to ESP firmware.

This feature is experimental in 2026.7.1. Use strict caller/source filters and test carefully before associating phone keys with locks, gates or other security-
sensitive devices.


:speaker_high_volume: Audio And Real-Time ESPHome Improvements

Browser and ESP audio paths received another qualification and cleanup pass.

Highlights include:

  • stateful browser codecs;
  • bounded audio queues;
  • absolute packet pacing;
  • a short browser microphone jitter buffer;
  • PCMA/G.711 level correction for normal telephone earpieces;
  • L16 48 kHz and Opus 48 kHz where supported;
  • conversion state prepared outside per-frame processing;
  • no arbitrary delays added to ESP real-time loops.

Generic software-AEC profiles now use a previous-frame reference by default.

The optional ring-buffer reference is aligned when a microphone consumer starts, so a new call cannot begin using stale playback audio accumulated before the call.

The AFE worker is persistent and event-driven. It sleeps while idle and wakes from notifications instead of relying on fixed polling delays.

Waveshare P4’s real-time I²S/AFE bridge remains in internal RAM. Its AEC path was exercised while Sendspin, TTS and bidirectional VoIP were active together.


:white_check_mark: Tested On Real Hardware And Real Calls

The release was qualified with:

  • Waveshare ESP32-S3 Audio;
  • Spotpear Ball v2;
  • Waveshare ESP32-P4 Touch;
  • generic ESP32-S3 native and audio-stack profiles;
  • Home Assistant softphone calls;
  • ESP-to-HA, HA-to-ESP and ESP-to-ESP calls;
  • registered SIP clients;
  • callers absent from the phonebook;
  • ring groups and conferences;
  • DND and Auto Answer;
  • external calls through a real SIP trunk;
  • mixed 8, 16 and 48 kHz media paths;
  • concurrent Sendspin, TTS and VoIP load.

Assist was tested both from a locally registered SIP client over Opus 48 kHz and from an external mobile caller through a PCMA 8 kHz trunk.

The external call retained one conversation over three spoken turns, including a Home Assistant control request, without RTP drops or media errors.


:warning: Important Boundaries

A few limits remain intentional:

  • ESP SIP/RTP is plaintext and belongs on a trusted LAN, VPN or behind an SBC;
  • RTP media remains UDP even when SIP signalling uses TCP;
  • full SIP hold/resume renegotiation is not implemented;
  • acoustic in-band DTMF tones are not decoded;
  • AFE/AEC microphone output remains 16 kHz by design;
  • Home Assistant bridging is the supported path when endpoints cannot negotiate compatible media directly.

:package: Installation And Upgrade

Install or upgrade VoIP Stack through HACS, then restart Home Assistant when prompted.

After upgrading, open:

Settings → Devices & services → VoIP Stack

Use Reconfigure to enable the optional Voice Assistant endpoint, choose its pipeline and assign an extension.

Users compiling the maintained ESPHome profiles should update their project sources and rebuild the relevant device firmware.

Full source, YAML examples and documentation:

GitHub - n-IA-hane/esphome-intercom: VoIP Stack for ESPHome and Home Assistant - local SIP phones, HA softphone/router, phonebook, softphone accounts and optional trunk calls · GitHub

Stable release:

Release 2026.7.1: Assist By Phone, Groups And A Stronger VoIP Stack · n-IA-hane/esphome-intercom · GitHub

I would especially appreciate real-world feedback about:

  • different SIP providers and PBXs;
  • FRITZ!Box registration;
  • direct internal and external Assist calls;
  • ideas and requirements for the upcoming answering-machine and secretary automation hooks;
  • ring and conference groups;
  • VLAN, VPN and routed-network setups;
  • mixed-codec calls;
  • custom ESPHome audio hardware.

This project started as an ESPHome intercom.

With 2026.7.1, Home Assistant can answer the telephone with its own voice assistant. :telephone::house::speaking_head:

3 Likes

That is indeed hilarious. I will try it out the end of this month. Thanks beforehand for the nice project. I’ll get in touch if I have any questions left :slight_smile:

Really packed with functionalities :slight_smile:
I wonder if / how we can make an ESP satellite call the home assistant host by voice? Would be useful for my wife who is a little bit tech impaired :wink:

This is already supported. You just need to enable the relevant option in the component’s config flow.

After that, it all depends on how accurate your assistant’s speech recognition is. I sometimes run into issues simply because it understands one word as another.

For example, suppose your Home Assistant instance is called “Home.” You say, “Call Home” to your assistant. If it correctly understands “Call Home,” the call goes through. If it understands “Call Moon,” then obviously the call fails, or the assistant replies with a generic response.

Cool!
Is “Home” in your example the actual name of my HA instance, or some other name I configure somewhere in your integration?


This.

Native SIP video is coming to the Home Assistant softphone :movie_camera::telephone:
A fairly substantial development update has landed in VoIP Stack 2026.7.2-dev.
We are now dangerously close to turning a Lovelace card into a real native SIP video phone.
Home Assistant SIP video call
The Home Assistant softphone can now negotiate and exchange video with standard SIP endpoints and PBXs using normal SIP/SDP/RTP media negotiation.

ha-sip-video-call
What is working
• Native video inside the VoIP Stack Lovelace card
• Direct H.264, VP8 and RFC 2435 JPEG
• Bidirectional browser camera video with H.264 or VP8
• Independent send and receive directions
• Manual answer or auto-answer
• Receive-only calls when the local camera is disabled
• Camera enable/disable during an active call
• Correct Calling, Ringing and In call card states
• Local hangup, remote BYE and caller CANCEL
• SIP video through authenticated PBX/trunk calls
• Optional receive-only FFmpeg conversion for H.263, H.263-1998 and H.265
The video fills the card while call identity, duration and hangup controls remain available in a responsive bottom bar.
ESPHome voice endpoints remain audio-only. The video path belongs to the Home Assistant browser softphone.
Real SIP qualification
This is no longer only a mocked browser demo.
The current build has been tested between two independent Home Assistant installations registered as normal SIP extensions through a Wildix PBX. Testing covered both call directions, ringing, answer, auto-answer, decline, CANCEL, BYE, camera-disabled calls
and live camera toggling.
The captured signaling uses normal SDP media descriptions such as:
m=video RTP/AVP 103 104
a=rtpmap:103 H264/90000
a=fmtp:103 profile-level-id=42800d;packetization-mode=1;level-asymmetry-allowed=1
a=rtpmap:104 VP8/90000
a=sendrecv
There are no Wildix-specific video parameters or proprietary media protocols involved.
Home Assistant can now control the dial plan
This release also introduces automation-native call routing.
For example, Home Assistant can ring first and forward the same unanswered call to an Assist
extension after 30 seconds:
alias: VoIP - HA unanswered to Assist
mode: parallel
For example, Home Assistant can ring first and forward the same unanswered call to an Assist
extension after 30 seconds:
alias: VoIP - HA unanswered to Assist
mode: parallel
triggers:

Is there any sensors included in this stack that will tell me if a call is incoming, and from which number? I’d like to create an automation to broadcast a TTS to my speakers on incoming calls.

Yes, I’m working on this, and it’s exactly the type of scenario I want to open up. To be able to create advanced dial plans using Home Assistant automations, I’m trying to expose as many hooks, triggers, and conditions as I can, also to cover any scenarios I haven’t considered but that might be useful to users.

1 Like

Nice job @meconiotech I was just looking into deployeing asterisk into my homelab for stuff like this, this hits the spot. what i dont understand or maybe i missed in the very well written documentation is how do i create extensions? i was expecting this to be an add-on(app) wher i could manage stuff but i just cant find where i create my extensions

Call this service from developer tool voip_stack.create_account

:tada: VoIP Stack 2026.8.0: Native HA Video Phones, Multi-Room Calling/Video Calling And PBX Routing

VoIP Stack 2026.8.0 is now available through HACS.

This post contains only the user-visible delta from stable 2026.7.1.

:house: Multiple Home Assistant phones

Home Assistant can now host more than one logical browser phone.

Keep the migrated default phone, then use:

Settings → Devices & services → VoIP Stack → Add phone

Create Kitchen, Reception, Warehouse, Bedroom or any other room phone and bind
one VoIP Stack card to each Device.

Each phone has independent:

  • extension and phonebook identity;
  • call state and call Event Entity;
  • connectivity;
  • Do Not Disturb;
  • Auto Answer;
  • Send Camera;
  • ring groups and conference groups;
  • Ring for conference calls.

These settings belong to the integration backend and survive browser cache
clearing, integration reloads and Home Assistant restarts.

A logical browser phone may ring while its kiosk is temporarily offline. This
allows missed-call, timeout and forwarding automations to run independently of
whether one particular dashboard is open.

:movie_camera: Native SIP video calling

Live SIP video in the Home Assistant card

The Home Assistant softphone can now negotiate SIP video with compatible
phones, PBXs and door stations.

  • Direct browser path for H.264, VP8 and JPEG.
  • Optional bounded FFmpeg receive path for H.263, H.263-1998 and H.265.
  • Bidirectional or one-way video.
  • Audio-to-video and video-to-audio re-INVITE.
  • RTCP PLI/FIR feedback where negotiated.
  • Browser camera return for compatible H.264 and VP8 calls.
  • Responsive in-card video that preserves aspect ratio and dashboard geometry.
  • Optional detailed RTP/media information inside the compact call bar.

Audio remains independent if video is unavailable. ESPHome and Assist endpoints
remain audio-only, and conference rooms currently mix audio only.

:compass: Initial preview: automation-native PBX routing

Home Assistant automations can now influence explicit inbound routing
decisions without replacing the normal phonebook dial plan.

  • Direct incoming mode may expose a bounded route_requested decision.
  • DTMF mode keeps explicitly entered extensions authoritative.
  • ingress and origin distinguish trunk calls from local extension calls.
  • voip_stack.select_inbound_destination chooses the initial destination.
  • voip_stack.forward moves an already ringing or connected HA-owned call.
  • Forward failure may resume the original call, terminate it or return busy.
  • Phone-scoped call-state Sensors support rules such as “ringing for 30
    seconds”.

This is an opt-in preview. The phonebook, explicit extensions, groups and
configured fallback destination remain the stable default. Preview event fields
and decision semantics may still evolve.

This enables the normal domestic-secretary flow:

Door call → ring selected phones → nobody answers → forward the same call to Assist

Presence, schedules and caller/trunk origin can be ordinary Home Assistant
conditions.

:busts_in_silhouette: Unified ring groups and conferences

Groups now use the same canonical PBX routing and media lifecycle as every
other destination.

  • Ring groups call eligible members in parallel.
  • The first answer wins.
  • Losing SIP legs receive the correct CANCEL or BYE.
  • The caller is excluded when it belongs to the destination group.
  • DND, busy state, disabled endpoints and media capability are checked before
    fan-out.
  • Browser phones, ESP endpoints and registered SIP clients can share a group.
  • Conference groups host a real HA-mixed audio room and clean up when the last
    participant leaves.

:telephone: SIP, trunk and lifecycle hardening

The large internal consolidation is mostly invisible when it works:

  • SIP dialog identity is independent from one TCP connection or source port.
  • Confirmed trunk dialogs survive a replacement TCP flow.
  • Incoming answer prepares resources before committing signaling and media.
  • Audio/video updates commit atomically against the current call generation.
  • Late provisional responses and stale browser callbacks cannot resurrect a
    terminated call.
  • Hang Up remains available during calling, connecting and remote ringing.
  • CANCEL, 487 Request Terminated, ACK and crossed-200 BYE use one lifecycle.
  • Record-Route, Contact, CSeq and in-dialog routing are retained correctly.
  • Cleanup releases dialogs, tasks, media owners, relays and RTP reservations
    before the endpoint returns idle.

Initial trunk extension selection supports negotiated RFC 4733
telephone-event and compatible SIP INFO digits. Established HA-owned bridges
also publish one preview voip_stack.dtmf occurrence per key for door and gate
automations.

:desktop_computer: Card and Home Assistant integration

  • The card uses normal Home Assistant services instead of a parallel call
    engine.
  • The visual card picker suggests VoIP Stack for the correct browser-phone
    call-state entity and binds it to the correct Device.
  • Old entity-bound dashboard cards remain supported.
  • Navigating between dashboards releases completed-call browser media claims.
  • A finished call no longer leaves another phone disabled or shows a false
    “media active in another tab” error.
  • Auto Answer uses a permission-safe browser flow.
  • Auto Answer and Send Camera are persisted phone settings.
  • Phone and integration diagnostics can be downloaded with private fields
    redacted.
  • Logbook records one readable summary per PBX session.
  • Runtime snapshots expose sessions, legs, routes, owners, media tasks and RTP
    ports for troubleshooting.

:studio_microphone: ESPHome audio and endpoint updates

Maintained full-device profiles continue to share one coordinated playback
path and one cleaned post-AEC microphone between Micro Wake Word, Voice
Assistant and VoIP.

The ESP endpoint role is now derived only from real audio components:

  • full_duplex;
  • mic_only;
  • speaker_only.

The former signaling-only control_only shape is not supported.

ESPHome primary entities are now declared explicitly. Custom YAMLs that relied
on auto_entities must add the required platform: voip_stack entities or use
the maintained package.

:warning: Breaking changes to review

Please read the complete
2026.8.0 breaking changes
before upgrading.

The important short version:

  1. Restart Home Assistant and run Reconfigure once after updating.
  2. Verify each additional phone’s extension, groups, DND and video settings.
  3. Bind each HA softphone card to its intended phone Device.
  4. Public call actions now use destination as the remote target.
  5. Optional device_id selects the local HA phone placing or controlling the
    call; it does not identify the remote destination.
  6. Remove old target, endpoint_id, entity_id, source and similar action
    aliases.
  7. Generated SIP account passwords are returned once by the administrator
    action response and are no longer broadcast in notifications or events.
  8. Update custom ESPHome YAMLs that relied on auto_entities.
  9. Hard-refresh browser dashboards and fully restart the Companion app so the
    frontend matches the new backend.

Example:

- action: voip_stack.call
  data:
    destination: Kitchen

Add device_id only when a non-default local HA phone, such as Reception, must
place the call:

- action: voip_stack.call
  data:
    destination: Kitchen
    device_id: <reception_phone_device_id>

:test_tube: Qualification

The release passes 1102 tests plus 99 subtests, together with Ruff,
JavaScript parsing, hassfest and HACS validation.

Real call qualification covered browser phones, ESP endpoints, registered SIP
accounts, ring groups, conferences, trunks, audio, bidirectional video,
re-INVITE, local/remote termination, dashboard media handoff and complete
post-call cleanup.

:package: Install or upgrade

Install or update VoIP Stack through HACS, restart Home Assistant, run
Reconfigure once and hard-refresh every dashboard.

This release is the point where the project stops being one clever intercom
and becomes a genuinely useful Home Assistant-native communications system.

Took a while to figure out the right config and a few restarts, but im amazed by the result. Thanks for the project :slight_smile:

1 Like

VoIP Stack 2026.9.0: A More Coherent Home Assistant Phone System And An ESPHome Videophone

VoIP Stack 2026.9.0 is now available through HACS.

This post contains the user-visible changes since stable 2026.8.0.

The short version:

  • Home Assistant now handles direct calls, trunks, registered clients, groups,
    conferences and forwarding through one coherent call model;
  • SIP and media negotiation are considerably more predictable across different
    endpoints and PBXs;
  • the dashboard phone can remember and switch its microphone, speaker and
    camera;
  • the phonebook follows the real availability of ESPHome devices and registered
    SIP clients;
  • ESP32-P4 can now operate as a complete bidirectional SIP videophone.
    Human interaction remains optional.

One phone system instead of several special cases

Calls placed from the Home Assistant dashboard, ESPHome devices, registered SIP
clients and trunks now follow the same central call model.

This also applies to forwarding, ring groups and conferences. Each destination
remains an individual call leg, but answer, cancellation, media changes,
hangup and final cleanup follow the same rules.

In everyday use this means fewer stale busy states, ghost calls, delayed
callbacks and immediate-redial failures. A failed member of a group no longer
needs a separate recovery path, and the first valid answer can consistently
win while the remaining phones stop ringing.

Better SIP and PBX interoperability

Trunk identity, authentication domain and outbound proxy are now treated as
separate concepts. UDP calls can reuse the registration flow when required by
the provider, while a configured proxy remains the network route without
becoming the public SIP identity.

The call lifecycle also preserves the correct dialog identity across INVITE,
authentication, ACK, re-INVITE, CANCEL and BYE.

The result is standards-based behavior rather than a collection of provider
specific fixes. Current qualification includes real PBX trunks, registered SIP
clients, direct ESP calls and Home Assistant browser phones.

Audio and video negotiate per endpoint

Each side of a call negotiates the media it actually supports.

Audio-only ESPHome devices are not offered irrelevant video. Compatible video
phones can start directly with video, while an established audio call can add
or remove video later through a normal in-dialog re-INVITE.

Rejecting a video change leaves the existing audio call active.

Home Assistant browser phones continue to support H.264, VP8 and RTP/JPEG.
Where a compatible direct format is unavailable, VoIP Stack can use its
bounded video conversion path instead of creating an unrelated second call.

The phonebook reflects real availability

Registered SIP clients appear only while they have a valid registration.
De-registration and Contact expiry remove them automatically.

ESPHome contacts follow device availability, while static contacts and Home
Assistant browser phones remain independent of SIP registration.

Phonebook delivery is also tracked per ESPHome device. Reconnecting one phone
restores that device without needlessly republishing the same roster to every
other endpoint.

DTMF follows the active call

RFC 4733 RTP events and compatible SIP INFO digits now follow the established
dialog and media bridge.

A digit entered from the dashboard, a registered SIP phone or an ESPHome device
reaches the endpoint participating in that call. Home Assistant can also expose
the same digit to automations, for example to open a gate during an intercom
call.

Better media controls in the Home Assistant card

Each browser phone can select and remember its preferred microphone, speaker
and camera from the card Options view.

The selected devices can also be changed while a call is active without
replacing the SIP session.

The card received additional protection against stale video frames, duplicated
browser ownership and media from a completed call appearing in the next one.
Caller and callee names now remain consistent between the active call and call
history.

Brazilian Portuguese and German translations are now included across the
integration, entities, repairs, services, card editor and phonebook.

ESPHome has a complete videophone now

The ESP32-P4 is no longer limited to sending its camera to Home Assistant.

It can transmit its local camera, receive the remote RTP video stream, decode
it and display the other party on its physical MIPI DSI panel while
bidirectional audio remains active.

This works for calls that begin with audio and video together, and for calls
that start as audio and enable video later. Video can be removed and restored
without restarting the call.

When the call ends, the P4 returns to its normal LVGL interface instead of
leaving a stale frame or broken navigation state.

Two separate firmware profiles are available:

  • JPEG, the stable full-device baseline;
  • H.264, experimental in this release.

The full JPEG profile combines bidirectional video with AFE echo cancellation,
Micro Wake Word, Voice Assistant, LVGL, TTS, HTTP media and Sendspin.

This is not only a successful SDP exchange or a browser preview. Qualification
also covered video presentation on the physical P4 panel, bidirectional audio,
hangup, immediate redial and repeated calls.

Smaller ESPHome improvements

ESPHome media paths reuse large buffers across playback and call cycles where
the hardware profile permits it. This reduces repeated allocation and memory
fragmentation when music, TTS, Voice Assistant and VoIP share the same device.

The compact touch interface can navigate contacts and dial extensions directly
from the device.

Existing audio profiles retain their established PCM transport and configured
sample rates. The P4 video work does not replace the proven audio backend.

Breaking change for the full P4 profile

The former profile:

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

Please review the complete breaking changes before updating a custom YAML.

Install or upgrade

In HACS, open VoIP Stack, select Redownload from the three-dot menu and
choose 2026.9.0.

Restart Home Assistant after the update, then refresh the browser dashboard or
restart the Companion app so the new card code is loaded.

If you test the release with a real SIP phone, video door station, PBX, provider
trunk or ESP32-P4, compatibility reports are very welcome. Please include the
call direction, endpoint models, SIP transport and negotiated codecs where
possible.

Special thanks to @jjhelin, @kuid87, @jftkcs and @DunklerPhoenix for supporting
the project.

2 Likes