camb-sdk 1.5.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. camb/__init__.py +335 -0
  2. camb/audio_separation/__init__.py +4 -0
  3. camb/audio_separation/client.py +406 -0
  4. camb/audio_separation/raw_client.py +534 -0
  5. camb/client.py +717 -0
  6. camb/core/__init__.py +105 -0
  7. camb/core/api_error.py +23 -0
  8. camb/core/client_wrapper.py +113 -0
  9. camb/core/datetime_utils.py +28 -0
  10. camb/core/file.py +67 -0
  11. camb/core/force_multipart.py +18 -0
  12. camb/core/http_client.py +663 -0
  13. camb/core/http_response.py +55 -0
  14. camb/core/http_sse/__init__.py +42 -0
  15. camb/core/http_sse/_api.py +112 -0
  16. camb/core/http_sse/_decoders.py +61 -0
  17. camb/core/http_sse/_exceptions.py +7 -0
  18. camb/core/http_sse/_models.py +17 -0
  19. camb/core/jsonable_encoder.py +100 -0
  20. camb/core/pydantic_utilities.py +260 -0
  21. camb/core/query_encoder.py +58 -0
  22. camb/core/remove_none_from_dict.py +11 -0
  23. camb/core/request_options.py +35 -0
  24. camb/core/serialization.py +276 -0
  25. camb/deprecated_streaming/__init__.py +4 -0
  26. camb/deprecated_streaming/client.py +532 -0
  27. camb/deprecated_streaming/raw_client.py +639 -0
  28. camb/dictionaries/__init__.py +4 -0
  29. camb/dictionaries/client.py +785 -0
  30. camb/dictionaries/raw_client.py +1048 -0
  31. camb/dub/__init__.py +49 -0
  32. camb/dub/client.py +846 -0
  33. camb/dub/raw_client.py +1194 -0
  34. camb/dub/types/__init__.py +53 -0
  35. camb/dub/types/dubbed_output_in_alt_format_request_payload_output_format.py +8 -0
  36. camb/dub/types/get_dubbed_output_in_alt_format_dub_alt_format_run_id_language_post_response.py +9 -0
  37. camb/dub/types/get_dubbed_run_info_dub_result_run_id_get_response.py +7 -0
  38. camb/dub/types/get_dubbing_runs_results_dubbing_results_post_response_value.py +7 -0
  39. camb/environment.py +7 -0
  40. camb/errors/__init__.py +34 -0
  41. camb/errors/unprocessable_entity_error.py +11 -0
  42. camb/folders/__init__.py +4 -0
  43. camb/folders/client.py +213 -0
  44. camb/folders/raw_client.py +278 -0
  45. camb/languages/__init__.py +4 -0
  46. camb/languages/client.py +168 -0
  47. camb/languages/raw_client.py +223 -0
  48. camb/project_setup/__init__.py +4 -0
  49. camb/project_setup/client.py +537 -0
  50. camb/project_setup/raw_client.py +655 -0
  51. camb/py.typed +0 -0
  52. camb/raw_client.py +236 -0
  53. camb/story/__init__.py +37 -0
  54. camb/story/client.py +579 -0
  55. camb/story/raw_client.py +743 -0
  56. camb/story/types/__init__.py +38 -0
  57. camb/story/types/create_story_story_post_response.py +8 -0
  58. camb/story/types/setup_story_story_setup_post_response.py +8 -0
  59. camb/streaming/__init__.py +4 -0
  60. camb/streaming/client.py +645 -0
  61. camb/streaming/raw_client.py +796 -0
  62. camb/text_to_audio/__init__.py +4 -0
  63. camb/text_to_audio/client.py +469 -0
  64. camb/text_to_audio/raw_client.py +610 -0
  65. camb/text_to_speech/__init__.py +49 -0
  66. camb/text_to_speech/baseten.py +214 -0
  67. camb/text_to_speech/client.py +742 -0
  68. camb/text_to_speech/raw_client.py +995 -0
  69. camb/text_to_speech/types/__init__.py +47 -0
  70. camb/text_to_speech/types/create_stream_tts_request_payload_language.py +71 -0
  71. camb/text_to_speech/types/create_stream_tts_request_payload_speech_model.py +7 -0
  72. camb/text_to_speech/types/get_tts_results_tts_results_post_response_value.py +7 -0
  73. camb/text_to_speech/types/get_tts_run_info_tts_result_run_id_get_response.py +7 -0
  74. camb/text_to_voice/__init__.py +4 -0
  75. camb/text_to_voice/client.py +329 -0
  76. camb/text_to_voice/raw_client.py +405 -0
  77. camb/transcription/__init__.py +4 -0
  78. camb/transcription/client.py +465 -0
  79. camb/transcription/raw_client.py +587 -0
  80. camb/translated_story/__init__.py +4 -0
  81. camb/translated_story/client.py +309 -0
  82. camb/translated_story/raw_client.py +381 -0
  83. camb/translated_tts/__init__.py +4 -0
  84. camb/translated_tts/client.py +313 -0
  85. camb/translated_tts/raw_client.py +357 -0
  86. camb/translation/__init__.py +4 -0
  87. camb/translation/client.py +631 -0
  88. camb/translation/raw_client.py +787 -0
  89. camb/types/__init__.py +236 -0
  90. camb/types/add_target_language_out.py +20 -0
  91. camb/types/audio_output_type.py +5 -0
  92. camb/types/audio_stream.py +31 -0
  93. camb/types/config_stream.py +22 -0
  94. camb/types/config_stream_pipeline.py +28 -0
  95. camb/types/create_custom_voice_out.py +19 -0
  96. camb/types/create_project_setup_out.py +19 -0
  97. camb/types/create_stream_out.py +22 -0
  98. camb/types/create_stream_request_payload.py +70 -0
  99. camb/types/create_translated_tts_out.py +19 -0
  100. camb/types/create_tts_out.py +19 -0
  101. camb/types/data_stream.py +24 -0
  102. camb/types/demixing_option.py +10 -0
  103. camb/types/dictionary_term.py +21 -0
  104. camb/types/dictionary_with_terms.py +28 -0
  105. camb/types/dubbing_result.py +22 -0
  106. camb/types/exception_reasons.py +30 -0
  107. camb/types/folder.py +20 -0
  108. camb/types/formalities.py +3 -0
  109. camb/types/gender.py +3 -0
  110. camb/types/get_audio_separation_result_out.py +20 -0
  111. camb/types/get_create_project_setup_response.py +21 -0
  112. camb/types/get_probe_stream_in.py +21 -0
  113. camb/types/get_probe_stream_out.py +24 -0
  114. camb/types/get_setup_story_result_response.py +21 -0
  115. camb/types/get_text_to_voice_result_out.py +19 -0
  116. camb/types/get_tts_result_out_file_url.py +19 -0
  117. camb/types/http_validation_error.py +20 -0
  118. camb/types/language_enums.py +154 -0
  119. camb/types/language_pydantic_model.py +21 -0
  120. camb/types/languages.py +3 -0
  121. camb/types/orchestrator_pipeline_call_result.py +19 -0
  122. camb/types/orchestrator_pipeline_result.py +25 -0
  123. camb/types/orchestrator_pipeline_result_exception_reason.py +7 -0
  124. camb/types/orchestrator_pipeline_result_message.py +5 -0
  125. camb/types/output_format.py +10 -0
  126. camb/types/overdub_config.py +37 -0
  127. camb/types/project_details.py +28 -0
  128. camb/types/revoicing_option.py +5 -0
  129. camb/types/run_i_ds_request_payload.py +19 -0
  130. camb/types/segmenting_option.py +5 -0
  131. camb/types/source_stream.py +30 -0
  132. camb/types/story_details.py +27 -0
  133. camb/types/stream_category.py +3 -0
  134. camb/types/stream_tts_inference_options.py +38 -0
  135. camb/types/stream_tts_output_configuration.py +33 -0
  136. camb/types/stream_tts_voice_settings.py +28 -0
  137. camb/types/stream_type.py +3 -0
  138. camb/types/stream_url_for_languages.py +21 -0
  139. camb/types/target_stream.py +34 -0
  140. camb/types/task_status.py +5 -0
  141. camb/types/term_translation_input.py +21 -0
  142. camb/types/term_translation_output.py +20 -0
  143. camb/types/text_to_audio_result.py +19 -0
  144. camb/types/text_to_audio_type.py +5 -0
  145. camb/types/transcribing_option.py +5 -0
  146. camb/types/transcript.py +22 -0
  147. camb/types/transcript_data_type.py +5 -0
  148. camb/types/transcript_file_format.py +5 -0
  149. camb/types/transcription_result.py +20 -0
  150. camb/types/translating_option.py +5 -0
  151. camb/types/translation_result.py +19 -0
  152. camb/types/tts_provider.py +3 -0
  153. camb/types/validation_error.py +22 -0
  154. camb/types/validation_error_loc_item.py +5 -0
  155. camb/types/video_output_type_without_avi.py +5 -0
  156. camb/types/video_stream.py +28 -0
  157. camb/types/voice.py +28 -0
  158. camb/voice_cloning/__init__.py +34 -0
  159. camb/voice_cloning/client.py +265 -0
  160. camb/voice_cloning/raw_client.py +320 -0
  161. camb/voice_cloning/types/__init__.py +36 -0
  162. camb/voice_cloning/types/list_voices_list_voices_get_response_item.py +7 -0
  163. camb_sdk-1.5.4.dist-info/METADATA +282 -0
  164. camb_sdk-1.5.4.dist-info/RECORD +167 -0
  165. camb_sdk-1.5.4.dist-info/WHEEL +5 -0
  166. camb_sdk-1.5.4.dist-info/licenses/LICENSE +21 -0
  167. camb_sdk-1.5.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,995 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import contextlib
