Skip to content
Open
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
4 changes: 2 additions & 2 deletions .fern/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"skip_validation": true
}
},
"originGitCommit": "8dd6f48a06eee8c3985894f68ba3b554e5564d21",
"originGitCommit": "335af96251466afae7a9f71badb65c630a48626e",
"originGitCommitIsDirty": true,
"invokedBy": "manual",
"sdkVersion": "7.3.2"
"sdkVersion": "7.4.1"
}
13 changes: 13 additions & 0 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ src/deepgram/agent/v1/socket_client.py
src/deepgram/listen/v1/socket_client.py
src/deepgram/listen/v2/socket_client.py
src/deepgram/speak/v1/socket_client.py
src/deepgram/speak/v2/socket_client.py

# Backward-compat patch: AgentV1SettingsAgentContext schema restructure as of
# 2026-05-05. The new schema nests messages under .context.messages; this file
Expand Down Expand Up @@ -123,15 +124,27 @@ src/deepgram/listen/v2/types/__init__.py
# [temporarily frozen — manual patches listed above]
src/deepgram/core/query_encoder.py

# Carries `# x-release-please-version` annotations on the User-Agent and
# X-Fern-SDK-Version header lines so release-please bumps the wire telemetry
# version in lockstep with the published package version (it is a `generic`
# extra-file in .github/release-please-config.json). Fern regenerates this file
# from scratch and would strip the annotations, so it is frozen to protect them.
# [temporarily frozen — manual patches listed above]
src/deepgram/core/client_wrapper.py

# Hand-written custom tests
tests/custom/test_agent_history.py
tests/custom/test_agent_update_listen.py
tests/custom/test_compat_aliases.py
tests/custom/test_eot_thresholds_feature.py
tests/custom/test_language_hint_compat.py
tests/custom/test_language_hints_feature.py
tests/custom/test_listen_v2_regen_constraints.py
tests/custom/test_query_encoder.py
tests/custom/test_secure_logging.py
tests/custom/test_socket_client_shims.py
tests/custom/test_speak_v2_connect_wire.py
tests/custom/test_speak_v2_socket.py
tests/custom/test_text_builder.py
tests/custom/test_transport.py
tests/typecheck/compat_aliases.py
Expand Down
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ How to identify:

Current temporarily frozen files:
- `src/deepgram/speak/v1/socket_client.py` — optional message param defaults, broad exception catch
- `src/deepgram/speak/v2/socket_client.py` — same (optional `send_flush`/`send_close` defaults, broad exception catch); new websocket TTS client added in the 2026-07-08 regen
- `src/deepgram/listen/v1/socket_client.py` — same
- `src/deepgram/listen/v2/socket_client.py` — same + `send_configure` typing.Any/raw shim, response Union uses typing.Any instead of `ListenV2ConfigureSuccess`
- `src/deepgram/agent/v1/socket_client.py` — same + `_sanitize_numeric_types`
- `src/deepgram/agent/v1/types/agent_v1settings_agent_context.py`, `src/deepgram/agent/v1/types/agent_v1settings_agent.py`, `src/deepgram/agent/v1/types/agent_v1settings.py`, `src/deepgram/agent/v1/requests/agent_v1settings_agent_context.py`, `src/deepgram/agent/v1/requests/agent_v1settings_agent.py`, `src/deepgram/agent/v1/requests/agent_v1settings.py` — backward-compat patches for the 2026-05-05 Agent Settings schema restructure. These preserve callable `AgentV1SettingsAgent(...)`, keep `AgentV1Settings.agent` accepting both that wrapper and `agent_id` strings, restore the legacy request TypedDict shapes, remap legacy `messages=[...]` / nested `context=AgentV1SettingsAgentContext(messages=[...])` usage into the new `context={"messages": [...]}` wire shape, and keep read-side `obj.messages` access working.
- `src/deepgram/core/query_encoder.py` — coerces Python bools to lowercase `"true"`/`"false"` before they reach `urllib.parse.urlencode` (which would otherwise produce `"True"`/`"False"` via `str()` and break websocket query strings). Only the four `*/connect()` paths call `urlencode`; HTTP raw clients hand params to httpx, which lowercases bools itself, so the patch is a no-op for the HTTP path. Once Fern's websocket codegen normalizes bools (or the spec types these as `boolean` end-to-end), this can be unfrozen.
- `src/deepgram/core/client_wrapper.py` — carries `# x-release-please-version` annotations on the `User-Agent` and `X-Fern-SDK-Version` header lines. `client_wrapper.py` is listed as a `generic` extra-file in `.github/release-please-config.json`, but the generic updater only rewrites annotated lines, so without these comments release-please never bumps the wire telemetry version and it drifts from the published package version (e.g. main shipping 7.4.0 while sending 7.3.2). Fern regenerates this file from scratch and would strip the annotations, so it is frozen to protect them. On regen, re-apply the two annotation comments to the freshly generated header lines. Unfreeze only if Fern's generator starts emitting the annotations itself.
- `tests/wire/test_manage_v1_projects_keys.py` — restored wire coverage for the legacy `CreateKeyV1RequestOneParams` request alias so future regens do not silently drop that compatibility check
- `src/deepgram/__init__.py`, `src/deepgram/agent/__init__.py`, `src/deepgram/agent/v1/__init__.py`, `src/deepgram/agent/v1/types/__init__.py`, `src/deepgram/agent/v1/requests/__init__.py`, `src/deepgram/types/__init__.py`, `src/deepgram/requests/__init__.py` — package `__init__.py` files carrying hand-applied legacy alias re-exports for `CreateKeyV1RequestOne`, `AgentV1HistoryContent`, `AgentV1HistoryFunctionCalls`, `AgentV1SettingsAgentContextMessagesItemContent`, `AgentV1SettingsAgentContextMessagesItemFunctionCalls` (and their `*Params` variants). Fern would otherwise regenerate these and strip the legacy entries. After unfreezing for the next regen and reviewing the new generated content, re-apply the legacy re-exports plus any genuine new entries Fern added.
- `src/deepgram/listen/__init__.py`, `src/deepgram/listen/v2/__init__.py`, `src/deepgram/listen/v2/types/__init__.py` — `__init__.py` files re-exporting the hand-written `ListenV2CloseStreamType` shim. Frozen so Fern won't strip the re-export on regen. Same handling as the package `__init__.py` files above: after unfreezing, re-apply the `ListenV2CloseStreamType` re-export plus any genuine new entries Fern added.
Expand Down
66 changes: 66 additions & 0 deletions examples/25-text-to-speech-streaming-v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
Example: Text-to-Speech Streaming with the Speak V2 (Flux) WebSocket

