Skip to content

About

VoIP Stack for Home Assistant and ESPHome: SIP audio/video calls, dashboard phones, ESP32 intercoms, ring groups, trunks and call routing through HA automations.

Topics

Resources

Stars

264 stars

Watchers

3 watching

Forks

Latest commit

 

History

1,490 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

❤️ Support the future of this project

This project is developed and maintained by one person, as a private individual, with no company, commercial sponsor, or organization funding its development.

Until now, development tools, subscriptions, testing hardware and services have been paid entirely from my personal income.

With the rising cost of living and everyday expenses in Italy, continuing to personally absorb all of these costs has become financially unsustainable.

The project will remain free and open source. No features are being placed behind a paywall.

However, without more community support, development, testing, hardware support and bug fixing will inevitably have to slow down.

If this project is useful to you, please consider supporting its continued development:

Even a small contribution helps cover the real costs of keeping the project active.

You are not paying to unlock features. You are helping make continued development possible.

VoIP Stack for ESPHome and Home Assistant

Stable release: 2026.10.1. Requires Home Assistant 2026.7.0 or newer. Firmware builds require ESPHome 2026.9.0 or newer.

The updated firmware profiles use ESP VoIP Stack 2026.10.1, Runtime Controller 2026.10.1, and Audio Stack 2026.10.2 from their main branches. HA and ESP firmware do not need matching version numbers. Rebuilding ESP firmware is recommended to receive the updated AFE delivery and playback fixes; it is separate from updating HA through HACS.

See the 2026.10.1 changes and upgrade instructions.

Platform Home Assistant ESPHome

Turn ESPHome audio devices and Home Assistant into a local SIP phone system, or use the maintained full-experience firmware to combine VoIP with a complete ESPHome voice satellite.

ESP devices become standards-based SIP phones, with audio on every maintained VoIP profile and optional video on qualified ESP32-P4 profiles. Home Assistant can be a SIP video softphone, call router, RTP bridge, local registrar, conference focus, callable Assist destination and optional trunk endpoint. Browser phones, wall tablets, ESP room stations, standard SIP clients and an external PBX can share one phonebook without requiring a separate Asterisk or FreeSWITCH server for the normal home use case.

VoIP is only one part of the project. The optional full-experience ESP YAMLs also provide an independent on-device Voice Assistant, Micro Wake Word, media playback, TTS, Sendspin support, runtime audio controls and touch interfaces. That local assistant is not created or controlled by calling Assist over SIP.

The project therefore has three cooperating, independently useful surfaces:

Surface Runs on Purpose
ESP VoIP endpoint ESPHome device A standards-based SIP/RTP phone, with audio and optional qualified P4 video.
Home Assistant VoIP Stack Home Assistant Browser phones, PBX routing, registrar, bridges, groups, conferences, callable Assist and an optional trunk.
Full ESP experience ESPHome device A local voice satellite with wake word, Voice Assistant, media, TTS, optional Sendspin, runtime UI and VoIP.

Install only the surfaces you need. A VoIP-only ESP does not require the local Voice Assistant, and a full-experience ESP keeps its local assistant even when no SIP Assist extension is configured.

VoIP Stack dashboard and central phonebook

Dashboard demo

One dashboard can control a browser phone, an ESP endpoint and the shared phonebook. Each room phone still has its own identity and call state.


ESP to HA

SIP video

ESP Voice Assistant

ESP TTS response

Runtime audio controls
Support this project
If this work is useful to you, please consider a donation. It helps cover development tools, services and test hardware, which means better compatibility and fewer regressions for everyone.

Sponsor

Maintained ESP firmware profiles require ESPHome 2026.9.0 or newer. See the firmware migration notes when updating copied YAMLs. This does not force an immediate firmware update when installing the Home Assistant integration alone.

What can you build?

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

