soniox 2.3.2__tar.gz → 2.5.0__tar.gz

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 (134) hide show
  1. soniox-2.5.0/.claude/settings.local.json +15 -0
  2. soniox-2.5.0/.github/ISSUE_TEMPLATE/bug_report.yml +81 -0
  3. soniox-2.5.0/.github/ISSUE_TEMPLATE/feature_request.yml +44 -0
  4. soniox-2.5.0/.github/PULL_REQUEST_TEMPLATE.md +27 -0
  5. soniox-2.5.0/.gitignore +15 -0
  6. soniox-2.5.0/CHANGELOG.md +203 -0
  7. soniox-2.5.0/CODE_OF_CONDUCT.md +39 -0
  8. soniox-2.5.0/CONTRIBUTING.md +56 -0
  9. {soniox-2.3.2 → soniox-2.5.0}/PKG-INFO +28 -15
  10. {soniox-2.3.2 → soniox-2.5.0}/README.md +19 -12
  11. soniox-2.5.0/SECURITY.md +14 -0
  12. {soniox-2.3.2 → soniox-2.5.0}/docs/async_client.md +410 -1
  13. {soniox-2.3.2 → soniox-2.5.0}/docs/realtime_client.md +639 -591
  14. {soniox-2.3.2 → soniox-2.5.0}/docs/types.md +370 -17
  15. soniox-2.5.0/docs/utils.md +201 -0
  16. {soniox-2.3.2 → soniox-2.5.0}/examples/async_soniox_client/tts_realtime_multiplexed_example.py +1 -1
  17. {soniox-2.3.2 → soniox-2.5.0}/justfile +25 -0
  18. {soniox-2.3.2 → soniox-2.5.0}/pyproject.toml +51 -6
  19. {soniox-2.3.2 → soniox-2.5.0}/scripts/generate_docs.py +47 -12
  20. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/__init__.py +8 -0
  21. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/_utils.py +36 -1
  22. soniox-2.5.0/src/soniox/api/async_concurrency_limits.py +30 -0
  23. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/async_files.py +13 -0
  24. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/async_stt.py +227 -2
  25. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/async_tts.py +1 -2
  26. soniox-2.5.0/src/soniox/api/async_usage_logs.py +77 -0
  27. soniox-2.5.0/src/soniox/api/concurrency_limits.py +30 -0
  28. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/files.py +13 -0
  29. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/stt.py +222 -2
  30. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/tts.py +1 -2
  31. soniox-2.5.0/src/soniox/api/usage_logs.py +76 -0
  32. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/client.py +28 -0
  33. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/errors.py +5 -2
  34. soniox-2.5.0/src/soniox/py.typed +0 -0
  35. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/realtime/_utils.py +10 -0
  36. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/realtime/async_stt.py +58 -15
  37. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/realtime/async_tts.py +67 -21
  38. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/realtime/stt.py +58 -16
  39. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/realtime/tts.py +56 -19
  40. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/types/__init__.py +52 -0
  41. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/types/api.py +252 -22
  42. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/types/realtime.py +37 -8
  43. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/utils.py +21 -6
  44. soniox-2.5.0/tests/__init__.py +0 -0
  45. soniox-2.5.0/tests/conftest.py +26 -0
  46. soniox-2.5.0/tests/data/openapi.json +1 -0
  47. soniox-2.5.0/tests/helpers.py +43 -0
  48. soniox-2.5.0/tests/realtime/__init__.py +0 -0
  49. soniox-2.5.0/tests/realtime/cases.py +84 -0
  50. soniox-2.5.0/tests/realtime/mock_ws.py +148 -0
  51. soniox-2.5.0/tests/realtime/test_async_tts_realtime.py +838 -0
  52. soniox-2.5.0/tests/realtime/test_chaos_realtime.py +157 -0
  53. soniox-2.5.0/tests/realtime/test_fuzz_realtime.py +98 -0
  54. soniox-2.5.0/tests/realtime/test_keepalive.py +118 -0
  55. soniox-2.5.0/tests/realtime/test_live_ws.py +267 -0
  56. soniox-2.5.0/tests/realtime/test_stt_realtime.py +642 -0
  57. soniox-2.5.0/tests/realtime/test_tts_realtime.py +791 -0
  58. soniox-2.5.0/tests/unit/__init__.py +0 -0
  59. soniox-2.5.0/tests/unit/_openapi.py +87 -0
  60. soniox-2.5.0/tests/unit/_sdk_bindings.py +215 -0
  61. soniox-2.5.0/tests/unit/test_api.py +250 -0
  62. soniox-2.5.0/tests/unit/test_async_client.py +231 -0
  63. soniox-2.5.0/tests/unit/test_async_stt_workflows.py +334 -0
  64. soniox-2.5.0/tests/unit/test_async_tts_workflows.py +111 -0
  65. soniox-2.5.0/tests/unit/test_client.py +227 -0
  66. soniox-2.5.0/tests/unit/test_concurrency_limits.py +58 -0
  67. soniox-2.5.0/tests/unit/test_coverage_gaps.py +174 -0
  68. soniox-2.5.0/tests/unit/test_schema_drift.py +94 -0
  69. soniox-2.5.0/tests/unit/test_stt_extras.py +151 -0
  70. soniox-2.5.0/tests/unit/test_stt_workflows.py +337 -0
  71. soniox-2.5.0/tests/unit/test_sync_async_parity.py +138 -0
  72. soniox-2.5.0/tests/unit/test_translate.py +280 -0
  73. soniox-2.5.0/tests/unit/test_tts_workflows.py +115 -0
  74. soniox-2.5.0/tests/unit/test_types.py +70 -0
  75. soniox-2.5.0/tests/unit/test_usage_logs.py +166 -0
  76. soniox-2.5.0/tests/unit/test_utils.py +332 -0
  77. soniox-2.5.0/tests/unit/test_webhooks.py +139 -0
  78. {soniox-2.3.2 → soniox-2.5.0}/uv.lock +338 -5
  79. soniox-2.3.2/.gitignore +0 -3
  80. soniox-2.3.2/CHANGELOG.md +0 -154
  81. soniox-2.3.2/docs/soniox/__init__.md +0 -282
  82. soniox-2.3.2/docs/soniox/api/__init__.md +0 -1968
  83. soniox-2.3.2/docs/soniox/api/api__utils.md +0 -112
  84. soniox-2.3.2/docs/soniox/api/api_async_auth.md +0 -61
  85. soniox-2.3.2/docs/soniox/api/api_async_files.md +0 -239
  86. soniox-2.3.2/docs/soniox/api/api_async_models.md +0 -55
  87. soniox-2.3.2/docs/soniox/api/api_async_stt.md +0 -595
  88. soniox-2.3.2/docs/soniox/api/api_async_transcriptions.md +0 -546
  89. soniox-2.3.2/docs/soniox/api/api_async_webhooks.md +0 -10
  90. soniox-2.3.2/docs/soniox/api/api_auth.md +0 -61
  91. soniox-2.3.2/docs/soniox/api/api_files.md +0 -239
  92. soniox-2.3.2/docs/soniox/api/api_models.md +0 -55
  93. soniox-2.3.2/docs/soniox/api/api_stt.md +0 -595
  94. soniox-2.3.2/docs/soniox/api/api_transcriptions.md +0 -546
  95. soniox-2.3.2/docs/soniox/api/api_webhooks.md +0 -152
  96. soniox-2.3.2/docs/soniox/realtime/__init__.md +0 -1148
  97. soniox-2.3.2/docs/soniox/realtime/realtime__utils.md +0 -194
  98. soniox-2.3.2/docs/soniox/realtime/realtime_async_stt.md +0 -548
  99. soniox-2.3.2/docs/soniox/realtime/realtime_stt.md +0 -546
  100. soniox-2.3.2/docs/soniox/soniox_client.md +0 -346
  101. soniox-2.3.2/docs/soniox/soniox_errors.md +0 -204
  102. soniox-2.3.2/docs/soniox/soniox_utils.md +0 -195
  103. soniox-2.3.2/docs/soniox/types/__init__.md +0 -532
  104. soniox-2.3.2/docs/soniox/types/types_api.md +0 -400
  105. soniox-2.3.2/docs/soniox/types/types_common.md +0 -34
  106. soniox-2.3.2/docs/soniox/types/types_realtime.md +0 -112
  107. soniox-2.3.2/docs/soniox/types/types_webhooks.md +0 -30
  108. {soniox-2.3.2 → soniox-2.5.0}/LICENSE +0 -0
  109. {soniox-2.3.2 → soniox-2.5.0}/assets/coffee_shop.mp3 +0 -0
  110. {soniox-2.3.2 → soniox-2.5.0}/assets/coffee_shop.pcm_s16le +0 -0
  111. {soniox-2.3.2 → soniox-2.5.0}/assets/two_way_translation.mp3 +0 -0
  112. {soniox-2.3.2 → soniox-2.5.0}/assets/two_way_translation.pcm_s16le +0 -0
  113. {soniox-2.3.2 → soniox-2.5.0}/examples/async_soniox_client/api_example.py +0 -0
  114. {soniox-2.3.2 → soniox-2.5.0}/examples/async_soniox_client/realtime_example.py +0 -0
  115. {soniox-2.3.2 → soniox-2.5.0}/examples/async_soniox_client/tts_api_example.py +0 -0
  116. {soniox-2.3.2 → soniox-2.5.0}/examples/async_soniox_client/tts_realtime_example.py +0 -0
  117. {soniox-2.3.2 → soniox-2.5.0}/examples/soniox_client/api_example.py +0 -0
  118. {soniox-2.3.2 → soniox-2.5.0}/examples/soniox_client/realtime_example.py +0 -0
  119. {soniox-2.3.2 → soniox-2.5.0}/examples/soniox_client/tts_api_example.py +0 -0
  120. {soniox-2.3.2 → soniox-2.5.0}/examples/soniox_client/tts_realtime_example.py +0 -0
  121. {soniox-2.3.2 → soniox-2.5.0}/examples/soniox_client/tts_realtime_multiplexed_example.py +0 -0
  122. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/__init__.py +0 -0
  123. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/async_auth.py +0 -0
  124. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/async_models.py +0 -0
  125. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/async_tts_models.py +0 -0
  126. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/async_webhooks.py +0 -0
  127. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/auth.py +0 -0
  128. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/models.py +0 -0
  129. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/tts_models.py +0 -0
  130. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/api/webhooks.py +0 -0
  131. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/realtime/__init__.py +0 -0
  132. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/realtime/_constants.py +0 -0
  133. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/types/common.py +0 -0
  134. {soniox-2.3.2 → soniox-2.5.0}/src/soniox/types/webhooks.py +0 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(uv run *)",