This example shows how to stream text-to-speech conversion using the Speak V2
WebSocket. Speak V2 uses Flux voices (model strings of the form
`flux-{voice}-{language}`, e.g. `flux-alexis-en`); use Speak V1 for Aura voices.
"""

from typing import Union

from dotenv import load_dotenv

load_dotenv()

from deepgram import DeepgramClient
from deepgram.core.events import EventType
from deepgram.speak.v2.types import SpeakV2Speak

SpeakV2SocketClientResponse = Union[str, bytes]

client = DeepgramClient()

try:
with client.speak.v2.connect(model="flux-alexis-en", encoding="linear16", sample_rate="24000") as connection:

def on_message(message: SpeakV2SocketClientResponse) -> None:
if isinstance(message, bytes):
print("Received audio data")
# In production, you would write this audio data to a file or play it
# with open("output.raw", "ab") as audio_file:
# audio_file.write(message)
else:
msg_type = getattr(message, "type", "Unknown")
print(f"Received {msg_type} event")

connection.on(EventType.OPEN, lambda _: print("Connection opened"))
connection.on(EventType.MESSAGE, on_message)
connection.on(EventType.CLOSE, lambda _: print("Connection closed"))
connection.on(EventType.ERROR, lambda error: print(f"Error: {error}"))

# For sync version: Send messages before starting to listen
# Note: start_listening() blocks, so send all messages first
# For better control with bidirectional communication, use the async version
connection.send_speak(SpeakV2Speak(text="Hello, this is a text to speech example."))

# Flush to ensure all text is processed
connection.send_flush()

# Close the connection when done
connection.send_close()

# Start listening - this blocks until the connection closes
# All messages should be sent before calling this in sync mode
connection.start_listening()

# For async version:
# from deepgram import AsyncDeepgramClient
# async with client.speak.v2.connect(...) as connection:
# listen_task = asyncio.create_task(connection.start_listening())
# await connection.send_speak(SpeakV2Speak(text="..."))
# await connection.send_flush()
# await connection.send_close()
# await listen_task

except Exception as e:
print(f"Error: {e}")
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This directory contains comprehensive examples demonstrating how to use the Deep
- **22-text-builder-demo.py** - TextBuilder demo (no API key required)
- **23-text-builder-helper.py** - TextBuilder with REST API generation
- **24-text-builder-streaming.py** - TextBuilder with streaming TTS (WebSocket)
- **25-text-to-speech-streaming-v2.py** - Streaming TTS via the Speak V2 (Flux) WebSocket

### 30-39: Voice Agent

Expand Down
Loading
Loading