Goal What VoIP Stack provides Start here
Video doorbell A SIP video door station can ring a browser phone in a dashboard or Companion app. Standard ESP profiles remain audio-only; qualified ESP32-P4 profiles can also send and receive SIP video. SIP video · door-station recipe
Room-to-room calls Create a logical HA phone and dedicated dashboard view for each kiosk or tablet. Calls may be private audio or video. Logical phones
ESP room phones Flash one maintained VoIP YAML per room. ESPs can call names and extensions from the shared phonebook. Deployment guide
Full ESP voice device Flash a maintained full-experience YAML to combine a local Voice Assistant, Micro Wake Word, media, TTS, optional Sendspin and VoIP on one device. Full ESP experience
Existing SIP equipment Register Zoiper, Linphone, baresip, an IP phone or an ATA directly to HA. Local accounts
Ring groups Ring several eligible endpoints; the first answer wins and the losing branches are cancelled. Groups
Audio conferences Host a local audio conference in HA and optionally ring its members. Groups
Callable Assist Give a native Assist pipeline an extension and talk to it from ESP, SIP or trunk callers. Assist calls
External calls Connect an optional provider/PBX trunk using registration or source-IP authorization. SIP trunk
Contextual routing Use native HA entities, conditions and services for presence, schedules, no-answer forwarding and in-call DTMF. Automation cookbook

Fastest start

  1. Install VoIP Stack from HACS and restart Home Assistant.
  2. Add VoIP Stack from Settings → Devices & services.
  3. Keep SIP 5060 and RTP base 40000 unless they conflict with your network.
  4. Choose a maintained YAML under yamls/ and adapt only its substitutions, pins and secrets.
  5. Add the flashed device through the normal ESPHome integration.
  6. Add the VoIP Stack card to a dashboard and select the intended phone Device.
  7. Call the phonebook name shown by the card or ESP.

For one ESP intercom, that is enough. Local SIP accounts, multiple browser phones, callable Assist and a trunk are optional PBX layers. The full ESP experience is a separate firmware choice, not another PBX requirement.

Device goal Maintained starting point
ESP VoIP only yamls/voip-only/
Local Voice Assistant + MWW + media + TTS + optional Sendspin + VoIP yamls/full-experience/
Native ESPHome mic/speaker paths yamls/voip-only/esphome-native/
New or unqualified hardware yamls/experimental/

The user guide continues from installation through cards, calls, SIP accounts, groups, Assist, trunks and diagnostics. The deployment guide explains how to choose between single-bus, dual-bus, lightweight AEC and full AFE profiles.

How it works

Home Assistant as a local SIP and PBX hub

The system has one call model and four main surfaces:

  • ESP endpoint: A lightweight SIP/SDP/RTP phone with a microphone, speaker or both.
  • Home Assistant runtime: Logical browser phones, routing, media bridges, groups, local registration, Assist and the optional trunk.
  • Central phonebook: Names, extensions, groups, registered clients, routable SIP endpoints and external numbers.
  • Lovelace card: A UI bound to one phone Device; it projects backend state and invokes normal HA services instead of running a second call controller.

SIP dialogs, transactions and transports have separate lifecycles. Logical phones share the listener and RTP pool, so creating another room phone does not open another SIP server. Each phone owns at most one active call; calls to different phones remain independent.

The detailed ownership and media model is in docs/ARCHITECTURE.md. Complete peer-to-peer and HA-bridged sequences are in docs/CALL_FLOWS.md.

Logical Home Assistant phones

Experimental native Companion phones are separate from dashboard phones and require a compatible Companion build.

The integration creates one ordinary Home Assistant browser phone on first setup, named from Home Assistant's location. Add or remove phones from:

Settings → Devices & services → VoIP Stack → Add phone → Home Assistant browser phone

Give every real place its own name and optional extension: Kitchen, Reception, Garage, 201, and so on. Each logical phone is represented by a native HA Device with entities for call state, connectivity, DND, extension, groups, auto answer, camera transmission settings and call events.

Bind the card to that Device:

type: custom:voip-stack-card
mode: ha_softphone
device_id: <phone_device_id>

device_id answers "which local phone owns this card or action?". destination answers "who should this phone call?". The central phonebook resolves the destination, so a normal call does not require the destination's Device ID:

action: voip_stack.call
data:
  device_id: <kitchen_phone_device_id>
  destination: Garage

Omit device_id only when a preferred phone is configured or exactly one compatible phone exists. Otherwise the action asks you to select the local phone explicitly.

The card's idle Options panel includes a Microphone anti-alias filter. It is enabled by default and stored per browser and logical phone. The setting takes effect when the next call opens the microphone and only adds processing when the negotiated transmit rate is lower than the browser capture rate.