5
+ "Bash(just test *)",
6
+ "Bash(/home/miha/workspace/soniox_python_sdk/.venv/bin/python *)",
7
+ "Bash(git apply *)",
8
+ "Bash(git add *)",
9
+ "Bash(sed -n '110,140p' tests/unit/test_client.py)",
10
+ "Bash(sed -n '85,120p' tests/unit/test_async_client.py)",
11
+ "Bash(/tmp/soniox-v240-test/.venv/bin/python -u test_schema_sync.py)",
12
+ "Bash(awk '/^class Transcription\\\\b/,/^class [A-Z]/' src/soniox/types/api.py)"
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,81 @@
1
+ name: Bug report
2
+ description: Report something the SDK does wrong, or fails to do
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to file a bug. A **minimal** reproducer speeds things up significantly.
9
+
10
+ - type: checkboxes
11
+ id: non_api
12
+ attributes:
13
+ label: SDK or API?
14
+ description: For API-level problems such as transcription accuracy or server-side errors, please contact [support@soniox.com](mailto:support@soniox.com) instead.
15
+ options:
16
+ - label: I confirm this is an issue with the Python SDK, not the Soniox API.
17
+ required: true
18
+
19
+ - type: textarea
20
+ id: what_happened
21
+ attributes:
22
+ label: What happened?
23
+ description: What did you observe? What did you expect instead?
24
+ placeholder: |
25
+ Observed: ...
26
+ Expected: ...
27
+ validations:
28
+ required: true
29
+
30
+ - type: textarea
31
+ id: repro
32
+ attributes:
33
+ label: Minimal reproducer
34
+ description: The smallest script that triggers the issue. Strip out anything unrelated.
35
+ render: python
36
+ placeholder: |
37
+ from soniox import SonioxClient
38
+ ...
39
+ validations:
40
+ required: true
41
+
42
+ - type: textarea
43
+ id: traceback
44
+ attributes:
45
+ label: Logs or traceback
46
+ description: Full traceback or relevant log lines, if any.
47
+ render: shell
48
+ validations:
49
+ required: false
50
+
51
+ - type: input
52
+ id: sdk_version
53
+ attributes:
54
+ label: SDK version
55
+ placeholder: "soniox==2.4.0"
56
+ validations:
57
+ required: true
58
+
59
+ - type: input
60
+ id: python_version
61
+ attributes:
62
+ label: Python version
63
+ placeholder: "Python 3.12.3"
64
+ validations:
65
+ required: true
66
+
67
+ - type: input
68
+ id: os
69
+ attributes:
70
+ label: Operating system
71
+ placeholder: "Ubuntu 24.04 / macOS 15 / Windows 11"
72
+ validations:
73
+ required: true
74
+
75
+ - type: textarea
76
+ id: additional
77
+ attributes:
78
+ label: Additional context
79
+ description: Anything else relevant: timing patterns, frequency, workarounds you have tried.
80
+ validations:
81
+ required: false
@@ -0,0 +1,44 @@
1
+ name: Feature request
2
+ description: Propose a new capability or improvement
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Use this template to propose new SDK functionality or improvements to existing APIs.
9
+
10
+ - type: textarea
11
+ id: problem
12
+ attributes:
13
+ label: Problem
14
+ description: What are you trying to do? What does the SDK currently make hard or awkward?
15
+ validations:
16
+ required: true
17
+
18
+ - type: textarea
19
+ id: solution
20
+ attributes:
21
+ label: Proposed solution
22
+ description: The shape of the API or behavior you would like. Python sketches welcome.
23
+ render: python
24
+ placeholder: |
25
+ # What the call site could look like:
26
+ client.foo.bar(...)
27
+ validations:
28
+ required: true
29
+
30
+ - type: textarea
31
+ id: alternatives
32
+ attributes:
33
+ label: Alternatives considered
34
+ description: Other approaches you thought about, and why you do not prefer them.
35
+ validations:
36
+ required: false
37
+
38
+ - type: textarea
39
+ id: context
40
+ attributes:
41
+ label: Additional context
42
+ description: Links to similar features in other SDKs, related issues, or use-case background.
43
+ validations:
44
+ required: false
@@ -0,0 +1,27 @@
1
+ ## Summary
2
+
3
+ <!-- One or two sentences. What does this PR do, and why? -->
4
+
5
+ ## Type of change
6
+
7
+ - [ ] Bug fix
8
+ - [ ] New feature
9
+ - [ ] Breaking change
10
+ - [ ] Internal refactor
11
+ - [ ] Documentation
12
+
13
+ ## How to test
14
+
15
+ <!-- Steps a reviewer can run to verify the change. -->
16
+
17
+ ## Checklist
18
+
19
+ - [ ] Tests added or updated under `tests/unit/` or `tests/realtime/`.
20
+ - [ ] `just lint`, `just typecheck`, and `just test` all pass locally.
21
+ - [ ] `CHANGELOG.md` `[Unreleased]` section updated, if the change is user-visible.
22
+ - [ ] Reference docs regenerated with `just docs`, if public APIs changed.
23
+ - [ ] No leftover `print()` debug statements or commented-out code.
24
+
25
+ ## Related issues
26
+
27
+ <!-- Closes #123, refs #456 -->
@@ -0,0 +1,15 @@
1
+ dist
2
+ build
3
+ __pycache__
4
+ generated-docs
5
+
6
+ # Virtualenv
7
+ .venv
8
+
9
+ # Test / coverage artifacts
10
+ .coverage
11
+ .pytest_cache
12
+ htmlcov
13
+
14
+ # Local audio scratch
15
+ *.wav
@@ -0,0 +1,203 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is inspired by Keep a Changelog and this project follows Semantic Versioning.
6
+
7
+ ## Quick Guide for Contributors
8
+
9
+ - Every PR that changes behavior must update **[Unreleased]**.
10
+ - Write from the **user’s perspective** (what changed for SDK users).
11
+ - Keep entries short (one clear sentence).
12
+ - Use the correct section: **Added**, **Changed**, **Fixed**, **Deprecated**, **Removed**, **Security**.
13
+ - Avoid internal details or commit-style messages.
14
+
15
+ **Release process (maintainers):**
16
+
17
+ - Rename **[Unreleased]** → new version + date.
18
+ - Add a fresh empty **[Unreleased]** section at the top.
19
+
20
+ ### Version Categories Guide
21
+
22
+ Use the following categories when adding entries:
23
+
24
+ - **Added** - new features or capabilities.
25
+ - **Changed** - updates to existing functionality.
26
+ - **Deprecated** - features that will be removed soon.
27
+ - **Removed** - features removed in this version.
28
+ - **Fixed** - bug fixes.
29
+ - **Security** - vulnerability fixes.
30
+
31
+ ---
32
+
33
+ ### Writing Guidelines
34
+
35
+ - Write entries from the **user's perspective**, not implementation details.
36
+ - ✅ "Added async file uploads"
37
+ - ❌ "Refactored upload handler"
38
+
39
+ - Keep lines short and scannable.
40
+ - Group related changes into one bullet when possible.
41
+ - Avoid commit-message noise.
42
+ - Every released version should have a date.
43
+
44
+ ---
45
+
46
+ ### Versioning Notes
47
+
48
+ This project follows Semantic Versioning:
49
+
50
+ - **MAJOR** version when you make incompatible API changes.
51
+ - **MINOR** version when you add functionality in a backward-compatible manner.
52
+ - **PATCH** version when you make backward-compatible bug fixes.
53
+
54
+ Examples:
55
+
56
+ - `1.0.0` - stable API
57
+ - `1.1.0` - new features added
58
+ - `1.1.1` - bug fixes only
59
+
60
+ ---
61
+
62
+ ## [Unreleased]
63
+
64
+ ### Added
65
+
66
+ ### Changed
67
+
68
+ ### Deprecated
69
+
70
+ ### Fixed
71
+
72
+ ### Removed
73
+
74
+ ---
75
+
76
+ ## [2.5.0] - 12 jun 2026
77
+
78
+ ### Added
79
+
80
+ - `LanguageCode` type alias (`Annotated[str, Field(min_length=2, max_length=2)]`) representing an ISO 639-1 two-letter code. Now used by `TranslationConfig.target_language`, `language_a`, `language_b`, and by the `language_hints` lists on `CreateTranscriptionPayload`, `CreateTranscriptionConfig`, and `RealtimeSTTConfig`.
81
+ - `SupportedLanguage` model (renamed from `Language`) describing a `{code, name}` language entry returned by `client.models.list()`.
82
+ - `translate*` methods on the async and sync STT clients (`translate`, `translate_from_url`, `translate_from_file_id`, `translate_from_file`, `translate_and_wait`, `translate_and_wait_with_tokens`). Pass `to=` for one-way translation (optionally with `source=` as a strict language hint) or `between=("en", "fr")` for two-way; exactly one of `to` or `between` is required.
83
+ - `connect_timeout_sec` parameter on the realtime `connect()` and `connect_multi_stream()` methods (STT and TTS, sync and async): maximum seconds to wait for the WebSocket handshake. Defaults to 10 seconds; must be greater than zero. ([#4](https://github.com/soniox/soniox-python/pull/4) by [@imcooder](https://github.com/imcooder))
84
+
85
+ ### Changed
86
+
87
+ - Reorganized reference docs: `async_client.md` now documents only the async surface (the sync `SonioxClient` is a line-by-line mirror, called out in a preamble); `realtime_client.md` continues to cover both sync and async realtime clients.
88
+ - Expanded the `output_file_for_audio_format` docstring with a proper `Args` block.
89
+ - `language_hints` fields now validate each entry as a two-letter code; previously any string was accepted client-side.
90
+ - Realtime WebSocket connection failures now raise `SonioxRealtimeError` (with message `"Connection timed out"` when the handshake times out) instead of propagating raw `websockets` exceptions. ([#4](https://github.com/soniox/soniox-python/pull/4) by [@imcooder](https://github.com/imcooder))
91
+ - Default model for asynchronous transcriptions is now `stt-async-v5` (was `stt-async-v4`).
92
+
93
+ ### Deprecated
94
+
95
+ - `Language` is a deprecated alias for `SupportedLanguage`. Update imports to `from soniox.types import SupportedLanguage`.
96
+
97
+ ### Fixed
98
+
99
+ - Removed Sphinx `:meth:` directive leaks from realtime STT client docstrings; they were rendering as raw text in the generated markdown reference.
100
+ - `AsyncRealtimeTTSClient.connect_multi_stream()` now validates that an API key is available, matching the sync `RealtimeTTSClient.connect_multi_stream()`; previously it silently constructed a connection with an empty key.
101
+
102
+ ---
103
+
104
+ ## [2.4.0] - 13 may 2026
105
+
106
+ ### Added
107
+
108
+ - `client.files.count()` and `client.stt.count()` endpoints (and async variants) returning the total count of files and transcriptions.
109
+ - `client.usage_logs.list()` and `list_all()` (and async variants) for retrieving per-request usage logs over a time window.
110
+ - `client.concurrency_limits.get()` (and async variant) returning current and configured concurrency limits for realtime STT and TTS, scoped to project and organization.
111
+ - `TtsVoice.description` and `TtsVoice.gender` (`"male" | "female" | "neutral"`) fields, exposing richer voice metadata from the server. Enables programmatic voice filtering.
112
+ - `RealtimeSTTAudioFormat`, `RealtimeSTTHeaderFormat`, `RealtimeSTTRawFormat` literal types covering the 30 audio formats accepted by realtime STT.
113
+ - `py.typed` marker (PEP 561): downstream type-checkers now consume the SDK's inline type annotations.
114
+ - `StructuredContext.general` and `StructuredContext.translation_terms` now accept a plain dict in addition to the typed item lists.
115
+ - `finalize: bool = True` keyword-only parameter on realtime STT `pause()` (sync and async). When `False`, pause without emitting a finalize.
116
+ - `TtsModel.languages` field listing the languages supported by the model. Defaults to an empty list for backward compatibility with direct construction.
117
+ - `Language` type exported from `soniox.types` (previously only reachable via `soniox.types.api`).
118
+ - `ApiError.more_info` field - optional URL pointing to documentation for resolving an error.
119
+ - `Model.supports_max_endpoint_delay` flag indicating whether a model supports the `max_endpoint_delay_ms` option.
120
+ - Internal test suite (pytest + respx + polyfactory) covering REST, realtime websocket, schema drift, and sync/async parity. Not shipped to users; runnable via `just test`.
121
+
122
+ ### Changed
123
+
124
+ - `RealtimeSTTConfig.audio_format` is now typed as a Literal union instead of bare `str`. Passing an unrecognized value raises at validation time instead of failing on the wire.
125
+ - Raw realtime STT audio formats (`pcm_*`, `mulaw`, `alaw`) now require `sample_rate` and `num_channels` on `RealtimeSTTConfig`. Previously these were silently accepted client-side and rejected by the server.
126
+
127
+ ---
128
+
129
+ ## [2.3.2] - 4 may 2026
130
+
131
+ ### Added
132
+
133
+ - `single_use` and `max_session_duration_seconds` parameters on `client.auth.create_temporary_api_key()` (and the async variant).
134
+ - `tts_rt` value for `TemporaryApiKeyUsageType`, allowing temporary API keys to be scoped to realtime TTS.
135
+
136
+ ---
137
+
138
+ ## [2.3.1] - 29 apr 2026
139
+
140
+ ### Changed
141
+
142
+ - Default TTS model is now `tts-rt-v1` (previously `tts-rt-v1-preview`).
143
+
144
+ ---
145
+
146
+ ## [2.3.0] - 22 apr 2026
147
+
148
+ ### Added
149
+
150
+ - Text-to-Speech (TTS) support, available on both `SonioxClient` and `AsyncSonioxClient`.
151
+ - REST TTS API via `client.tts`: `generate()` returns audio bytes, `generate_to_file()` writes audio to a path or file-like object. Configurable `voice`, `model`, `language`, `audio_format`, `sample_rate`, and `bitrate`.
152
+ - TTS model listing via `client.tts_models.list()`.
153
+ - Realtime TTS over websocket via `client.realtime.tts.connect(...)`: stream text in with `send_text_chunk` / `send_text_chunks` / `finish`, receive audio with `receive_audio_chunks` or raw events with `receive_events`, plus `cancel`, `pause`, `resume`, and `keep_alive`.
154
+ - Multiplexed realtime TTS via `client.realtime.tts.connect_multi_stream()`: run multiple concurrent TTS streams over a single websocket connection using `open_stream`.
155
+ - New TTS examples for sync and async clients (REST, realtime, and multiplexed realtime).
156
+ - `tts_api_base_url` and `tts_websocket_base_url` client options for overriding TTS endpoints.
157
+
158
+ ---
159
+
160
+ ## [2.2.0] - 25 feb 2026
161
+
162
+ ### Added
163
+
164
+ - max_endpoint_delay_ms parameter (v4 model only)
165
+ - fin (<fin>) and end (<end>) constants
166
+ - validation for TranslationConfig
167
+
168
+ ### Changed
169
+
170
+ - Improved docs generating script
171
+
172
+ ---
173
+
174
+ ## [2.1.0] - 18 feb 2026
175
+
176
+ ### Added
177
+
178
+ - pause and resume methods
179
+ - destroy_all method (removes all transcriptions and all files)
180
+ - send_bytes accepts finish parameter
181
+
182
+ ### Changed
183
+
184
+ - renamed client.transcriptions to 'client.stt'
185
+ - removed send\_ prefix from methods (i.e. send_keep_alive -> keep_alive)
186
+
187
+ ### Removed
188
+
189
+ - keep alive helpers (use pause, resume, or manually send keepalive message)
190
+
191
+ ---
192
+
193
+ ## [2.0.0] - 3 feb 2026
194
+
195
+ ### Added
196
+
197
+ - Initial public release of the Python SDK.
198
+ - Core client implementation (sync and async).
199
+ - Full support for REST API and websocket API
200
+
201
+ ### Removed
202
+
203
+ - Old Soniox Python SDK (versions 1._._)
@@ -0,0 +1,39 @@
1
+ # Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We pledge to make participation in this project a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our standards
10
+
11
+ Behavior that contributes to a positive environment includes:
12
+
13
+ - Using welcoming and inclusive language.
14
+ - Respecting differing viewpoints and experiences.
15
+ - Accepting constructive criticism gracefully.
16
+ - Focusing on what is best for the community.
17
+ - Showing empathy toward other community members.
18
+
19
+ Unacceptable behavior includes:
20
+
21
+ - Sexualized language or imagery, and unwelcome sexual attention or advances.
22
+ - Trolling, insulting or derogatory comments, and personal or political attacks.
23
+ - Public or private harassment.
24
+ - Publishing others' private information, such as a physical or email address, without their explicit permission.
25
+ - Other conduct that could reasonably be considered inappropriate in a professional setting.
26
+
27
+ ## Scope
28
+
29
+ This Code of Conduct applies on GitHub, Discord, and any other channel where someone is representing the project.
30
+
31
+ ## Reporting and enforcement
32
+
33
+ Report incidents to [support@soniox.com](mailto:support@soniox.com). All reports are reviewed and investigated promptly and fairly. We respect the privacy of reporters.
34
+
35
+ Maintainers are responsible for clarifying and enforcing these standards, and may take corrective action in response to behavior they consider inappropriate.
36
+
37
+ ## Attribution
38
+
39
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1, available at <https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
@@ -0,0 +1,56 @@
1
+ # Contributing
2
+
3
+ Contributions are welcome. PRs that are small, typed, and tested move through review fastest.
4
+
5
+ By participating in this project, you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md).
6
+
7
+ ## Development setup
8
+
9
+ Install [uv](https://docs.astral.sh/uv/) and [just](https://github.com/casey/just), then:
10
+
11
+ ```bash
12
+ git clone https://github.com/soniox/soniox-python
13
+ cd soniox-python
14
+ uv sync --extra dev
15
+ ```
16
+
17
+ > Python 3.13.6 has a regression in the `ssl` module that hangs realtime WebSocket sessions ([CPython #137583](https://github.com/python/cpython/issues/137583)). For local development, use Python 3.10 through 3.12, or 3.13.5 / 3.13.7 and later.
18
+
19
+ Day-to-day commands:
20
+
21
+ ```bash
22
+ just test # full test suite
23
+ just lint # ruff
24
+ just typecheck # pyright
25
+ just docs # regenerate docs/*.md from source
26
+ ```
27
+
28
+ ## Opening a pull request
29
+
30
+ Open PRs against the `dev` branch. `main` tracks releases.
31
+
32
+ Before you push:
33
+
34
+ 1. Keep the PR focused. One bug fix, one feature, or one refactor. Mixed PRs are slower to review.
35
+ 2. Add tests. New endpoints belong in `tests/unit/`; realtime helpers belong in `tests/realtime/`.
36
+ 3. Run `just lint`, `just typecheck`, and `just test`. All three must pass before review.
37
+ 4. Maintain coverage above the threshold set in `pyproject.toml`.
38
+ 5. Update the `[Unreleased]` section of `CHANGELOG.md` for any user-visible change. Categorize as Added, Changed, Fixed, or Removed.
39
+ 6. If you changed public APIs, regenerate the reference docs with `just docs`.
40
+
41
+ To pick up a newer OpenAPI schema, run `just download-schema`. This pulls the latest `openapi.json` into `tests/data/`. The `test_schema_drift.py` suite then reports missing fields and changed signatures automatically.
42
+
43
+ ## Conventions
44
+
45
+ - `ruff` handles formatting and lint rules; the configuration lives in `pyproject.toml`.
46
+ - `pyright` runs in strict mode against `src/`. Tests have a narrower config in the same file.
47
+ - Write docstrings in plain markdown with backticks for code references. Do not use Sphinx directives such as `:meth:` or `:param:`. They leak as raw text into the generated reference.
48
+ - Write comments to explain why, not what. Well-named identifiers already say what the code does.
49
+
50
+ ## Reporting bugs
51
+
52
+ File issues at [github.com/soniox/soniox-python/issues](https://github.com/soniox/soniox-python/issues) using the bug report template. Include the SDK version, the Python version, and a minimal reproducer.
53
+
54
+ ## Reporting security issues
55
+
56
+ Do not file a public issue for security vulnerabilities. See [SECURITY.md](SECURITY.md) for the channels we monitor.
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soniox
3
- Version: 2.3.2
3
+ Version: 2.5.0
4
4
  Summary: The official Python SDK for the Soniox API (STT, REST)
5
- Project-URL: Homepage, https://sonoix.com
5
+ Project-URL: Homepage, https://soniox.com
6
6
  Project-URL: Documentation, https://soniox.com/docs
7
7
  Project-URL: Repository, https://github.com/soniox/soniox-python
8
8
  Author-email: Soniox <support@soniox.com>
@@ -31,13 +31,20 @@ Requires-Dist: pydantic>2
31
31
  Requires-Dist: websockets>11.0
32
32
  Provides-Extra: dev
33
33
  Requires-Dist: griffe>=1.15.0; extra == 'dev'
34
- Requires-Dist: pyright>=1.1.0; extra == 'dev'
34
+ Requires-Dist: polyfactory>=2.15.0; extra == 'dev'
35
+ Requires-Dist: pyright>=1.1.409; extra == 'dev'
36
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
37
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
38
+ Requires-Dist: pytest-timeout>=2.3; extra == 'dev'
39
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
40
+ Requires-Dist: respx>=0.21.1; extra == 'dev'
35
41
  Requires-Dist: ruff>=0.0.0; extra == 'dev'
36
42
  Description-Content-Type: text/markdown
37
43
 
38
44
  # Soniox Python SDK
39
45
 
40
46
  The SDK exposes two clients: `SonioxClient` (sync) and `AsyncSonioxClient` (async). Each client supports:
47
+
41
48
  - STT over REST (`client.stt`) and realtime WebSocket (`client.realtime.stt`)
42
49
  - TTS over REST (`client.tts`) and realtime WebSocket (`client.realtime.tts`)
43
50
  - auth, file uploads, model listing, webhooks, and typed request/response models
@@ -53,20 +60,23 @@ export SONIOX_API_KEY=<your-key>
53
60
 
54
61
  Get your API key from the [Soniox Console](https://console.soniox.com) and inject it once per shell session. Both clients read `SONIOX_API_KEY` by default, but you can override it per-client if needed.
55
62
 
63
+ > **Avoid Python 3.13.6** - it has a regression in `ssl` that hangs realtime STT/TTS (CPython issue [#137583](https://github.com/python/cpython/issues/137583)). Use any other 3.10-3.13.x.
64
+
56
65
  ## Quick run (STT + TTS, REST + realtime)
57
66
 
58
- 1. **REST STT transcription**: copy this snippet or run [`examples/soniox_client/api_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/api_example.py).
67
+ 1. **REST STT transcription**: transcribe a local file end-to-end in one call. Full example: [`examples/soniox_client/api_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/api_example.py).
59
68
 
60
69
  ```python
61
70
  from soniox import SonioxClient
62
71
 
63
72
  client = SonioxClient()
64
- transcription = client.stt.transcribe(
65
- audio_url="https://soniox.com/media/examples/coffee_shop.mp3",
66
- client_reference_id="docs-quick-start",
73
+ transcript = client.stt.transcribe_and_wait_with_tokens(
74
+ file="path/to/audio.mp3", # local file
75
+ # audio_url="https://example.com/audio.mp3", # or remote URL
76
+ delete_after=True, # auto-cleanup file + transcription
67
77
  )
68
- client.stt.wait(transcription.id, timeout_sec=60)
69
- print(client.stt.get_transcript(transcription.id).text[:200])
78
+ print(transcript.text)
79
+ client.close()
70
80
  ```
71
81
 
72
82
  2. **REST TTS generation**: convert text to an audio file.
@@ -118,17 +128,19 @@ def realtime():
118
128
  non_final_tokens.clear()
119
129
 
120
130
  realtime()
131
+ client.close()
121
132
  ```
122
133
 
123
134
  See [`examples/soniox_client/realtime_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/realtime_example.py) for the full flow.
124
135
 
125
- 4. **Realtime TTS streaming**: send text chunks and read generated audio chunks from the session.
136
+ 4. **Realtime TTS streaming**: send text chunks and write audio to a file as it arrives.
126
137
 
127
138
  ```python
128
139
  from uuid import uuid4
129
140
 
130
141
  from soniox import SonioxClient
131
142
  from soniox.types import RealtimeTTSConfig
143
+ from soniox.utils import output_file_for_audio_format
132
144
 
133
145
  client = SonioxClient()
134
146
  config = RealtimeTTSConfig(
@@ -139,17 +151,18 @@ config = RealtimeTTSConfig(
139
151
  audio_format="wav",
140
152
  )
141
153
 
142
- audio_chunks: list[bytes] = []
143
- with client.realtime.tts.connect(config=config) as session:
144
- session.keep_alive()
154
+ output_file = output_file_for_audio_format("wav", "tts_realtime_output")
155
+ bytes_written = 0
156
+ with client.realtime.tts.connect(config=config) as session, output_file.open("wb") as f:
145
157
  session.send_text_chunks(
146
158
  ["Hello from realtime TTS. ", "This is the final chunk."],
147
159
  text_end=True,
148
160
  )
149
161
  for chunk in session.receive_audio_chunks():
150
- audio_chunks.append(chunk)
162
+ f.write(chunk)
163
+ bytes_written += len(chunk)
151
164
 
152
- print(f"Collected {sum(len(c) for c in audio_chunks)} bytes of audio")
165
+ print(f"Wrote {bytes_written} bytes to {output_file.resolve()}")
153
166
  ```
154
167
 
155
168
  Run the full example at [`examples/soniox_client/tts_realtime_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/tts_realtime_example.py) or async version at [`examples/async_soniox_client/tts_realtime_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/async_soniox_client/tts_realtime_example.py).
@@ -1,6 +1,7 @@
1
1
  # Soniox Python SDK
2
2
 
3
3
  The SDK exposes two clients: `SonioxClient` (sync) and `AsyncSonioxClient` (async). Each client supports:
4
+
4
5
  - STT over REST (`client.stt`) and realtime WebSocket (`client.realtime.stt`)
5
6
  - TTS over REST (`client.tts`) and realtime WebSocket (`client.realtime.tts`)
6
7
  - auth, file uploads, model listing, webhooks, and typed request/response models
@@ -16,20 +17,23 @@ export SONIOX_API_KEY=<your-key>
16
17
 
17
18
  Get your API key from the [Soniox Console](https://console.soniox.com) and inject it once per shell session. Both clients read `SONIOX_API_KEY` by default, but you can override it per-client if needed.
18
19
 
20
+ > **Avoid Python 3.13.6** - it has a regression in `ssl` that hangs realtime STT/TTS (CPython issue [#137583](https://github.com/python/cpython/issues/137583)). Use any other 3.10-3.13.x.
21
+
19
22
  ## Quick run (STT + TTS, REST + realtime)
20
23
 
21
- 1. **REST STT transcription**: copy this snippet or run [`examples/soniox_client/api_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/api_example.py).
24
+ 1. **REST STT transcription**: transcribe a local file end-to-end in one call. Full example: [`examples/soniox_client/api_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/api_example.py).
22
25
 
23
26
  ```python
24
27
  from soniox import SonioxClient
25
28
 
26
29
  client = SonioxClient()
27
- transcription = client.stt.transcribe(
28
- audio_url="https://soniox.com/media/examples/coffee_shop.mp3",
29
- client_reference_id="docs-quick-start",
30
+ transcript = client.stt.transcribe_and_wait_with_tokens(
31
+ file="path/to/audio.mp3", # local file
32
+ # audio_url="https://example.com/audio.mp3", # or remote URL
33
+ delete_after=True, # auto-cleanup file + transcription
30
34
  )
31
- client.stt.wait(transcription.id, timeout_sec=60)
32
- print(client.stt.get_transcript(transcription.id).text[:200])
35
+ print(transcript.text)
36
+ client.close()
33
37
  ```
34
38
 
35
39
  2. **REST TTS generation**: convert text to an audio file.
@@ -81,17 +85,19 @@ def realtime():
81
85
  non_final_tokens.clear()
82
86
 
83
87
  realtime()
88
+ client.close()
84
89
  ```
85
90
 
86
91
  See [`examples/soniox_client/realtime_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/realtime_example.py) for the full flow.
87
92
 
88
- 4. **Realtime TTS streaming**: send text chunks and read generated audio chunks from the session.
93
+ 4. **Realtime TTS streaming**: send text chunks and write audio to a file as it arrives.
89
94
 
90
95
  ```python
91
96
  from uuid import uuid4
92
97
 
93
98
  from soniox import SonioxClient
94
99
  from soniox.types import RealtimeTTSConfig
100
+ from soniox.utils import output_file_for_audio_format
95
101
 
96
102
  client = SonioxClient()
97
103
  config = RealtimeTTSConfig(
@@ -102,17 +108,18 @@ config = RealtimeTTSConfig(
102
108
  audio_format="wav",
103
109
  )
104
110
 
105
- audio_chunks: list[bytes] = []
106
- with client.realtime.tts.connect(config=config) as session:
107
- session.keep_alive()
111
+ output_file = output_file_for_audio_format("wav", "tts_realtime_output")
112
+ bytes_written = 0
113
+ with client.realtime.tts.connect(config=config) as session, output_file.open("wb") as f:
108
114
  session.send_text_chunks(
109
115
  ["Hello from realtime TTS. ", "This is the final chunk."],
110
116
  text_end=True,
111
117
  )
112
118
  for chunk in session.receive_audio_chunks():
113
- audio_chunks.append(chunk)
119
+ f.write(chunk)
120
+ bytes_written += len(chunk)
114
121
 
115
- print(f"Collected {sum(len(c) for c in audio_chunks)} bytes of audio")
122
+ print(f"Wrote {bytes_written} bytes to {output_file.resolve()}")
116
123
  ```
117
124
 
118
125
  Run the full example at [`examples/soniox_client/tts_realtime_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/soniox_client/tts_realtime_example.py) or async version at [`examples/async_soniox_client/tts_realtime_example.py`](https://github.com/soniox/soniox-python/blob/main/examples/async_soniox_client/tts_realtime_example.py).