Skip to content

Commit

Permalink
adds TTS streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
SandraRodgers committed Jun 26, 2024
1 parent 102b807 commit 3b6c941
Show file tree
Hide file tree
Showing 14 changed files with 1,592 additions and 6 deletions.
2 changes: 2 additions & 0 deletions deepgram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@

# speak
from .client import SpeakClient, AsyncSpeakClient
from .client import SpeakStreamClient, AsyncSpeakStreamClient
from .client import SpeakOptions, SpeakStreamSource, SpeakSource
from .client import SpeakResponse
from .client import SpeakStreamEvents

# manage
from .client import ManageClient, AsyncManageClient
Expand Down
25 changes: 25 additions & 0 deletions deepgram/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@

# speak client classes/input
from .clients import SpeakClient, AsyncSpeakClient
from .clients import SpeakStreamClient, AsyncSpeakStreamClient
from .clients import SpeakOptions
from .clients import SpeakStreamSource, SpeakSource
from .clients import SpeakStreamEvents

# speak client responses
from .clients import SpeakResponse
Expand Down Expand Up @@ -236,6 +238,19 @@ def asyncspeak(self):
return self.Version(self._config, "asyncspeak")

@property
def speakstream(self):
"""
Returns a SpeakStreamClient instance for interacting with Deepgram's speak services.
"""
return self.Version(self._config, "speak-stream")

@property
def asyncspeakstream(self):
"""
Returns an AsyncSpeakStreamClient instance for interacting with Deepgram's speak services.
"""
return self.Version(self._config, "asyncspeak-stream")
@property
def manage(self):
"""
Returns a ManageClient instance for managing Deepgram resources.
Expand Down Expand Up @@ -310,6 +325,7 @@ def __init__(self, config, parent: str):
# raise DeepgramModuleError("Invalid parent")

def v(self, version: str = ""):
# pylint: disable-msg=too-many-statements
"""
Returns a client for the specified version of the API.
"""
Expand Down Expand Up @@ -340,6 +356,14 @@ def v(self, version: str = ""):
parent = "speak"
filename = "async_client"
classname = "AsyncSpeakClient"
case "speak-stream":
parent = "speak"
filename = "client_stream"
classname = "SpeakStreamClient"
case "asyncspeak-stream":
parent = "speak"
filename = "async_client_stream"
classname = "AsyncSpeakStreamClient"
case "selfhosted":
parent = "selfhosted"
filename = "client"
Expand Down Expand Up @@ -376,3 +400,4 @@ def v(self, version: str = ""):
self._logger.notice("Version.v succeeded")
self._logger.debug("Version.v LEAVE")
return my_class_instance
# pylint: enable-msg=too-many-statements
4 changes: 4 additions & 0 deletions deepgram/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,12 @@
SpeakStreamSource,
SpeakSource,
)
from .speak import SpeakStreamEvents
from .speak import SpeakResponse

# speak-stream
from .speak import SpeakStreamClient, AsyncSpeakStreamClient

# manage
from .manage import ManageClient, AsyncManageClient
from .manage import (
Expand Down
13 changes: 8 additions & 5 deletions deepgram/clients/live/v1/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ def on(self, event: LiveTranscriptionEvents, handler) -> None:
"""
self._logger.info("event subscribed: %s", event)
if event in LiveTranscriptionEvents.__members__.values() and callable(handler):
self._event_handlers[event].append(handler)
if handler not in self._event_handlers[event]:
self._event_handlers[event].append(handler)

# triggers the registered event handlers for a specific event
async def _emit(self, event: LiveTranscriptionEvents, *args, **kwargs) -> None:
Expand All @@ -238,11 +239,13 @@ async def _emit(self, event: LiveTranscriptionEvents, *args, **kwargs) -> None:

tasks = []
for handler in self._event_handlers[event]:
tasks.append(asyncio.create_task(handler(self, *args, **kwargs)))
task = asyncio.create_task(handler(self, *args, **kwargs))
tasks.append(task)

if len(tasks) > 0:
if tasks:
self._logger.debug("waiting for tasks to finish...")
await asyncio.gather(*filter(None, tasks), return_exceptions=True)
await asyncio.gather(*tasks, return_exceptions=True)
tasks.clear()

# debug the threads
for thread in threading.enumerate():
Expand Down Expand Up @@ -380,7 +383,7 @@ async def _listening(self) -> None:
return

except websockets.exceptions.ConnectionClosed as e:
if e.code == 1000:
if e.code in [1000, 1001]:
self._logger.notice(f"_listening({e.code}) exiting gracefully")
self._logger.debug("AsyncLiveClient._listening LEAVE")
return
Expand Down
2 changes: 2 additions & 0 deletions deepgram/clients/speak/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# SPDX-License-Identifier: MIT

from .client import SpeakClient
from .client import SpeakStreamClient, AsyncSpeakStreamClient
from .client import AsyncSpeakClient
from .client import SpeakOptions
from .client import SpeakResponse
Expand All @@ -12,4 +13,5 @@
SpeakSource,
)

from .enums import SpeakStreamEvents
from ...options import DeepgramClientOptions, ClientOptionsFromEnv
4 changes: 4 additions & 0 deletions deepgram/clients/speak/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from .v1.client import SpeakClient as SpeakClientLatest
from .v1.async_client import AsyncSpeakClient as AsyncSpeakClientLatest
from .v1.client_stream import SpeakStreamClient as SpeakStreamClientLatest
from .v1.async_client_stream import AsyncSpeakStreamClient as AsyncSpeakStreamClientLatest
from .v1.options import (
SpeakOptions as SpeakOptionsLatest,
FileSource as FileSourceLatest,
Expand All @@ -29,3 +31,5 @@
SpeakResponse = SpeakResponseLatest
SpeakClient = SpeakClientLatest
AsyncSpeakClient = AsyncSpeakClientLatest
SpeakStreamClient = SpeakStreamClientLatest
AsyncSpeakStreamClient = AsyncSpeakStreamClientLatest
22 changes: 22 additions & 0 deletions deepgram/clients/speak/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2024 Deepgram SDK contributors. All Rights Reserved.
# Use of this source code is governed by a MIT license that can be found in the LICENSE file.
# SPDX-License-Identifier: MIT

from aenum import StrEnum

# Constants mapping to events from the Deepgram API


class SpeakStreamEvents(StrEnum):
"""
Enumerates the possible events that can be received from the Deepgram API
"""

Open: str = "Open"
Close: str = "Close"
AudioData: str = "AudioData"
Metadata: str = "Metadata"
Flush: str = "Flush"
Unhandled: str = "Unhandled"
Error: str = "Error"
Warning: str = "Warning"
2 changes: 1 addition & 1 deletion deepgram/clients/speak/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __str__(self):

class DeepgramTypeError(Exception):
"""
Exception raised for unknown errors related to unknown Types for Transcription.
Exception raised for unknown errors related to unknown Types for TTS Synthesis.
Attributes:
message (str): The error message describing the exception.
Expand Down
2 changes: 2 additions & 0 deletions deepgram/clients/speak/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# SPDX-License-Identifier: MIT

from .client import SpeakClient
from .client_stream import SpeakStreamClient
from .async_client_stream import AsyncSpeakStreamClient
from .async_client import AsyncSpeakClient
from .options import SpeakOptions, FileSource, SpeakStreamSource, SpeakSource
from .response import SpeakResponse
Expand Down
Loading

0 comments on commit 3b6c941

Please sign in to comment.