The same panel selects the browser microphone, speaker and camera. These preferences belong to the browser or Companion App session, are shared by all VoIP Stack cards in that session and remain unchanged when no device is selected. During a call, the tune button beside Hangup opens the same controls, so a headset or camera can be changed without ending the call. Unsupported speaker routing remains under operating-system control.

Each room-to-room media endpoint needs a distinct browser or Companion session. Two cards in one browser tab can display two phones, but one tab still owns one physical microphone, speaker and camera pipeline.

ESP endpoints and media roles

ESP media roles are derived from the configured components; they are not a separate user mode.

Derived role Media Typical use
full_duplex microphone TX + speaker RX Room phone, door station, wall panel
mic_only microphone TX Monitor or capture endpoint
speaker_only speaker RX Paging or announcement target

An endpoint must have at least one real media direction. ESP VoIP intentionally uses uncompressed PCM for audio. Standard profiles are audio-only; qualified ESP32-P4 videophone profiles compile exactly one video codec, JPEG or H.264. HA performs format conversion when a standard SIP peer negotiates another supported audio codec; ESP firmware is not downgraded to a telephone codec for that purpose.

Audio component details live in the companion projects:

Full ESP voice experience

The yamls/full-experience/ profiles are complete ESPHome voice devices, not merely larger SIP configurations. They combine the VoIP endpoint with an independent local Voice Assistant stack and coordinate all realtime consumers through one audio and runtime ownership model.

The underlying audio stack is also reusable without VoIP. Custom ESPHome voice devices can use it to share codec or I2S ownership, speaker reference, AEC/AFE processing and a cleaned microphone stream between their own consumers.


Animated assistant

Assistant response

Runtime audio controls

Call end reason

Positive mood

Neutral mood

Negative mood

AFE controls in HA

P4 weather, Voice Assistant and VoIP controls

Ducking and barge-in

The full profiles provide:

  • continuous Micro Wake Word on the cleaned post-AEC microphone stream;
  • a native ESPHome Voice Assistant started by wake word or touch;
  • media playback, announcements, TTS, ringtones and optional Sendspin through one shared speaker path;
  • ducking and barge-in, including interruption of a current assistant reply;
  • VoIP calls that coexist with the assistant instead of creating a second microphone or speaker owner;
  • AEC or AFE processing, with runtime controls and diagnostics where supported;
  • coordinated LEDs, display pages, timers, call state and media activity through runtime_controller;
  • headless operation on audio boards, plus full LVGL interfaces on supported displays;
  • optional animated and mood-aware assistant artwork on display profiles.

The shared pipeline matters because Micro Wake Word, Voice Assistant and VoIP all need the same cleaned user speech while music, TTS or a ringtone may still be playing. Speaker output also supplies the phase-coherent reference used by AEC instead of letting each feature open its own audio path.

Shared music, TTS, wake word, Voice Assistant and VoIP audio pipeline

Assistant artwork and avatars

Display profiles can select an assistant avatar with the ai_avatar substitution. Each avatar directory may provide idle animation frames plus listening, thinking, loading, error, timer and mood images. The selected assets are resized for the target display during the build.

substitutions:
  ai_avatar: my_assistant

An optional community theme is also included: starfleet, contributed by rvdv01 in discussion #110. Set ai_avatar: starfleet in your own configuration to use it. Maintained YAMLs keep their current default. See the theme preview and optional ringtone.

This artwork represents the ESP device's own Voice Assistant state. It is unrelated to the optional HA Assist pipeline that SIP callers can dial as an extension.

See the deployment guide for profile selection and the companion audio stack documentation for AEC, AFE, I2S and codec topology details.

Home Assistant as a SIP video phone

Video is available to compatible browser phones in current browsers and the Home Assistant Companion app. Standard SIP video door stations, video phones, softphones and PBX/trunk legs can negotiate H.264, VP8 or RTP/JPEG. An optional bounded FFmpeg path can receive selected legacy codecs and bridge incompatible H.264/JPEG SIP legs when direct encoded relay is impossible.

Receiving video does not require camera permission. Sending the browser camera is a separate persisted phone setting and still requires browser permission. Audio remains usable when video is unavailable or deliberately disabled.

