mirror of
https://github.com/home-assistant/core.git
synced 2026-09-25 17:04:04 -04:00
Use iter_chunked for STT audio stream to prevent LineTooLong (#180831)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot Autofix powered by AI
parent
0a8ac8ab5a
commit
a293744b78
@@ -72,6 +72,11 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
|
||||
|
||||
# Audio is read from the request body in chunks of at most 4096 bytes because
|
||||
# line-based iteration raises LineTooLong on binary audio without newline bytes.
|
||||
# At 16 kHz/16-bit/mono, 4096 bytes represents up to 128 ms of audio.
|
||||
AUDIO_CHUNK_SIZE = 4096
|
||||
|
||||
|
||||
@callback
|
||||
def async_default_engine(hass: HomeAssistant) -> str | None:
|
||||
@@ -291,7 +296,7 @@ class SpeechToTextView(HomeAssistantView):
|
||||
|
||||
# Process audio stream
|
||||
result = await stt_provider.async_process_audio_stream(
|
||||
metadata, request.content
|
||||
metadata, request.content.iter_chunked(AUDIO_CHUNK_SIZE)
|
||||
)
|
||||
else:
|
||||
# Check format
|
||||
@@ -300,7 +305,7 @@ class SpeechToTextView(HomeAssistantView):
|
||||
|
||||
# Process audio stream
|
||||
result = await provider_entity.internal_async_process_audio_stream(
|
||||
metadata, request.content
|
||||
metadata, request.content.iter_chunked(AUDIO_CHUNK_SIZE)
|
||||
)
|
||||
|
||||
# Return result
|
||||
|
||||
@@ -644,3 +644,33 @@ async def test_audio_processing_custom(hass: HomeAssistant, tmp_path: Path) -> N
|
||||
assert engine.audio_processing.requires_external_vad is False
|
||||
assert engine.audio_processing.prefers_auto_gain_enabled is False
|
||||
assert engine.audio_processing.prefers_noise_reduction_enabled is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"setup", ["mock_setup", "mock_config_entry_setup"], indirect=True
|
||||
)
|
||||
async def test_stream_audio_large_no_newline_block(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
setup: MockSTTProvider | MockSTTProviderEntity,
|
||||
) -> None:
|
||||
"""Test a newline-free audio stream larger than aiohttp's line limit."""
|
||||
# 600,000 bytes of silence - larger than the 512KB LineTooLong threshold.
|
||||
# This is the reproduction case from issue #180708.
|
||||
test_data = b"\x00" * 600_000
|
||||
client = await hass_client()
|
||||
response = await client.post(
|
||||
f"/api/stt/{setup.url_path}",
|
||||
headers={
|
||||
"X-Speech-Content": (
|
||||
"format=wav; codec=pcm; sample_rate=16000; bit_rate=16; channel=1;"
|
||||
" language=en"
|
||||
)
|
||||
},
|
||||
data=test_data,
|
||||
)
|
||||
assert response.status == HTTPStatus.OK
|
||||
assert await response.json() == {"text": "test_result", "result": "success"}
|
||||
|
||||
received_data = b"".join(setup.received)
|
||||
assert received_data == test_data
|
||||
|
||||
Reference in New Issue
Block a user