Implement API URL resolution for OpenAICompatibleTTSService to handle both base and full speech endpoint formats.

This commit is contained in:
Xin Wang
2026-02-26 11:07:54 +08:00
parent 1bcf625f86
commit 14b4b3d966

View File

@@ -10,6 +10,7 @@ import os
import asyncio
import aiohttp
from typing import AsyncIterator, Optional
from urllib.parse import urlparse, urlunparse
from loguru import logger
from services.base import BaseTTSService, TTSChunk, ServiceState
@@ -74,10 +75,35 @@ class OpenAICompatibleTTSService(BaseTTSService):
self.api_key = api_key or os.getenv("TTS_API_KEY") or os.getenv("SILICONFLOW_API_KEY")
self.model = model
self.api_url = api_url or os.getenv("TTS_API_URL") or "https://api.siliconflow.cn/v1/audio/speech"
raw_api_url = api_url or os.getenv("TTS_API_URL") or "https://api.siliconflow.cn/v1/audio/speech"
self.api_url = self._resolve_speech_endpoint(raw_api_url)
self._session: Optional[aiohttp.ClientSession] = None
self._cancel_event = asyncio.Event()
@staticmethod
def _resolve_speech_endpoint(api_url: str) -> str:
"""
Accept either:
- base URL: https://host/v1
- full speech endpoint: https://host/v1/audio/speech
and always return the final speech endpoint URL.
"""
raw = str(api_url or "").strip()
if not raw:
return "https://api.siliconflow.cn/v1/audio/speech"
parsed = urlparse(raw)
path = (parsed.path or "").rstrip("/")
if path.endswith("/audio/speech"):
return raw
if not path:
new_path = "/audio/speech"
else:
new_path = f"{path}/audio/speech"
return urlunparse(parsed._replace(path=new_path))
async def connect(self) -> None:
"""Initialize HTTP session."""