Audio-only ESP endpoints and audio conferences remain audio-only. Qualified ESP32-P4 videophone profiles can negotiate RTP/JPEG or H.264 directly, while the full P4 profile supports bidirectional RTP/JPEG. These are complete display endpoints, not camera-only devices: the P4 can transmit its camera, receive the remote RTP video stream, decode it through the selected JPEG or H.264 path and present the other party on its own MIPI DSI panel while bidirectional audio remains active. After video is removed or the call ends, the normal LVGL interface is restored.

Video compatibility depends on the actual offer/answer, packetization and decoder contract, not only on a codec name printed on a product page. See the video guide for the separate outgoing camera path, incoming decode and panel presentation path, initial-video and audio-first re-INVITE behavior, and the JPEG/H.264 compile-time profiles.

See the capability matrix, privacy controls and limits.

Phonebook and routing

Home Assistant publishes the shared roster through sensor.voip_phonebook. It combines:

  • online ESPHome VoIP endpoints;
  • logical Home Assistant phones;
  • registered local SIP accounts;
  • manual contacts;
  • Assist destinations;
  • dynamic ring/conference groups;
  • optional trunk-routed numbers.

A name is the contact identity. An extension is an internal alias for that same destination; a number is normally routed through the trunk. The resolver can also handle canonical SIP URIs.

Phonebook names must be unique across phones, contacts and Assist pipelines, even when their extensions differ. Duplicate names produce an error log and a persistent Home Assistant notification identifying the conflicting entries. Rename one destination; the notification clears when the phonebook updates.

SIP routing identity and presentation identity remain separate. ESPHome node names and account usernames provide stable URI users, while friendly names are sent as standard SIP display names with spaces preserved. Incoming caller text comes from the peer's From header, and the answering endpoint can publish its resolved name through RFC 4916 connected identity.

Use the card, voice intents or voip_stack.call with a phonebook name or extension. Do not copy endpoint addresses into automations unless you deliberately need a raw SIP route.

Central phonebook and endpoint resolution

Groups

Ring groups and conference groups

A ring group forks one call to all eligible members. DND, disabled and busy members are excluded; the caller is excluded if it belongs to the target group. The first successful answer wins and every losing leg is cancelled.

An audio conference group joins answered members to one HA-hosted mixer. conference_ring optionally rings the declared members when somebody joins. Auto answer is a per-phone policy: enabling it on several group members means several endpoints may join or compete immediately, which is the configured behavior.

Membership declared by a phone becomes visible in HA dynamically. A group disappears when no current endpoint declares it. See docs/GROUPS.md for declaration and collision rules.

Assist as a phone extension

There are two separate Assist-related features:

Feature Where it runs How it starts
ESP Voice Assistant On a full-experience ESP device Local wake word, touch control or an ESPHome action.
Callable HA Assist In Home Assistant through VoIP Stack A SIP caller dials its phonebook name or extension.

Enable Include voice assistant while configuring VoIP Stack, choose the pipeline and assign an extension. ESPs, registered SIP phones, browser phones and trunk callers can then call that Assist pipeline like any other contact.

This is a Home Assistant PBX feature. The SIP caller talks to the selected HA Assist pipeline over the call. It does not start, replace or change the local Voice Assistant running on a full-experience ESP device.

VoIP Stack sends one initial user message such as Incoming SIP call from "Daniele". and then streams the selected pipeline's STT, conversation and TTS over the same call. It does not inject a second persistent personality prompt. Put behavioral instructions in the conversation agent itself.

Optional advanced call context appends caller ID, phonebook match, ingress and called extension once. Treat those fields as untrusted call metadata, not authentication.

Voice intents may also resolve commands such as "Call Kitchen", "Answer" and "Hang up" against the live phonebook and the satellite's selected phone.

Door station and unanswered calls

Assist answers an unattended doorbell call

A typical path is:

  1. a door station calls Front door;
  2. a ring group alerts selected browser, SIP and ESP phones;
  3. the first endpoint to answer owns the call;
  4. if nobody answers, a native HA automation forwards the still-live call to another phone or Assist;
  5. call events can trigger a mobile notification or another HA action.

Copyable, current recipes:

The assistant's personality is entirely up to your prompt. Professional receptionist and verbally abusive domestic secretary are both technically valid configurations.

