Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: make install-dev
run: make install-dev-rt
- name: Lint RT SDK
run: make lint-rt
- name: Test RT SDK
Expand All @@ -42,7 +42,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: make install-dev
run: make install-dev-batch
- name: Lint Batch SDK
run: make lint-batch
- name: Test Batch SDK
Expand All @@ -62,7 +62,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: make install-dev
run: make install-dev-flow
- name: Lint Flow SDK
run: make lint-flow
- name: Test Flow SDK
Expand All @@ -82,7 +82,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: make install-dev
run: make install-dev-voice
- name: Lint Voice Agent SDK
run: make lint-voice
- name: Test Voice Agent SDK
Expand All @@ -102,7 +102,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: make install-dev
run: make install-dev-tts
- name: Lint TTS SDK
run: make lint-tts
- name: Test TTS SDK
Expand Down
23 changes: 22 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
.PHONY: type-check-all type-check-rt type-check-batch type-check-flow type-check-tts type-check-voice
.PHONY: build-all build-rt build-batch build-flow build-tts build-voice
.PHONY: clean-all clean-rt clean-batch clean-flow clean-tts clean-voice
.PHONY: install-dev install-dev-rt install-dev-batch install-dev-flow install-dev-tts install-dev-voice


help:
Expand Down Expand Up @@ -145,13 +146,33 @@ type-check-voice:
cd sdk/voice/speechmatics && mypy .

# Installation targets
install-dev:
#
# voice depends on speechmatics-rt>=0.5.3; the local rt package's own dev version (0.0.0)
# never satisfies that, so pip silently replaces the editable rt install with a published
# PyPI wheel the moment voice[dev] installs after it. rt must always be the LAST install
# in any sequence that also installs voice, so the local editable copy is what's left active.
install-dev: install-dev-batch install-dev-flow install-dev-tts install-dev-voice install-dev-rt

install-dev-rt:
python -m pip install --upgrade pip
python -m pip install -e sdk/rt[dev]

install-dev-batch:
python -m pip install --upgrade pip
python -m pip install -e sdk/batch[dev]

install-dev-flow:
python -m pip install --upgrade pip
python -m pip install -e sdk/flow[dev]

install-dev-tts:
python -m pip install --upgrade pip
python -m pip install -e sdk/tts[dev]

install-dev-voice:
python -m pip install --upgrade pip
python -m pip install -e sdk/voice[dev]
python -m pip install -e sdk/rt
Comment thread
giorgosHadji marked this conversation as resolved.

install-build:
python -m pip install --upgrade build
Expand Down
31 changes: 21 additions & 10 deletions sdk/rt/speechmatics/rt/_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from ._base_client import _BaseClient
from ._exceptions import AudioError
from ._exceptions import TimeoutError
from ._exceptions import TranscriptionError
from ._logging import get_logger
from ._models import AudioEncoding
from ._models import AudioEventsConfig
Expand Down Expand Up @@ -39,6 +38,9 @@ class AsyncClient(_BaseClient):
url: WebSocket endpoint URL. If not provided, uses SPEECHMATICS_RT_URL
environment variable or defaults to EU endpoint.
conn_config: Websocket connection configuration.
sdk_identifier: Value reported to the service as `sm-sdk`. For a package built on
top of speechmatics-rt, pass its own identifier here instead of subclassing
Transport to override `_prepare_url`.

Raises:
ConfigurationError: If required configuration is missing or invalid.
Expand Down Expand Up @@ -76,22 +78,26 @@ def __init__(
api_key: Optional[str] = None,
url: Optional[str] = None,
conn_config: Optional[ConnectionConfig] = None,
sdk_identifier: Optional[str] = None,
) -> None:
self._logger = get_logger("speechmatics.rt.async_client")

self._build_transport = lambda request_id: self._create_transport_from_config(
auth=auth,
api_key=api_key,
url=url,
conn_config=conn_config,
request_id=request_id,
sdk_identifier=sdk_identifier,
)

(
self._session,
self._recognition_started_evt,
self._session_done_evt,
) = self._init_session_info()

transport = self._create_transport_from_config(
auth=auth,
api_key=api_key,
url=url,
conn_config=conn_config,
request_id=self._session.request_id,
)
transport = self._build_transport(self._session.request_id)
super().__init__(transport)

self.on(ServerMessageType.RECOGNITION_STARTED, self._on_recognition_started)
Expand Down Expand Up @@ -340,7 +346,12 @@ async def _send_eos(self, seq_no: int) -> None:

