Repository navigation
Feature: Using websockets for STT streaming - #31
Conversation
There was a problem hiding this comment.
Pull request overview
Adds optional WebSocket-based streaming for the STT subentry so audio can be sent incrementally (instead of base64-over-HTTP), while keeping existing HTTP/HTTPS behavior unchanged.
Changes:
- Add a WebSocket code path in the STT entity to stream audio chunks and receive a JSON transcription response.
- Refactor auth helpers to expose the base64 basic-auth credential string for reuse beyond HTTP headers.
- Extend config validation and documentation to describe/allow WebSocket STT usage.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| custom_components/webhook_conversation/stt.py | Implements WebSocket streaming branch for STT and factors response parsing into a helper. |
| custom_components/webhook_conversation/models.py | Adds a TypedDict for the initial STT WebSocket metadata payload. |
| custom_components/webhook_conversation/entity.py | Adds _get_basic_auth() helper and reuses it in _get_auth_headers(). |
| custom_components/webhook_conversation/config_flow.py | Updates webhook URL validation (currently allowing ws://) and minor schema formatting changes. |
| README.md | Documents STT-over-WebSocket payload shape and expected behavior. |
Comments suppressed due to low confidence (1)
custom_components/webhook_conversation/config_flow.py:305
- This URL validation allows
ws://for all subentry types, but only STT implements a WebSocket client. Configuring a conversation/ai_task/tts subentry withws://will later fail when the code tries toPOSTto it. Consider allowingws:///wss://only whenself._subentry_type == "stt"(and keep other types limited to http/https).
webhook_url: str = user_input[CONF_WEBHOOK_URL]
if (
not webhook_url.startswith("http://")
and not webhook_url.startswith("https://")
and not webhook_url.startswith("ws://")
):
_LOGGER.error("Invalid webhook URL: %s", webhook_url)
errors["base"] = "invalid_webhook_url"
if self._subentry_type in ("tts", "stt"):
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@tobiloeb Thanks for the contribution! Please consider the failing mypy check and the comments made by copilot. |
|
Good catches from Copilot. I refactored the websockets to aiohttp websockets. I like that because its standard in HA. I have tested the changes and everything is working (with and without basic auth). |
|
@tobiloeb Sorry I kinda forgot about this. Any reason for closing the PR other than not getting an answer/getting merged, or can I merge it? |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ( | ||
| not webhook_url.startswith("http://") | ||
| and not webhook_url.startswith("https://") | ||
| and not webhook_url.startswith("ws://") | ||
| and not webhook_url.startswith("wss://") | ||
| ): |
| async for chunk in stream: | ||
| await ws.send_bytes(chunk) | ||
|
|
| headers = {"Content-Type": "application/json"} | ||
|
|
||
| username, password = self._get_basic_auth() | ||
| if username and password is not None: |
|
|
||
| try: | ||
| username, password = self._get_basic_auth() | ||
| if username and password is not None: |
|
@copilot fix the remaining review comments, check mypy and ruff |
Agent-Logs-Url: https://github.com/EuleMitKeule/webhook-conversation/sessions/4d1322ed-2adc-4b17-90f2-31b28fcce94e Co-authored-by: EuleMitKeule <47421406+EuleMitKeule@users.noreply.github.com>
|
🎉 This PR is included in version 1.12.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Hi,
I really like your project and I am currently using it with n8n.
Currently, the integration doesn't stream the STT audio (because n8n can't handle it well), but other systems could. ;) And there are some custom n8n-nodes which provide websocket triggers. So, I extended your integration with the option to configure a ws:// STT endpoint. If a WebSocket is configured, the audio will be streamed. Nothing changes for existing users using http or https.
What do you think?
WebSockets doesn't provide a Basic Authentication header. I'm not sure about the default behavior for WebSocket authentication in HA — I've read about several options. My approach is to send the base64-encoded basic auth string with the other metadata information in the first WebSocket message.
I have tested my changes with the current HA Version 2026.2.2 and a small python Websocket server. Its working well and STT is now very fast. :)
If you have any questions or suggestions, let me know. I just thought that some others can benefit from streaming STT.
Regards,
Tobias