Automations as dialplan

Automations as dialplan lets you define call behavior in Home Assistant's normal automation editor. Create an Automation contact, then build a sequence: greeting, then forward to a phone or voice assistant. Add a keypad menu, presence condition or office-hours rule when you need it.

Phonebook as dialplan remains the default when no routing automation overrides it. Native VoIP triggers select the call for the actions automatically, including across waits and synchronous scripts. No blueprint, generic event filter or Call-ID template is needed for the common examples. A destination can be its phonebook name or extension.

Start with the step-by-step greeting, then add a forward after the greeting. These native automation features are included in 2026.10.0; they are not part of 2026.9.2.

Explicit extension digits entered during the trunk's initial DTMF menu retain precedence over a generic routing override. With no applicable automation selection, the configured phonebook route continues. Existing Event Entity and state automations remain available; see the migration guide.

The full Automations as dialplan cookbook explains call completion, fallback, time limits, concurrent callers and troubleshooting.

Optional SIP trunk

The trunk is disabled by default. Enable it to connect HA to a provider or another PBX. Keep Register the trunk enabled for account registration, or disable it for a static trunk and configure the allowed incoming SIP source IPs.

Inbound mode can route immediately or collect an internal extension through negotiated RTP telephone-event/compatible SIP INFO DTMF. Outbound contacts with public numbers use the same trunk. Explicit digits, no-digit fallback and automation overrides have distinct, documented precedence.

See docs/SIP_TRUNK.md before exposing the listener beyond a trusted network.

Installation

Home Assistant through HACS

  1. Search for VoIP Stack in HACS.
  2. Open the integration and select Download.
  3. Restart Home Assistant.
  4. Open Settings → Devices & services → Add integration.
  5. Select VoIP Stack and complete the config flow.

Install VoIP Stack from HACS

The card is registered automatically. A normal LAN can keep SIP 5060 and RTP base 40000. Container, LXC, VPN and multi-subnet installs may need an explicit reachable Advertise host and host networking.

Manual source and release-archive installation, port requirements and network topologies are documented in the deployment guide.

ESPHome components

Use the maintained YAML whenever possible. A minimal custom external-component declaration is:

external_components:
  - source: github://n-IA-hane/esphome-voip-stack@main
    components: [voip_stack]
  - source: github://n-IA-hane/esphome-audio-stack@main
    components: [esp_audio_stack, esp_aec]

Replace esp_aec with esp_afe only when the profile actually uses the full AFE pipeline. All maintained YAMLs point to the stable main branches.

After a major ESPHome or component upgrade, clear that device's ESPHome build cache before compiling. The deployment guide contains the complete component and cache instructions.

Upgrading

This project is maintained by one person and major releases may make deliberate breaking changes. Maintaining old and new call engines or service semantics in parallel is not sustainable; new features can require updates to automations, dashboards, config entries or custom ESPHome YAML.

Before every upgrade:

  1. read docs/BREAKING_CHANGES.md and the release note;
  2. update through HACS and restart HA;
  3. run Reconfigure on the VoIP Stack integration and review every step;
  4. verify phone/routing automations;
  5. reset the frontend cache on dashboards or Companion sessions using the card;
  6. clear the ESPHome build cache before rebuilding firmware after package changes.

Never assume an automation still has the same contract merely because the integration loaded successfully.

What's new in 2026.10.1

Static SIP trunks can now operate without registration, with explicit allowed incoming source IPs. Remote ESP phonebooks reuse HA's connected ESPHome service identity. SIP interoperability fixes preserve audio through one-way video direction conflicts, and translated card buttons grow to fit their labels.

The Waveshare 1.85C-BOX V2 gains an experimental FULL profile with dual microphones, AFE/AEC, voice features, calls, media and the circular touch UI. The coordinated Audio Stack update delivers processed AFE samples without waiting for another input iteration. Playback also includes the upstream mixer restart correction and additional queue diagnostics.

See the release notes for photographs, validation details and update instructions.