async def _wait_recognition_started(self, timeout: float = 5.0) -> None:
"""Wait for RecognitionStarted message from server."""
await asyncio.wait_for(self._recognition_started_evt.wait(), timeout)
await self._wait_started_or_session_done(self._recognition_started_evt, timeout)

def _reset_session_events(self) -> None:
"""Clear the session-tracking events, for a fresh session."""
self._recognition_started_evt.clear()
self._session_done_evt.clear()

def _on_recognition_started(self, msg: dict[str, Any]) -> None:
"""Handle RecognitionStarted message from server."""
Expand All @@ -357,8 +368,8 @@ def _on_error(self, msg: dict[str, Any]) -> None:
"""Handle Error message from server."""
error = msg.get("reason", "unknown")
self._logger.error("Server error: %s", error)
self._last_error_reason = error
self._session_done_evt.set()
raise TranscriptionError(error)

def _on_audio_added(self, msg: dict[str, Any]) -> None:
"""Handle AudioAdded message from server."""
Expand Down
32 changes: 22 additions & 10 deletions sdk/rt/speechmatics/rt/_async_multi_channel_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from ._base_client import _BaseClient
from ._exceptions import ConfigurationError
from ._exceptions import TimeoutError
from ._exceptions import TranscriptionError
from ._logging import get_logger
from ._models import AudioEventsConfig
from ._models import AudioFormat
Expand Down Expand Up @@ -41,6 +40,8 @@ class AsyncMultiChannelClient(_BaseClient):
url: WebSocket endpoint URL. If not provided, uses SPEECHMATICS_RT_URL
environment variable or defaults to EU endpoint.
conn_config: Websocket connection configuration.
sdk_identifier: Value reported to the service as `sm-sdk`, for a package built on
top of speechmatics-rt.

Examples:
Transcribing stereo audio:
Expand All @@ -65,23 +66,27 @@ def __init__(
api_key: Optional[str] = None,
url: Optional[str] = None,
conn_config: Optional[ConnectionConfig] = None,
sdk_identifier: Optional[str] = None,
) -> None:
self._logger = get_logger("speechmatics.rt.async_multi_chan_client")

self._build_transport = lambda request_id: self._create_transport_from_config(
auth=auth,
api_key=api_key,
url=url,
conn_config=conn_config,
request_id=request_id,
sdk_identifier=sdk_identifier,
)

(
self._session,
self._rec_started_evt,
self._session_done_evt,
) = self._init_session_info()
self._eos_sent = False

transport = self._create_transport_from_config(
auth=auth,
api_key=api_key,
url=url,
conn_config=conn_config,
request_id=self._session.request_id,
)
transport = self._build_transport(self._session.request_id)

super().__init__(transport)

Expand Down Expand Up @@ -182,7 +187,12 @@ async def transcribe(

async def _wait_recognition_started(self, timeout: float = 5.0) -> None:
"""Wait for RecognitionStarted message from server."""
await asyncio.wait_for(self._rec_started_evt.wait(), timeout=timeout)
await self._wait_started_or_session_done(self._rec_started_evt, timeout)

def _reset_session_events(self) -> None:
"""Clear the session-tracking events, for a fresh session."""
self._rec_started_evt.clear()
self._session_done_evt.clear()

async def _audio_producer(self, sources: dict[str, BinaryIO], chunk_size: int) -> None:
"""
Expand Down Expand Up @@ -247,8 +257,10 @@ def _on_eot(self, msg: dict[str, Any]) -> None:

def _on_error(self, msg: dict[str, Any]) -> None:
"""Handle Error message from server."""
error = msg.get("reason", "unknown")
self._logger.error("Server error: %s", error)
self._last_error_reason = error
self._session_done_evt.set()
raise TranscriptionError(msg.get("reason", "unknown"))

def _on_warning(self, msg: dict[str, Any]) -> None:
"""Handle Warning message from server."""
Expand Down
3 changes: 2 additions & 1 deletion sdk/rt/speechmatics/rt/_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Optional

from ._exceptions import AuthenticationError
from .constants import REQUEST_ID_HEADER


class AuthBase(abc.ABC):
Expand Down Expand Up @@ -125,7 +126,7 @@ async def _generate_token(self) -> str:
}

if self._request_id:
headers["X-Request-Id"] = self._request_id
headers.setdefault(REQUEST_ID_HEADER, self._request_id)

try:
async with aiohttp.ClientSession() as session:
Expand Down
Loading
Loading