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
2 changes: 1 addition & 1 deletion .fern/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
},
"exclude_types_from_init_exports": true
},
"originGitCommit": "35ad41f85a53fa379f604440fb6fa833a5f70fe7"
"originGitCommit": "a2ae04ddfa09f1ddb164b918ced2d8c776900eae"
}
14 changes: 10 additions & 4 deletions .fern/replay.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs/concepts/vendors.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Used with `agent.with_tts()`. Each TTS vendor produces audio at a specific sampl
| `TypecastTTS` | Typecast | `api_key`, `voice_id`, `model` | — |
| `SarvamTTS` | Sarvam | `api_key` | — |
| `XaiTTS` | xAI | `api_key`, `language` | Configurable |
| `SonioxTTS` | Soniox | `api_key` | Configurable |

For `RimeTTS`, omitting `credential_mode` selects BYOK validation. Set `credential_mode=CredentialMode.MANAGED` to use managed credentials. See the [RimeTTS vendor reference](../reference/vendors.md#rimetts) for both configurations.

Expand All @@ -84,6 +85,7 @@ Used with `agent.with_tts()` when routing to `Area.CN`. Use `MiniMaxCNTTS` and `
| Class | Provider | Required Parameters | Sample Rate |
|---|---|---|---|
| `MiniMaxCNTTS` | MiniMax (CN) | `model`, `voice_id` or `timber_weights`; `key` typically required | — |
| `MiniMaxDuplexTTS` | MiniMax Duplex (CN only) | `key`, `model`, `voice_id` | Configurable |
| `TencentTTS` | Tencent | `app_id`, `secret_id`, `secret_key`, `voice_type` | — |
| `BytedanceTTS` | ByteDance | `token`, `app_id`, `cluster`, `voice_type` | — |
| `MicrosoftCNTTS` | Microsoft Azure (CN) | `key`, `region`, `voice_name` | 8000, 16000, 24000, or 48000 Hz |
Expand Down
36 changes: 36 additions & 0 deletions docs/reference/vendors.md
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,17 @@ Omitting the mode retains BYOK behavior. An explicit mode is serialized as top-l

`key` and `group_id` are required together for BYOK. `url` is optional. In both BYOK and managed modes, exactly one of `voice_id` or `timber_weights` must be provided. Without `key`, `model` must be one of the supported Agora-managed MiniMax models.

### `SonioxTTS`

Global streaming TTS helper (`vendor: "soniox"`). Only `api_key` is required. Optional fields are `base_url`, `model`, `language`, `voice`, `sample_rate`, `speed` (0.7–1.3), `reduce_silence`, `return_timestamps`, `client_reference_id`, `dump`, `skip_patterns`, and `additional_params`. Named options override matching additional parameters. Omitted values remain with the provider's defaults.

<!-- snippet: executable -->
```python
from agora_agent import SonioxTTS

tts = SonioxTTS(api_key='your-soniox-key')
```

### `MistralTTS`

| Parameter | Type | Required | Default | Description |
Expand Down Expand Up @@ -739,6 +750,31 @@ CN TTS classes use explicit names when they differ from the global implementatio

All CN TTS vendor classes support `skip_patterns` and `additional_params`.

#### `MiniMaxDuplexTTS`

Import from `agora_agent.cn`. This helper currently has only a CN implementation and emits `vendor: "minimax_duplex"`. `key`, `model`, and `voice_id` are required; it does not infer an Agora-managed MiniMax preset or accept `timber_weights` as a voice replacement.

<!-- snippet: executable -->
```python
from agora_agent.cn import MiniMaxDuplexTTS, StepFunSTT

tts = MiniMaxDuplexTTS(
key='your-minimax-key',
model='speech-2.8-turbo',
voice_id='female-shaonv',
sample_rate=24000,
audio_format='pcm',
channels=1,
)
stt = StepFunSTT(api_key='your-stepfun-key')
```

Voice options `speed`, `vol`, `pitch`, `emotion`, and `latex_read` serialize under `params.voice_setting`, following the existing CN MiniMax helper. `sample_rate`, `audio_format`, and `channels` serialize under `params.audio_setting` (with `audio_format` mapped to `format`).

Other optional fields are `url`, `pronunciation_dict`, `voice_modify` (`pitch`, `intensity`, `timbre`, `sound_effects`), `language_boost`, `text_normalization_mode`, `subtitle_enable`, `subtitle_type`, `continuous_sound`, `session_id`, `skip_patterns`, and `additional_params`. Explicit options override additional parameters and preserve `False` and `0`.

`StepFunSTT` is a CN ASR helper (`vendor: "stepfun"`). It requires `api_key`, accepts `additional_params`, and gets the wire recognition language from the agent's turn detection configuration.

#### `MiniMaxCNTTS`

| Parameter | Type | Required | Default | Description |
Expand Down
1 change: 1 addition & 0 deletions src/agora_agent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
RimeTTS,
SarvamSTT,
SarvamTTS,
SonioxTTS,
SmallestAISTT,
SmallestAITTS,
SpeechmaticsSTT,
Expand Down
6 changes: 6 additions & 0 deletions src/agora_agent/agentkit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@
MicrosoftCNSTT,
MicrosoftCNTTS,
MiniMaxCNTTS,
MiniMaxDuplexTTS,
MicrosoftSTT,
MicrosoftTTS,
MiniMaxTTS,
Expand All @@ -222,6 +223,7 @@
SampleRate,
SarvamSTT,
SarvamTTS,
SonioxTTS,
SmallestAISTT,
SmallestAITTS,
TypecastTTS,
Expand All @@ -244,6 +246,7 @@
FengmingSTT,
SenseTimeAvatar,
StepFunTTS,
StepFunSTT,
TencentLLM,
TencentSTT,
TencentTTS,
Expand Down Expand Up @@ -445,16 +448,19 @@
"FishAudioTTS",
"MiniMaxTTS",
"MiniMaxCNTTS",
"MiniMaxDuplexTTS",
"MistralTTS",
"TypecastTTS",
"TencentTTS",
"BytedanceTTS",
"CosyVoiceTTS",
"BytedanceDuplexTTS",
"StepFunTTS",
"StepFunSTT",
"MurfTTS",
"SarvamTTS",
"SmallestAITTS",
"SonioxTTS",
"XaiTTS",
"SpeechmaticsSTT",
"DeepgramSTT",
Expand Down
8 changes: 6 additions & 2 deletions src/agora_agent/agentkit/regional_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
DeepSeekLLM,
FengmingSTT,
MiniMaxTTS as MiniMaxCNTTS,
MiniMaxDuplexTTS,
MicrosoftSTT as MicrosoftCNSTT,
MicrosoftTTS as MicrosoftCNTTS,
QwenOmni,
SenseTimeAvatar,
SpatiusAvatar,
StepFunTTS,
StepFunSTT,
TencentLLM,
TencentSTT,
TencentTTS,
Expand Down Expand Up @@ -70,14 +72,15 @@
GenericTTS,
RimeTTS,
SarvamTTS,
SonioxTTS,
SmallestAITTS,
TypecastTTS,
XaiTTS,
)
from .vendors.avatar import AkoolAvatar, AnamAvatar, GenericAvatar, HeyGenAvatar, LiveAvatarAvatar

CNSTT = typing.Union[TencentSTT, FengmingSTT, MicrosoftCNSTT, XfyunSTT, XfyunBigModelSTT, XfyunDialectSTT]
CNTTS = typing.Union[MiniMaxCNTTS, TencentTTS, BytedanceTTS, MicrosoftCNTTS, CosyVoiceTTS, BytedanceDuplexTTS, StepFunTTS, GenericTTS]
CNSTT = typing.Union[TencentSTT, FengmingSTT, MicrosoftCNSTT, XfyunSTT, XfyunBigModelSTT, XfyunDialectSTT, StepFunSTT]
CNTTS = typing.Union[MiniMaxCNTTS, MiniMaxDuplexTTS, TencentTTS, BytedanceTTS, MicrosoftCNTTS, CosyVoiceTTS, BytedanceDuplexTTS, StepFunTTS, GenericTTS]
CNLLM = typing.Union[AliyunLLM, BytedanceLLM, DeepSeekLLM, TencentLLM]
CNMLLM = QwenOmni
CNAvatar = typing.Union[SenseTimeAvatar, SpatiusAvatar]
Expand All @@ -98,6 +101,7 @@
XaiSTT,
]
GlobalTTS = typing.Union[
SonioxTTS,
GeminiTTS,
MicrosoftTTS,
ElevenLabsTTS,
Expand Down
6 changes: 6 additions & 0 deletions src/agora_agent/agentkit/vendors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
FengmingSTT,
MicrosoftSTT as MicrosoftCNSTT,
MicrosoftTTS as MicrosoftCNTTS,
MiniMaxDuplexTTS,
MiniMaxTTS as MiniMaxCNTTS,
QwenOmni,
SenseTimeAvatar,
SpatiusAvatar,
StepFunSTT,
StepFunTTS,
TencentLLM,
TencentSTT,
Expand Down Expand Up @@ -84,6 +86,7 @@
RimeTTS,
SarvamTTS,
SmallestAITTS,
SonioxTTS,
TypecastTTS,
XaiTTS,
)
Expand Down Expand Up @@ -124,11 +127,13 @@
"FishAudioTTS",
"MiniMaxTTS",
"MiniMaxCNTTS",
"MiniMaxDuplexTTS",
"MistralTTS",
"TypecastTTS",
"MurfTTS",
"SarvamTTS",
"SmallestAITTS",
"SonioxTTS",
"GenericTTS",
"XaiTTS",
"MicrosoftCNTTS",
Expand All @@ -137,6 +142,7 @@
"CosyVoiceTTS",
"BytedanceDuplexTTS",
"StepFunTTS",
"StepFunSTT",
"SpeechmaticsSTT",
"DeepgramSTT",
"MicrosoftSTT",
Expand Down
4 changes: 4 additions & 0 deletions src/agora_agent/agentkit/vendors/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
GenericTTS,
RimeTTS,
SarvamTTS,
SonioxTTS,
SmallestAITTS,
TypecastTTS,
XaiTTS,
Expand Down Expand Up @@ -109,6 +110,7 @@ def __init__(
"xai": XaiGrok,
},
tts={
"soniox": SonioxTTS,
"gemini": GeminiTTS,
"microsoft": MicrosoftTTS,
"elevenlabs": ElevenLabsTTS,
Expand Down Expand Up @@ -142,6 +144,7 @@ def __init__(
CN_VENDOR_NAMESPACE = VendorNamespace(
asr={
"fengming": cn_vendors.FengmingSTT,
"stepfun": cn_vendors.StepFunSTT,
"tencent": cn_vendors.TencentSTT,
"microsoft": cn_vendors.MicrosoftSTT,
"xfyun": cn_vendors.XfyunSTT,
Expand All @@ -159,6 +162,7 @@ def __init__(
},
tts={
"minimax": cn_vendors.MiniMaxTTS,
"minimax_duplex": cn_vendors.MiniMaxDuplexTTS,
"tencent": cn_vendors.TencentTTS,
"bytedance": cn_vendors.BytedanceTTS,
"microsoft": cn_vendors.MicrosoftTTS,
Expand Down
74 changes: 74 additions & 0 deletions src/agora_agent/agentkit/vendors/cn.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@
from pydantic import BaseModel, ConfigDict, Field, model_validator


class StepFunSTTOptions(BaseModel):
model_config = ConfigDict(extra="forbid")

api_key: str = Field(..., min_length=1, repr=False)
additional_params: Optional[Dict[str, Any]] = None


class StepFunSTT(StepFunSTTOptions, _BaseSTTCompat):
"""StepFun ASR for mainland China."""

def to_config(self) -> Dict[str, Any]:
params = dict(self.additional_params or {})
params["api_key"] = self.api_key
return {"vendor": "stepfun", "params": params}


class TencentSTTOptions(BaseModel):
model_config = ConfigDict(extra="forbid")

Expand Down Expand Up @@ -435,6 +451,64 @@ def to_config(self) -> Dict[str, Any]:
return result


class MiniMaxDuplexTTSOptions(BaseModel):
model_config = ConfigDict(extra="forbid")

key: str = Field(..., min_length=1, repr=False)
model: str = Field(..., min_length=1)
voice_id: str = Field(..., min_length=1)
url: Optional[str] = None
speed: Optional[float] = None
vol: Optional[float] = None
pitch: Optional[float] = None
emotion: Optional[str] = None
latex_read: Optional[bool] = None
sample_rate: Optional[int] = None
audio_format: Optional[str] = None
channels: Optional[int] = None
pronunciation_dict: Optional[Dict[str, Any]] = None
voice_modify: Optional[Dict[str, Any]] = None
language_boost: Optional[str] = None
text_normalization_mode: Optional[str] = None
subtitle_enable: Optional[bool] = None
subtitle_type: Optional[str] = None
continuous_sound: Optional[bool] = None
session_id: Optional[str] = None
additional_params: Optional[Dict[str, Any]] = None
skip_patterns: Optional[List[int]] = None


class MiniMaxDuplexTTS(MiniMaxDuplexTTSOptions, _BaseTTSCompat):
"""MiniMax duplex streaming TTS, currently available only in mainland China."""

def to_config(self) -> Dict[str, Any]:
params: Dict[str, Any] = dict(self.additional_params or {})
voice_setting: Dict[str, Any] = {"voice_id": self.voice_id}
for field in ("speed", "vol", "pitch", "emotion", "latex_read"):
value = getattr(self, field)
if value is not None:
voice_setting[field] = value
params.update({"key": self.key, "model": self.model, "voice_setting": voice_setting})
audio_setting: Dict[str, Any] = {}
for field, wire_field in (("sample_rate", "sample_rate"), ("audio_format", "format"), ("channels", "channels")):
value = getattr(self, field)
if value is not None:
audio_setting[wire_field] = value
if audio_setting:
params["audio_setting"] = audio_setting
for field in (
"url", "pronunciation_dict", "voice_modify", "language_boost", "text_normalization_mode",
"subtitle_enable", "subtitle_type", "continuous_sound", "session_id",
):
value = getattr(self, field)
if value is not None:
params[field] = value
config: Dict[str, Any] = {"vendor": "minimax_duplex", "params": params}
if self.skip_patterns is not None:
config["skip_patterns"] = self.skip_patterns
return config


class MiniMaxTTSOptions(BaseModel):
model_config = ConfigDict(extra="forbid")

Expand Down
Loading
Loading