4
+ import typing
5
+ from json.decoder import JSONDecodeError
6
+
7
+ from ..core.api_error import ApiError
8
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
9
+ from ..core.http_response import AsyncHttpResponse, HttpResponse
10
+ from ..core.jsonable_encoder import jsonable_encoder
11
+ from ..core.pydantic_utilities import parse_obj_as
12
+ from ..core.request_options import RequestOptions
13
+ from ..core.serialization import convert_and_respect_annotation_metadata
14
+ from ..errors.unprocessable_entity_error import UnprocessableEntityError
15
+ from ..types.create_tts_out import CreateTtsOut
16
+ from ..types.gender import Gender
17
+ from ..types.http_validation_error import HttpValidationError
18
+ from ..types.languages import Languages
19
+ from ..types.orchestrator_pipeline_result import OrchestratorPipelineResult
20
+ from ..types.stream_tts_inference_options import StreamTtsInferenceOptions
21
+ from ..types.stream_tts_output_configuration import StreamTtsOutputConfiguration
22
+ from ..types.stream_tts_voice_settings import StreamTtsVoiceSettings
23
+ from .baseten import async_baseten_tts, baseten_tts
24
+ from .types.create_stream_tts_request_payload_language import CreateStreamTtsRequestPayloadLanguage
25
+ from .types.create_stream_tts_request_payload_speech_model import CreateStreamTtsRequestPayloadSpeechModel
26
+ from .types.get_tts_results_tts_results_post_response_value import GetTtsResultsTtsResultsPostResponseValue
27
+ from .types.get_tts_run_info_tts_result_run_id_get_response import GetTtsRunInfoTtsResultRunIdGetResponse
28
+
29
+ # this is used as the default value for optional parameters
30
+ OMIT = typing.cast(typing.Any, ...)
31
+
32
+
33
+ class RawTextToSpeechClient:
34
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
35
+ self._client_wrapper = client_wrapper
36
+
37
+ @contextlib.contextmanager
38
+ def tts(
39
+ self,
40
+ *,
41
+ text: str,
42
+ language: CreateStreamTtsRequestPayloadLanguage,
43
+ voice_id: typing.Optional[int] = OMIT,
44
+ speech_model: typing.Optional[CreateStreamTtsRequestPayloadSpeechModel] = OMIT,
45
+ user_instructions: typing.Optional[str] = OMIT,
46
+ enhance_named_entities_pronunciation: typing.Optional[bool] = OMIT,
47
+ output_configuration: typing.Optional[StreamTtsOutputConfiguration] = OMIT,
48
+ voice_settings: typing.Optional[StreamTtsVoiceSettings] = OMIT,
49
+ inference_options: typing.Optional[StreamTtsInferenceOptions] = OMIT,
50
+ request_options: typing.Optional[RequestOptions] = None,
51
+ ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]:
52
+ """
53
+ Parameters
54
+ ----------
55
+ text : str
56
+
57
+ language : CreateStreamTtsRequestPayloadLanguage
58
+
59
+ voice_id : int
60
+
61
+ speech_model : typing.Optional[CreateStreamTtsRequestPayloadSpeechModel]
62
+
63
+ user_instructions : typing.Optional[str]
64
+
65
+ enhance_named_entities_pronunciation : typing.Optional[bool]
66
+
67
+ output_configuration : typing.Optional[StreamTtsOutputConfiguration]
68
+
69
+ voice_settings : typing.Optional[StreamTtsVoiceSettings]
70
+
71
+ inference_options : typing.Optional[StreamTtsInferenceOptions]
72
+
73
+ request_options : typing.Optional[RequestOptions]
74
+ Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.
75
+
76
+ Returns
77
+ -------
78
+ typing.Iterator[HttpResponse[typing.Iterator[bytes]]]
79
+ Streaming audio response
80
+ """
81
+ if self._client_wrapper.tts_provider is None and (voice_id is OMIT or voice_id is None):
82
+ raise ValueError("voice_id is required when using the default Camb.ai provider.")
83
+
84
+ if self._client_wrapper.tts_provider == "baseten":
85
+ if speech_model == "mars-pro":
86
+ with baseten_tts(
87
+ self._client_wrapper,
88
+ text=text,
89
+ language=language,
90
+ voice_id=voice_id,
91
+ speech_model=speech_model,
92
+ user_instructions=user_instructions,
93
+ enhance_named_entities_pronunciation=enhance_named_entities_pronunciation,
94
+ output_configuration=output_configuration,
95
+ voice_settings=voice_settings,
96
+ inference_options=inference_options,
97
+ request_options=request_options,
98
+ ) as r:
99
+ yield r
100
+ return
101
+ else:
102
+ raise ValueError(f"{self._client_wrapper.tts_provider} provider can only be used with 'mars-pro' speech model.")
103
+
104
+ with self._client_wrapper.httpx_client.stream(
105
+ "tts-stream",
106
+ method="POST",
107
+ json={
108
+ "text": text,
109
+ "language": language,
110
+ "voice_id": voice_id,
111
+ "speech_model": speech_model,
112
+ "user_instructions": user_instructions,
113
+ "enhance_named_entities_pronunciation": enhance_named_entities_pronunciation,
114
+ "output_configuration": convert_and_respect_annotation_metadata(
115
+ object_=output_configuration, annotation=StreamTtsOutputConfiguration, direction="write"
116
+ ),
117
+ "voice_settings": convert_and_respect_annotation_metadata(
118
+ object_=voice_settings, annotation=StreamTtsVoiceSettings, direction="write"
119
+ ),
120
+ "inference_options": convert_and_respect_annotation_metadata(
121
+ object_=inference_options, annotation=StreamTtsInferenceOptions, direction="write"
122
+ ),
123
+ },
124
+ headers={
125
+ "content-type": "application/json",
126
+ },
127
+ request_options=request_options,
128
+ omit=OMIT,
129
+ ) as _response:
130
+
131
+ def _stream() -> HttpResponse[typing.Iterator[bytes]]:
132
+ try:
133
+ if 200 <= _response.status_code < 300:
134
+ _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
135
+ return HttpResponse(
136
+ response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size))
137
+ )
138
+ _response.read()
139
+ if _response.status_code == 422:
140
+ raise UnprocessableEntityError(
141
+ headers=dict(_response.headers),
142
+ body=typing.cast(
143
+ HttpValidationError,
144
+ parse_obj_as(
145
+ type_=HttpValidationError, # type: ignore
146
+ object_=_response.json(),
147
+ ),
148
+ ),
149
+ )
150
+ _response_json = _response.json()
151
+ except JSONDecodeError:
152
+ raise ApiError(
153
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
154
+ )
155
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
156
+
157
+ yield _stream()
158
+
159
+ def create_tts(
160
+ self,
161
+ *,
162
+ text: str,
163
+ voice_id: int,
164
+ language: Languages,
165
+ run_id: typing.Optional[int] = None,
166
+ project_name: typing.Optional[str] = OMIT,
167
+ project_description: typing.Optional[str] = OMIT,
168
+ folder_id: typing.Optional[int] = OMIT,
169
+ gender: typing.Optional[Gender] = OMIT,
170
+ age: typing.Optional[int] = OMIT,
171
+ request_options: typing.Optional[RequestOptions] = None,
172
+ ) -> HttpResponse[CreateTtsOut]:
173
+ """
174
+ Parameters
175
+ ----------
176
+ text : str
177
+
178
+ voice_id : int
179
+
180
+ language : Languages
181
+
182
+ run_id : typing.Optional[int]
183
+
184
+ project_name : typing.Optional[str]
185
+
186
+ project_description : typing.Optional[str]
187
+
188
+ folder_id : typing.Optional[int]
189
+
190
+ gender : typing.Optional[Gender]
191
+
192
+ age : typing.Optional[int]
193
+
194
+ request_options : typing.Optional[RequestOptions]
195
+ Request-specific configuration.
196
+
197
+ Returns
198
+ -------
199
+ HttpResponse[CreateTtsOut]
200
+ Successful Response
201
+ """
202
+ _response = self._client_wrapper.httpx_client.request(
203
+ "tts",
204
+ method="POST",
205
+ params={
206
+ "run_id": run_id,
207
+ },
208
+ json={
209
+ "project_name": project_name,
210
+ "project_description": project_description,
211
+ "folder_id": folder_id,
212
+ "text": text,
213
+ "voice_id": voice_id,
214
+ "language": language,
215
+ "gender": gender,
216
+ "age": age,
217
+ },
218
+ headers={
219
+ "content-type": "application/json",
220
+ },
221
+ request_options=request_options,
222
+ omit=OMIT,
223
+ )
224
+ try:
225
+ if 200 <= _response.status_code < 300:
226
+ _data = typing.cast(
227
+ CreateTtsOut,
228
+ parse_obj_as(
229
+ type_=CreateTtsOut, # type: ignore
230
+ object_=_response.json(),
231
+ ),
232
+ )
233
+ return HttpResponse(response=_response, data=_data)
234
+ if _response.status_code == 422:
235
+ raise UnprocessableEntityError(
236
+ headers=dict(_response.headers),
237
+ body=typing.cast(
238
+ HttpValidationError,
239
+ parse_obj_as(
240
+ type_=HttpValidationError, # type: ignore
241
+ object_=_response.json(),
242
+ ),
243
+ ),
244
+ )
245
+ _response_json = _response.json()
246
+ except JSONDecodeError:
247
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
248
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
249
+
250
+ def get_tts_result(
251
+ self,
252
+ task_id: str,
253
+ *,
254
+ run_id: typing.Optional[int] = None,
255
+ request_options: typing.Optional[RequestOptions] = None,
256
+ ) -> HttpResponse[OrchestratorPipelineResult]:
257
+ """
258
+ Parameters
259
+ ----------
260
+ task_id : str
261
+
262
+ run_id : typing.Optional[int]
263
+
264
+ request_options : typing.Optional[RequestOptions]
265
+ Request-specific configuration.
266
+
267
+ Returns
268
+ -------
269
+ HttpResponse[OrchestratorPipelineResult]
270
+ Successful Response
271
+ """
272
+ _response = self._client_wrapper.httpx_client.request(
273
+ f"tts/{jsonable_encoder(task_id)}",
274
+ method="GET",
275
+ params={
276
+ "run_id": run_id,
277
+ },
278
+ request_options=request_options,
279
+ )
280
+ try:
281
+ if 200 <= _response.status_code < 300:
282
+ _data = typing.cast(
283
+ OrchestratorPipelineResult,
284
+ parse_obj_as(
285
+ type_=OrchestratorPipelineResult, # type: ignore
286
+ object_=_response.json(),
287
+ ),
288
+ )
289
+ return HttpResponse(response=_response, data=_data)
290
+ if _response.status_code == 422:
291
+ raise UnprocessableEntityError(
292
+ headers=dict(_response.headers),
293
+ body=typing.cast(
294
+ HttpValidationError,
295
+ parse_obj_as(
296
+ type_=HttpValidationError, # type: ignore
297
+ object_=_response.json(),
298
+ ),
299
+ ),
300
+ )
301
+ _response_json = _response.json()
302
+ except JSONDecodeError:
303
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
304
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
305
+
306
+ def get_tts_run_info(
307
+ self,
308
+ run_id: typing.Optional[int],
309
+ *,
310
+ output_type: typing.Optional[str] = None,
311
+ request_options: typing.Optional[RequestOptions] = None,
312
+ ) -> HttpResponse[GetTtsRunInfoTtsResultRunIdGetResponse]:
313
+ """
314
+ Retrieves the result of a Text To Speech (TTS) run.
315
+
316
+ This endpoint validates the provided `run_id` and fetches the corresponding TTS-generated audio.
317
+ The user must have valid access to the run. The function supports two output formats:
318
+ - `RAW_BYTES`: Streams the audio file directly.
319
+ - `FILE_URL`: Returns a pre-signed URL to download the audio file.
320
+
321
+ Args:
322
+ run_id (int): Unique identifier for the TTS run.
323
+ api_key_obj (dict): API key object used for authentication and storage preferences.
324
+ traceparent (Optional[str]): Traceparent header for distributed tracing.
325
+ output_type (OutputType, optional): Determines the output format. Defaults to `RAW_BYTES`.
326
+
327
+ Returns:
328
+ StreamingResponse | GetTTSOut:
329
+ - If `output_type = RAW_BYTES`: A streaming response containing the TTS-generated audio in FLAC format.
330
+ - If `output_type = FILE_URL`: A URL pointing to the stored TTS-generated audio file.
331
+
332
+ Raises:
333
+ HTTPException:
334
+ - 400 BAD REQUEST if the run ID is invalid or does not belong to a TTS process.
335
+ - 500 INTERNAL SERVER ERROR if fetching or streaming the audio fails.
336
+
337
+ Assumptions:
338
+ - The user has valid access to the `run_id`.
339
+ - The `run_id` corresponds to a valid TTS run.
340
+ - There is only **one** dialogue associated with the given `run_id`.
341
+
342
+ Parameters
343
+ ----------
344
+ run_id : typing.Optional[int]
345
+
346
+ output_type : typing.Optional[str]
347
+ Output format for the Text To Speech result
348
+
349
+ request_options : typing.Optional[RequestOptions]
350
+ Request-specific configuration.
351
+
352
+ Returns
353
+ -------
354
+ HttpResponse[GetTtsRunInfoTtsResultRunIdGetResponse]
355
+ Successful Response
356
+ """
357
+ _response = self._client_wrapper.httpx_client.request(
358
+ f"tts-result/{jsonable_encoder(run_id)}",
359
+ method="GET",
360
+ params={
361
+ "output_type": output_type,
362
+ },
363
+ request_options=request_options,
364
+ )
365
+ try:
366
+ if 200 <= _response.status_code < 300:
367
+ _data = typing.cast(
368
+ GetTtsRunInfoTtsResultRunIdGetResponse,
369
+ parse_obj_as(
370
+ type_=GetTtsRunInfoTtsResultRunIdGetResponse, # type: ignore
371
+ object_=_response.json(),
372
+ ),
373
+ )
374
+ return HttpResponse(response=_response, data=_data)
375
+ if _response.status_code == 422:
376
+ raise UnprocessableEntityError(
377
+ headers=dict(_response.headers),
378
+ body=typing.cast(
379
+ HttpValidationError,
380
+ parse_obj_as(
381
+ type_=HttpValidationError, # type: ignore
382
+ object_=_response.json(),
383
+ ),
384
+ ),
385
+ )
386
+ _response_json = _response.json()
387
+ except JSONDecodeError:
388
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
389
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
390
+
391
+ def get_tts_results(
392
+ self,
393
+ *,
394
+ run_ids: typing.Sequence[int],
395
+ run_id: typing.Optional[int] = None,
396
+ traceparent: typing.Optional[str] = None,
397
+ request_options: typing.Optional[RequestOptions] = None,
398
+ ) -> HttpResponse[typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue]]:
399
+ """
400
+ Parameters
401
+ ----------
402
+ run_ids : typing.Sequence[int]
403
+
404
+ run_id : typing.Optional[int]
405
+
406
+ traceparent : typing.Optional[str]
407
+
408
+ request_options : typing.Optional[RequestOptions]
409
+ Request-specific configuration.
410
+
411
+ Returns
412
+ -------
413
+ HttpResponse[typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue]]
414
+ Successful Response
415
+ """
416
+ _response = self._client_wrapper.httpx_client.request(
417
+ "tts-results",
418
+ method="POST",
419
+ params={
420
+ "run_id": run_id,
421
+ },
422
+ json={
423
+ "run_ids": run_ids,
424
+ },
425
+ headers={
426
+ "content-type": "application/json",
427
+ "traceparent": str(traceparent) if traceparent is not None else None,
428
+ },
429
+ request_options=request_options,
430
+ omit=OMIT,
431
+ )
432
+ try:
433
+ if 200 <= _response.status_code < 300:
434
+ _data = typing.cast(
435
+ typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue],
436
+ parse_obj_as(
437
+ type_=typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue], # type: ignore
438
+ object_=_response.json(),
439
+ ),
440
+ )
441
+ return HttpResponse(response=_response, data=_data)
442
+ if _response.status_code == 422:
443
+ raise UnprocessableEntityError(
444
+ headers=dict(_response.headers),
445
+ body=typing.cast(
446
+ HttpValidationError,
447
+ parse_obj_as(
448
+ type_=HttpValidationError, # type: ignore
449
+ object_=_response.json(),
450
+ ),
451
+ ),
452
+ )
453
+ _response_json = _response.json()
454
+ except JSONDecodeError:
455
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
456
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
457
+
458
+ def get_tts_result_discord(
459
+ self,
460
+ task_id: str,
461
+ *,
462
+ run_id: typing.Optional[int] = None,
463
+ request_options: typing.Optional[RequestOptions] = None,
464
+ ) -> HttpResponse[OrchestratorPipelineResult]:
465
+ """
466
+ Parameters
467
+ ----------
468
+ task_id : str
469
+
470
+ run_id : typing.Optional[int]
471
+
472
+ request_options : typing.Optional[RequestOptions]
473
+ Request-specific configuration.
474
+
475
+ Returns
476
+ -------
477
+ HttpResponse[OrchestratorPipelineResult]
478
+ Successful Response
479
+ """
480
+ _response = self._client_wrapper.httpx_client.request(
481
+ f"discord/tts/{jsonable_encoder(task_id)}",
482
+ method="GET",
483
+ params={
484
+ "run_id": run_id,
485
+ },
486
+ request_options=request_options,
487
+ )
488
+ try:
489
+ if 200 <= _response.status_code < 300:
490
+ _data = typing.cast(
491
+ OrchestratorPipelineResult,
492
+ parse_obj_as(
493
+ type_=OrchestratorPipelineResult, # type: ignore
494
+ object_=_response.json(),
495
+ ),
496
+ )
497
+ return HttpResponse(response=_response, data=_data)
498
+ if _response.status_code == 422:
499
+ raise UnprocessableEntityError(
500
+ headers=dict(_response.headers),
501
+ body=typing.cast(
502
+ HttpValidationError,
503
+ parse_obj_as(
504
+ type_=HttpValidationError, # type: ignore
505
+ object_=_response.json(),
506
+ ),
507
+ ),
508
+ )
509
+ _response_json = _response.json()
510
+ except JSONDecodeError:
511
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
512
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
513
+
514
+
515
+ class AsyncRawTextToSpeechClient:
516
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
517
+ self._client_wrapper = client_wrapper
518
+
519
+ @contextlib.asynccontextmanager
520
+ async def tts(
521
+ self,
522
+ *,
523
+ text: str,
524
+ language: CreateStreamTtsRequestPayloadLanguage,
525
+ voice_id: typing.Optional[int] = OMIT,
526
+ speech_model: typing.Optional[CreateStreamTtsRequestPayloadSpeechModel] = OMIT,
527
+ user_instructions: typing.Optional[str] = OMIT,
528
+ enhance_named_entities_pronunciation: typing.Optional[bool] = OMIT,
529
+ output_configuration: typing.Optional[StreamTtsOutputConfiguration] = OMIT,
530
+ voice_settings: typing.Optional[StreamTtsVoiceSettings] = OMIT,
531
+ inference_options: typing.Optional[StreamTtsInferenceOptions] = OMIT,
532
+ request_options: typing.Optional[RequestOptions] = None,
533
+ ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]:
534
+ """
535
+ Parameters
536
+ ----------
537
+ text : str
538
+
539
+ language : CreateStreamTtsRequestPayloadLanguage
540
+
541
+ voice_id : int
542
+
543
+ speech_model : typing.Optional[CreateStreamTtsRequestPayloadSpeechModel]
544
+
545
+ user_instructions : typing.Optional[str]
546
+
547
+ enhance_named_entities_pronunciation : typing.Optional[bool]
548
+
549
+ output_configuration : typing.Optional[StreamTtsOutputConfiguration]
550
+
551
+ voice_settings : typing.Optional[StreamTtsVoiceSettings]
552
+
553
+ inference_options : typing.Optional[StreamTtsInferenceOptions]
554
+
555
+ request_options : typing.Optional[RequestOptions]
556
+ Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.
557
+
558
+ Returns
559
+ -------
560
+ typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]
561
+ Streaming audio response
562
+ """
563
+ if self._client_wrapper.tts_provider is None and (voice_id is OMIT or voice_id is None):
564
+ raise ValueError("voice_id is required when using the default Camb.ai provider.")
565
+
566
+ if self._client_wrapper.tts_provider == "baseten":
567
+ if speech_model == "mars-pro":
568
+ async with async_baseten_tts(
569
+ self._client_wrapper,
570
+ text=text,
571
+ language=language,
572
+ voice_id=voice_id,
573
+ speech_model=speech_model,
574
+ user_instructions=user_instructions,
575
+ enhance_named_entities_pronunciation=enhance_named_entities_pronunciation,
576
+ output_configuration=output_configuration,
577
+ voice_settings=voice_settings,
578
+ inference_options=inference_options,
579
+ request_options=request_options,
580
+ ) as r:
581
+ yield r
582
+ return
583
+ else:
584
+ raise ValueError("Baseten provider can only be used with 'mars-pro' speech model.")
585
+
586
+ async with self._client_wrapper.httpx_client.stream(
587
+ "tts-stream",
588
+ method="POST",
589
+ json={
590
+ "text": text,
591
+ "language": language,
592
+ "voice_id": voice_id,
593
+ "speech_model": speech_model,
594
+ "user_instructions": user_instructions,
595
+ "enhance_named_entities_pronunciation": enhance_named_entities_pronunciation,
596
+ "output_configuration": convert_and_respect_annotation_metadata(
597
+ object_=output_configuration, annotation=StreamTtsOutputConfiguration, direction="write"
598
+ ),
599
+ "voice_settings": convert_and_respect_annotation_metadata(
600
+ object_=voice_settings, annotation=StreamTtsVoiceSettings, direction="write"
601
+ ),
602
+ "inference_options": convert_and_respect_annotation_metadata(
603
+ object_=inference_options, annotation=StreamTtsInferenceOptions, direction="write"
604
+ ),
605
+ },
606
+ headers={
607
+ "content-type": "application/json",
608
+ },
609
+ request_options=request_options,
610
+ omit=OMIT,
611
+ ) as _response:
612
+
613
+ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]:
614
+ try:
615
+ if 200 <= _response.status_code < 300:
616
+ _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
617
+ return AsyncHttpResponse(
618
+ response=_response,
619
+ data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)),
620
+ )
621
+ await _response.aread()
622
+ if _response.status_code == 422:
623
+ raise UnprocessableEntityError(
624
+ headers=dict(_response.headers),
625
+ body=typing.cast(
626
+ HttpValidationError,
627
+ parse_obj_as(
628
+ type_=HttpValidationError, # type: ignore
629
+ object_=_response.json(),
630
+ ),
631
+ ),
632
+ )
633
+ _response_json = _response.json()
634
+ except JSONDecodeError:
635
+ raise ApiError(
636
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
637
+ )
638
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
639
+
640
+ yield await _stream()
641
+
642
+ async def create_tts(
643
+ self,
644
+ *,
645
+ text: str,
646
+ voice_id: int,
647
+ language: Languages,
648
+ run_id: typing.Optional[int] = None,
649
+ project_name: typing.Optional[str] = OMIT,
650
+ project_description: typing.Optional[str] = OMIT,
651
+ folder_id: typing.Optional[int] = OMIT,
652
+ gender: typing.Optional[Gender] = OMIT,
653
+ age: typing.Optional[int] = OMIT,
654
+ request_options: typing.Optional[RequestOptions] = None,
655
+ ) -> AsyncHttpResponse[CreateTtsOut]:
656
+ """
657
+ Parameters
658
+ ----------
659
+ text : str
660
+
661
+ voice_id : int
662
+
663
+ language : Languages
664
+
665
+ run_id : typing.Optional[int]
666
+
667
+ project_name : typing.Optional[str]
668
+
669
+ project_description : typing.Optional[str]
670
+
671
+ folder_id : typing.Optional[int]
672
+
673
+ gender : typing.Optional[Gender]
674
+
675
+ age : typing.Optional[int]
676
+
677
+ request_options : typing.Optional[RequestOptions]
678
+ Request-specific configuration.
679
+
680
+ Returns
681
+ -------
682
+ AsyncHttpResponse[CreateTtsOut]
683
+ Successful Response
684
+ """
685
+ _response = await self._client_wrapper.httpx_client.request(
686
+ "tts",
687
+ method="POST",
688
+ params={
689
+ "run_id": run_id,
690
+ },
691
+ json={
692
+ "project_name": project_name,
693
+ "project_description": project_description,
694
+ "folder_id": folder_id,
695
+ "text": text,
696
+ "voice_id": voice_id,
697
+ "language": language,
698
+ "gender": gender,
699
+ "age": age,
700
+ },
701
+ headers={
702
+ "content-type": "application/json",
703
+ },
704
+ request_options=request_options,
705
+ omit=OMIT,
706
+ )
707
+ try:
708
+ if 200 <= _response.status_code < 300:
709
+ _data = typing.cast(
710
+ CreateTtsOut,
711
+ parse_obj_as(
712
+ type_=CreateTtsOut, # type: ignore
713
+ object_=_response.json(),
714
+ ),
715
+ )
716
+ return AsyncHttpResponse(response=_response, data=_data)
717
+ if _response.status_code == 422:
718
+ raise UnprocessableEntityError(
719
+ headers=dict(_response.headers),
720
+ body=typing.cast(
721
+ HttpValidationError,
722
+ parse_obj_as(
723
+ type_=HttpValidationError, # type: ignore
724
+ object_=_response.json(),
725
+ ),
726
+ ),
727
+ )
728
+ _response_json = _response.json()
729
+ except JSONDecodeError:
730
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
731
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
732
+
733
+ async def get_tts_result(
734
+ self,
735
+ task_id: str,
736
+ *,
737
+ run_id: typing.Optional[int] = None,
738
+ request_options: typing.Optional[RequestOptions] = None,
739
+ ) -> AsyncHttpResponse[OrchestratorPipelineResult]:
740
+ """
741
+ Parameters
742
+ ----------
743
+ task_id : str
744
+
745
+ run_id : typing.Optional[int]
746
+
747
+ request_options : typing.Optional[RequestOptions]
748
+ Request-specific configuration.
749
+
750
+ Returns
751
+ -------
752
+ AsyncHttpResponse[OrchestratorPipelineResult]
753
+ Successful Response
754
+ """
755
+ _response = await self._client_wrapper.httpx_client.request(
756
+ f"tts/{jsonable_encoder(task_id)}",
757
+ method="GET",
758
+ params={
759
+ "run_id": run_id,
760
+ },
761
+ request_options=request_options,
762
+ )
763
+ try:
764
+ if 200 <= _response.status_code < 300:
765
+ _data = typing.cast(
766
+ OrchestratorPipelineResult,
767
+ parse_obj_as(
768
+ type_=OrchestratorPipelineResult, # type: ignore
769
+ object_=_response.json(),
770
+ ),
771
+ )
772
+ return AsyncHttpResponse(response=_response, data=_data)
773
+ if _response.status_code == 422:
774
+ raise UnprocessableEntityError(
775
+ headers=dict(_response.headers),
776
+ body=typing.cast(
777
+ HttpValidationError,
778
+ parse_obj_as(
779
+ type_=HttpValidationError, # type: ignore
780
+ object_=_response.json(),
781
+ ),
782
+ ),
783
+ )
784
+ _response_json = _response.json()
785
+ except JSONDecodeError:
786
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
787
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
788
+
789
+ async def get_tts_run_info(
790
+ self,
791
+ run_id: typing.Optional[int],
792
+ *,
793
+ output_type: typing.Optional[str] = None,
794
+ request_options: typing.Optional[RequestOptions] = None,
795
+ ) -> AsyncHttpResponse[GetTtsRunInfoTtsResultRunIdGetResponse]:
796
+ """
797
+ Retrieves the result of a Text To Speech (TTS) run.
798
+
799
+ This endpoint validates the provided `run_id` and fetches the corresponding TTS-generated audio.
800
+ The user must have valid access to the run. The function supports two output formats:
801
+ - `RAW_BYTES`: Streams the audio file directly.
802
+ - `FILE_URL`: Returns a pre-signed URL to download the audio file.
803
+
804
+ Args:
805
+ run_id (int): Unique identifier for the TTS run.
806
+ api_key_obj (dict): API key object used for authentication and storage preferences.
807
+ traceparent (Optional[str]): Traceparent header for distributed tracing.
808
+ output_type (OutputType, optional): Determines the output format. Defaults to `RAW_BYTES`.
809
+
810
+ Returns:
811
+ StreamingResponse | GetTTSOut:
812
+ - If `output_type = RAW_BYTES`: A streaming response containing the TTS-generated audio in FLAC format.
813
+ - If `output_type = FILE_URL`: A URL pointing to the stored TTS-generated audio file.
814
+
815
+ Raises:
816
+ HTTPException:
817
+ - 400 BAD REQUEST if the run ID is invalid or does not belong to a TTS process.
818
+ - 500 INTERNAL SERVER ERROR if fetching or streaming the audio fails.
819
+
820
+ Assumptions:
821
+ - The user has valid access to the `run_id`.
822
+ - The `run_id` corresponds to a valid TTS run.
823
+ - There is only **one** dialogue associated with the given `run_id`.
824
+
825
+ Parameters
826
+ ----------
827
+ run_id : typing.Optional[int]
828
+
829
+ output_type : typing.Optional[str]
830
+ Output format for the Text To Speech result
831
+
832
+ request_options : typing.Optional[RequestOptions]
833
+ Request-specific configuration.
834
+
835
+ Returns
836
+ -------
837
+ AsyncHttpResponse[GetTtsRunInfoTtsResultRunIdGetResponse]
838
+ Successful Response
839
+ """
840
+ _response = await self._client_wrapper.httpx_client.request(
841
+ f"tts-result/{jsonable_encoder(run_id)}",
842
+ method="GET",
843
+ params={
844
+ "output_type": output_type,
845
+ },
846
+ request_options=request_options,
847
+ )
848
+ try:
849
+ if 200 <= _response.status_code < 300:
850
+ _data = typing.cast(
851
+ GetTtsRunInfoTtsResultRunIdGetResponse,
852
+ parse_obj_as(
853
+ type_=GetTtsRunInfoTtsResultRunIdGetResponse, # type: ignore
854
+ object_=_response.json(),
855
+ ),
856
+ )
857
+ return AsyncHttpResponse(response=_response, data=_data)
858
+ if _response.status_code == 422:
859
+ raise UnprocessableEntityError(
860
+ headers=dict(_response.headers),
861
+ body=typing.cast(
862
+ HttpValidationError,
863
+ parse_obj_as(
864
+ type_=HttpValidationError, # type: ignore
865
+ object_=_response.json(),
866
+ ),
867
+ ),
868
+ )
869
+ _response_json = _response.json()
870
+ except JSONDecodeError:
871
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
872
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
873
+
874
+ async def get_tts_results(
875
+ self,
876
+ *,
877
+ run_ids: typing.Sequence[int],
878
+ run_id: typing.Optional[int] = None,
879
+ traceparent: typing.Optional[str] = None,
880
+ request_options: typing.Optional[RequestOptions] = None,
881
+ ) -> AsyncHttpResponse[typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue]]:
882
+ """
883
+ Parameters
884
+ ----------
885
+ run_ids : typing.Sequence[int]
886
+
887
+ run_id : typing.Optional[int]
888
+
889
+ traceparent : typing.Optional[str]
890
+
891
+ request_options : typing.Optional[RequestOptions]
892
+ Request-specific configuration.
893
+
894
+ Returns
895
+ -------
896
+ AsyncHttpResponse[typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue]]
897
+ Successful Response
898
+ """
899
+ _response = await self._client_wrapper.httpx_client.request(
900
+ "tts-results",
901
+ method="POST",
902
+ params={
903
+ "run_id": run_id,
904
+ },
905
+ json={
906
+ "run_ids": run_ids,
907
+ },
908
+ headers={
909
+ "content-type": "application/json",
910
+ "traceparent": str(traceparent) if traceparent is not None else None,
911
+ },
912
+ request_options=request_options,
913
+ omit=OMIT,
914
+ )
915
+ try:
916
+ if 200 <= _response.status_code < 300:
917
+ _data = typing.cast(
918
+ typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue],
919
+ parse_obj_as(
920
+ type_=typing.Dict[str, GetTtsResultsTtsResultsPostResponseValue], # type: ignore
921
+ object_=_response.json(),
922
+ ),
923
+ )
924
+ return AsyncHttpResponse(response=_response, data=_data)
925
+ if _response.status_code == 422:
926
+ raise UnprocessableEntityError(
927
+ headers=dict(_response.headers),
928
+ body=typing.cast(
929
+ HttpValidationError,
930
+ parse_obj_as(
931
+ type_=HttpValidationError, # type: ignore
932
+ object_=_response.json(),
933
+ ),
934
+ ),
935
+ )
936
+ _response_json = _response.json()
937
+ except JSONDecodeError:
938
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
939
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
940
+
941
+ async def get_tts_result_discord(
942
+ self,
943
+ task_id: str,
944
+ *,
945
+ run_id: typing.Optional[int] = None,
946
+ request_options: typing.Optional[RequestOptions] = None,
947
+ ) -> AsyncHttpResponse[OrchestratorPipelineResult]:
948
+ """
949
+ Parameters
950
+ ----------
951
+ task_id : str
952
+
953
+ run_id : typing.Optional[int]
954
+
955
+ request_options : typing.Optional[RequestOptions]
956
+ Request-specific configuration.
957
+
958
+ Returns
959
+ -------
960
+ AsyncHttpResponse[OrchestratorPipelineResult]
961
+ Successful Response
962
+ """
963
+ _response = await self._client_wrapper.httpx_client.request(
964
+ f"discord/tts/{jsonable_encoder(task_id)}",
965
+ method="GET",
966
+ params={
967
+ "run_id": run_id,
968
+ },
969
+ request_options=request_options,
970
+ )
971
+ try:
972
+ if 200 <= _response.status_code < 300:
973
+ _data = typing.cast(
974
+ OrchestratorPipelineResult,
975
+ parse_obj_as(
976
+ type_=OrchestratorPipelineResult, # type: ignore
977
+ object_=_response.json(),
978
+ ),
979
+ )
980
+ return AsyncHttpResponse(response=_response, data=_data)
981
+ if _response.status_code == 422:
982
+ raise UnprocessableEntityError(
983
+ headers=dict(_response.headers),
984
+ body=typing.cast(
985
+ HttpValidationError,
986
+ parse_obj_as(
987
+ type_=HttpValidationError, # type: ignore
988
+ object_=_response.json(),
989
+ ),
990
+ ),
991
+ )
992
+ _response_json = _response.json()
993
+ except JSONDecodeError:
994
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
995
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)