mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 01:46:11 -04:00
Return the requested format for OpenAI TTS (#169839)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
Paulus Schoutsen
co-authored by
Copilot Autofix powered by AI
parent
c12e1b5f4a
commit
c5e08b2409
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
from openai import OpenAIError
|
||||
from propcache.api import cached_property
|
||||
@@ -166,14 +166,15 @@ class OpenAITTSEntity(TextToSpeechEntity, OpenAIBaseLLMEntity):
|
||||
client = self.entry.runtime_data
|
||||
|
||||
response_format = options[ATTR_PREFERRED_FORMAT]
|
||||
if response_format not in self._supported_formats:
|
||||
# common aliases
|
||||
if response_format == "ogg":
|
||||
response_format = "opus"
|
||||
elif response_format == "raw":
|
||||
response_format = "pcm"
|
||||
else:
|
||||
response_format = self.default_options[ATTR_PREFERRED_FORMAT]
|
||||
if response_format in ("ogg", "oga"):
|
||||
codec: Literal["mp3", "opus", "aac", "flac", "wav", "pcm"] = "opus"
|
||||
elif response_format == "raw":
|
||||
response_format = codec = "pcm"
|
||||
elif response_format not in self._supported_formats:
|
||||
response_format = self.default_options[ATTR_PREFERRED_FORMAT]
|
||||
codec = response_format
|
||||
else:
|
||||
codec = response_format
|
||||
|
||||
try:
|
||||
async with client.audio.speech.with_streaming_response.create(
|
||||
@@ -182,7 +183,7 @@ class OpenAITTSEntity(TextToSpeechEntity, OpenAIBaseLLMEntity):
|
||||
input=message,
|
||||
instructions=str(options.get(CONF_PROMPT)),
|
||||
speed=options.get(CONF_TTS_SPEED, RECOMMENDED_TTS_SPEED),
|
||||
response_format=response_format,
|
||||
response_format=codec,
|
||||
) as response:
|
||||
response_data = bytearray()
|
||||
async for chunk in response.iter_bytes():
|
||||
|
||||
@@ -118,6 +118,79 @@ async def test_tts(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("preferred_format", "expected_response_format"),
|
||||
[
|
||||
("ogg", "opus"),
|
||||
("oga", "opus"),
|
||||
("mp3", "mp3"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_init_component")
|
||||
async def test_tts_preferred_format(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
mock_create_speech: MagicMock,
|
||||
calls: list[ServiceCall],
|
||||
preferred_format: str,
|
||||
expected_response_format: str,
|
||||
) -> None:
|
||||
"""Test text to speech preferred format handling."""
|
||||
mock_create_speech.return_value = [b"mock audio data"]
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"speak",
|
||||
{
|
||||
ATTR_ENTITY_ID: "tts.openai_tts",
|
||||
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
tts.ATTR_OPTIONS: {tts.ATTR_PREFERRED_FORMAT: preferred_format},
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
assert (
|
||||
await retrieve_media(hass, hass_client, calls[0].data[ATTR_MEDIA_CONTENT_ID])
|
||||
== HTTPStatus.OK
|
||||
)
|
||||
mock_create_speech.assert_called_once_with(
|
||||
model="gpt-4o-mini-tts",
|
||||
voice="marin",
|
||||
input="There is a person at the front door.",
|
||||
instructions="",
|
||||
speed=1.0,
|
||||
response_format=expected_response_format,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init_component")
|
||||
async def test_tts_raw_preferred_format_returns_pcm(
|
||||
hass: HomeAssistant,
|
||||
mock_create_speech: MagicMock,
|
||||
) -> None:
|
||||
"""Test raw preferred format is returned as pcm."""
|
||||
tts_entity = hass.data[tts.DOMAIN].get_entity("tts.openai_tts")
|
||||
mock_create_speech.return_value = [b"mock audio data"]
|
||||
|
||||
result = await tts_entity.async_get_tts_audio(
|
||||
"There is a person at the front door.",
|
||||
"en-US",
|
||||
{tts.ATTR_PREFERRED_FORMAT: "raw", tts.ATTR_VOICE: "marin"},
|
||||
)
|
||||
|
||||
assert result == ("pcm", b"mock audio data")
|
||||
mock_create_speech.assert_called_once_with(
|
||||
model="gpt-4o-mini-tts",
|
||||
voice="marin",
|
||||
input="There is a person at the front door.",
|
||||
instructions="",
|
||||
speed=1.0,
|
||||
response_format="pcm",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init_component")
|
||||
async def test_tts_error(
|
||||
hass: HomeAssistant,
|
||||
|
||||
Reference in New Issue
Block a user