Previous release: 2026.10.0

  • Native call triggers, conditions and actions make greetings, forwarding, unanswered-call rules and DTMF menus available in HA's normal automation editor.
  • ESP phones receive their HA controls and phonebook through the VoIP component, without the retired VoIP HA packages.
  • Modular full profiles preserve paused music and handle interrupted replies, ringtones and overlapping voice/media activity more consistently.
  • P4 video changes during calls preserve the negotiated media path; on-device labels distinguish Direct from HA transcoding.
  • Audio and VoIP diagnostic actions help capture a useful issue report without enabling verbose audio tracing.

See the complete changelog for this release and earlier releases, and the breaking changes before updating custom YAMLs. A HACS update changes HA and the card; ESP improvements require a firmware rebuild.

Supported hardware

Ready profiles are examples of complete pin, codec and resource choices; they are not a claim that every board with the same chip has the same wiring.

Device/profile Configuration Status
Spotpear Ball v2 spotpear-ball-v2-full-afe.yaml Field tested
Waveshare ESP32-S3 Audio Board waveshare-s3-full-afe.yaml Field tested
Waveshare ESP32-P4 Touch LCD, full JPEG videophone waveshare-p4-touch-full-afe-landscape-videophone-jpeg.yaml Field tested
Waveshare ESP32-P4 Touch LCD, portrait waveshare-p4-touch-full-afe-portrait.yaml Experimental layout
Generic ESP32-S3, single bus generic-s3-full-aec.yaml Reference profile
Generic ESP32-S3, single bus, 4 MB flash generic-s3-full-lite-aec.yaml Experimental; limited OTA headroom
Generic ESP32-S3, dual bus generic-s3-full-aec.yaml Reference profile
Native ESPHome mic/speaker generic-s3-full-esphome-native.yaml Reference profile

The complete hardware, memory and C6 firmware notes are in the deployment guide.

The Generic Full Lite AEC profile keeps Voice Assistant, wake word, software AEC, VoIP, HTTP playback, TTS, timers and the runtime controller. It uses size optimization and leaves Sendspin disabled. PSRAM is still required. Its measured OTA image is about 1.78 MB, leaving roughly 59 KB in the standard 4 MB flash layout; check the build size again after adding components or updating dependencies. The full 8 MB profile retains Sendspin and more flash headroom.

Documentation

For custom firmware composition, see Modular device packages.

Start with the practical user guide for normal setup and daily operation. Use the automation cookbook for redirect, fallback, DTMF and guarded concurrent routing, and the SIP feature reference for the established SIP and PBX capabilities.

Topic Document
Choose and install a profile Deployment guide
Upgrade safely Breaking changes
Services, selectors and side effects Home Assistant services
Automations and contextual routing Automation cookbook
Ring and conference groups Groups
SIP video codecs and browser privacy SIP video
Provider/PBX registration SIP trunk
Names, extensions and route precedence Dial-plan resolver
ESP/HA phonebook representation Phonebook protocol
Expected signaling and media paths Call flows
Runtime ownership and architecture Architecture
Every option, trigger and condition Reference
Logs, captures and qualification Testing and debug
Common failures Troubleshooting
All documentation Documentation index

Testing

The repository maintains more than 1,100 automated tests plus real SIP, RTP, browser, trunk and hardware qualification tools. A green unit suite is not treated as proof of a complete call: release qualification also checks media in both directions, remote/local hangup and final resource cleanup.

Developer commands and capture locations are in docs/TESTING_AND_DEBUG.md.

Troubleshooting

Start with docs/troubleshooting.md. It covers:

  • an ESP or browser phone that does not ring;
  • unknown callers or route failures;
  • 488 media_incompatible;
  • missing or one-way audio;
  • SIP registration/trunk failures;
  • hold, UPDATE and re-INVITE;
  • stale card state or frontend cache.

For SIP call setup or hangup problems, the voip_stack.capture_sip action can produce a Wireshark-readable trace directly from HA, including HA OS, without SSH or tcpdump. Start it, reproduce the problem, then stop and download the PCAP from the action response. See the step-by-step SIP capture guide for examples, memory limits and what the trace can diagnose. Requires a release containing this action.

Before opening an issue

Report the parts you actually use. If the issue involves only HA, browser cards or SIP equipment without an ESP, provide the HA-side information below and skip the ESP requirements. ESP dumps apply only to ESP-related faults; Audio Diagnostics additionally requires Audio Stack on that device.

Reproduce the issue with the current maintained release/profile and report the exact versions actually running, including ESP firmware when an ESP is involved. An updated YAML on your computer does not update a device until it is rebuilt and uploaded.

Include:

  • Steps to reproduce, expected behavior, actual behavior and how often it happens.
  • HA and VoIP Stack versions; for ESP devices, ESPHome and component tags/commits.
  • Exact board, microphone/speaker and codec models, relevant YAML and custom wiring.
  • The call path: who calls whom, directly or through HA, SIP UDP/TCP, and PBX or peer software/version. Include negotiated codecs and ptime if known.
  • HA integration diagnostics and logs around the failure, plus the ESP boot log.
  • For an updated ESP profile, complete VoIP Diagnostics log output during the fault and after hangup. Add Audio Diagnostics when using Audio Stack. Open the ESPHome logs before pressing the buttons, use INFO or a more verbose logger level, and include whole diagnostic blocks, not only the last line.
  • A SIP capture for HA-handled signaling problems. It does not capture RTP media or SIP exchanged directly between ESP devices. Further captures may be needed for those paths.

To request an ESP dump from HA, open Developer Tools > Actions, select Button: Press (button.press) and choose that device's VoIP Diagnostics or Audio Diagnostics button. Open the ESPHome device logs first: the dump is printed there, not returned by the HA action. For missing buttons in custom firmware, use the YAML definitions and rebuild/upload. The voip_stack.dump_diagnostics and esp_audio_stack.dump_diagnostics names are ESPHome actions, not HA services.

For audio faults, state which direction is silent or distorted. For video faults, state whether the call began with video or video was enabled later. For custom Audio Stack hardware, include whether the problem persists with AEC/AFE disabled and whether the bus is shared or split, if you can test those cases.

Use this structure, replacing the example details with what you observed:

Title: ESP receives audio but the browser caller hears silence
Versions: [exact installed HA, integration, ESPHome and component versions]
Hardware: [board, microphone, speaker, codec and relevant wiring]
Call path: HA browser card -> Generic S3, through HA, SIP UDP
Steps: call, answer, speak in both directions, hang up from HA
Expected: bidirectional audio and both endpoints idle after hangup
Actual: ESP plays audio; browser hears silence; hangup works
Frequency and test time: [repetitions, timestamp and timezone]
Attachments: sanitized YAML, HA diagnostics, HA/ESP logs, full diagnostic blocks,
             and a SIP capture when relevant

Never publish SIP passwords, authentication data, API keys or tokens. Review configuration files, logs and captures before attaching them.

If you ignore these instructions and open an "it does not work" issue without reproduction details or supporting logs, I'll get pissed off like there's no tomorrow and close it as incomplete.

Support the project

If this work is useful, consider sponsoring it on GitHub. Donations help cover development tools, services and test hardware.

For bug reports and hardware feedback, follow the issue-reporting instructions above.

Contributing

Contributions should preserve standards-based SIP/SDP/RTP behavior and the single authoritative call lifecycle. Avoid endpoint-specific timing workarounds when a transaction, dialog, media or ownership invariant can solve the underlying problem.

Before submitting a change, run the repository test environment documented in docs/TESTING_AND_DEBUG.md.

AI-assisted contributions

Vibe coding is welcome here. I support AI-assisted development and consider it an invaluable tool, provided it is used thoughtfully.

Asking an AI to "add this feature" or "fix this bug" and submitting the result is not enough. A change may solve the immediate problem while introducing regressions elsewhere, especially in a project where audio, video and call handling share limited resources.

Understand the proposed changes, review their wider effects, and test the affected functionality before opening a pull request. Explain what you tested and what remains unverified. AI can help write the code, but careful review and testing remain the contributor's responsibility.

License

Project-owned code is licensed under the MIT License; see LICENSE.

External Espressif components and optional system codecs keep their own licenses. They are consumed as upstream dependencies and are not copied into the project license.

Note

VoIP Stack is an enthusiast open-source project maintained primarily by one person. It is designed for trusted home and laboratory networks, not as an emergency telephone service.

About

VoIP Stack for Home Assistant and ESPHome: SIP audio/video calls, dashboard phones, ESP32 intercoms, ring groups, trunks and call routing through HA automations.

Topics

Resources

Stars

264 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages