orbitalsai 1.1.0__tar.gz → 1.2.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.
- orbitalsai-1.2.0/PKG-INFO +850 -0
- orbitalsai-1.2.0/README.md +790 -0
- orbitalsai-1.2.0/examples/streaming_async.py +116 -0
- orbitalsai-1.2.0/examples/streaming_callbacks.py +115 -0
- orbitalsai-1.2.0/examples/streaming_microphone.py +165 -0
- orbitalsai-1.2.0/examples/streaming_sync.py +169 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai/__init__.py +24 -2
- orbitalsai-1.2.0/orbitalsai/streaming/__init__.py +117 -0
- orbitalsai-1.2.0/orbitalsai/streaming/async_client.py +507 -0
- orbitalsai-1.2.0/orbitalsai/streaming/audio/__init__.py +33 -0
- orbitalsai-1.2.0/orbitalsai/streaming/audio/buffer.py +171 -0
- orbitalsai-1.2.0/orbitalsai/streaming/audio/converter.py +327 -0
- orbitalsai-1.2.0/orbitalsai/streaming/audio/formats.py +112 -0
- orbitalsai-1.2.0/orbitalsai/streaming/audio/source.py +317 -0
- orbitalsai-1.2.0/orbitalsai/streaming/client.py +384 -0
- orbitalsai-1.2.0/orbitalsai/streaming/config.py +207 -0
- orbitalsai-1.2.0/orbitalsai/streaming/connection.py +298 -0
- orbitalsai-1.2.0/orbitalsai/streaming/events.py +360 -0
- orbitalsai-1.2.0/orbitalsai/streaming/exceptions.py +179 -0
- orbitalsai-1.2.0/orbitalsai/streaming/protocol.py +245 -0
- orbitalsai-1.2.0/orbitalsai.egg-info/PKG-INFO +850 -0
- orbitalsai-1.2.0/orbitalsai.egg-info/SOURCES.txt +42 -0
- orbitalsai-1.2.0/orbitalsai.egg-info/requires.txt +30 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/pyproject.toml +23 -3
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/setup.py +1 -1
- orbitalsai-1.1.0/PKG-INFO +0 -491
- orbitalsai-1.1.0/README.md +0 -448
- orbitalsai-1.1.0/orbitalsai.egg-info/PKG-INFO +0 -491
- orbitalsai-1.1.0/orbitalsai.egg-info/SOURCES.txt +0 -25
- orbitalsai-1.1.0/orbitalsai.egg-info/requires.txt +0 -10
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/.gitignore +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/LICENSE +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/examples/async_transcribe.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/examples/error_handling.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/examples/manage_balance.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/examples/model_selection.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/examples/model_selection_async.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/examples/simple_transcribe.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/examples/with_srt.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai/async_client.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai/client.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai/exceptions.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai/models.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai/utils.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai.egg-info/dependency_links.txt +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/orbitalsai.egg-info/top_level.txt +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/setup.cfg +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/test_model_update.py +0 -0
- {orbitalsai-1.1.0 → orbitalsai-1.2.0}/tests/test_client.py +0 -0
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: orbitalsai
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: A simple and powerful Python SDK for the OrbitalsAI API with real-time streaming support
|
|
5
|
+
Home-page: https://github.com/orbitalsai/orbitalsai-python-sdk
|
|
6
|
+
Author: OrbitalsAI
|
|
7
|
+
Author-email: OrbitalsAI <support@orbitalsai.com>
|
|
8
|
+
Maintainer-email: OrbitalsAI <support@orbitalsai.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Project-URL: Homepage, https://github.com/orbitalsai/orbitalsai-python-sdk
|
|
11
|
+
Project-URL: Documentation, https://docs.orbitalsai.com
|
|
12
|
+
Project-URL: Repository, https://github.com/orbitalsai/orbitalsai-python-sdk
|
|
13
|
+
Project-URL: Bug Tracker, https://github.com/orbitalsai/orbitalsai-python-sdk/issues
|
|
14
|
+
Keywords: ai,transcription,audio,speech,african languages,srt,subtitles,streaming,real-time,websocket
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
27
|
+
Requires-Python: >=3.8
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: requests>=2.25.0
|
|
31
|
+
Requires-Dist: aiohttp>=3.8.0
|
|
32
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
33
|
+
Requires-Dist: websockets>=11.0.0
|
|
34
|
+
Requires-Dist: numpy>=1.19.0
|
|
35
|
+
Provides-Extra: streaming
|
|
36
|
+
Requires-Dist: websockets>=11.0.0; extra == "streaming"
|
|
37
|
+
Requires-Dist: numpy>=1.19.0; extra == "streaming"
|
|
38
|
+
Provides-Extra: audio
|
|
39
|
+
Requires-Dist: sounddevice>=0.4.0; extra == "audio"
|
|
40
|
+
Requires-Dist: soundfile>=0.12.0; extra == "audio"
|
|
41
|
+
Requires-Dist: librosa>=0.10.0; extra == "audio"
|
|
42
|
+
Provides-Extra: all
|
|
43
|
+
Requires-Dist: websockets>=11.0.0; extra == "all"
|
|
44
|
+
Requires-Dist: numpy>=1.19.0; extra == "all"
|
|
45
|
+
Requires-Dist: sounddevice>=0.4.0; extra == "all"
|
|
46
|
+
Requires-Dist: soundfile>=0.12.0; extra == "all"
|
|
47
|
+
Requires-Dist: librosa>=0.10.0; extra == "all"
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
50
|
+
Requires-Dist: pytest-asyncio>=0.18.0; extra == "dev"
|
|
51
|
+
Requires-Dist: black>=21.0; extra == "dev"
|
|
52
|
+
Requires-Dist: flake8>=3.9; extra == "dev"
|
|
53
|
+
Requires-Dist: mypy>=0.910; extra == "dev"
|
|
54
|
+
Requires-Dist: websockets>=11.0.0; extra == "dev"
|
|
55
|
+
Requires-Dist: numpy>=1.19.0; extra == "dev"
|
|
56
|
+
Dynamic: author
|
|
57
|
+
Dynamic: home-page
|
|
58
|
+
Dynamic: license-file
|
|
59
|
+
Dynamic: requires-python
|
|
60
|
+
|
|
61
|
+
# OrbitalsAI Python SDK
|
|
62
|
+
|
|
63
|
+
[](https://badge.fury.io/py/orbitalsai)
|
|
64
|
+
[](https://pypi.org/project/orbitalsai/)
|
|
65
|
+
[](https://opensource.org/licenses/MIT)
|
|
66
|
+
|
|
67
|
+
Python SDK for the OrbitalsAI API. Transcribe audio files in African languages with SRT subtitle generation and real-time streaming via WebSocket.
|
|
68
|
+
|
|
69
|
+
## Features
|
|
70
|
+
|
|
71
|
+
- **Batch Transcription** - Upload files and get transcripts
|
|
72
|
+
- **Real-time Streaming** - Live transcription via WebSocket
|
|
73
|
+
- **Sync & Async** - Works synchronously or asynchronously
|
|
74
|
+
- **African Languages** - Hausa, Igbo, Yoruba, Swahili, Pidgin, Kinyarwanda, English
|
|
75
|
+
- **SRT Subtitles** - Generate subtitle files
|
|
76
|
+
- **Microphone Input** - Stream from microphone
|
|
77
|
+
- **Usage Tracking** - Check balance and usage history
|
|
78
|
+
- **Auto-Reconnect** - Automatic reconnection on connection loss
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
### Installation
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install orbitalsai
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
For streaming with audio file support:
|
|
89
|
+
```bash
|
|
90
|
+
pip install orbitalsai[audio]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Basic Usage (Batch)
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import orbitalsai
|
|
97
|
+
|
|
98
|
+
# Initialize client
|
|
99
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
100
|
+
|
|
101
|
+
# Transcribe audio (waits automatically)
|
|
102
|
+
transcript = client.transcribe("audio.mp3")
|
|
103
|
+
print(transcript.text)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Real-time Streaming
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import asyncio
|
|
110
|
+
from orbitalsai.streaming import AsyncStreamingClient, PrintingEventHandlers
|
|
111
|
+
|
|
112
|
+
async def main():
|
|
113
|
+
async with AsyncStreamingClient(api_key="your_api_key") as client:
|
|
114
|
+
await client.connect(PrintingEventHandlers())
|
|
115
|
+
|
|
116
|
+
with open("audio.pcm", "rb") as f:
|
|
117
|
+
while chunk := f.read(16000):
|
|
118
|
+
await client.send_audio(chunk)
|
|
119
|
+
|
|
120
|
+
await client.flush()
|
|
121
|
+
|
|
122
|
+
asyncio.run(main())
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
That's it.
|
|
126
|
+
|
|
127
|
+
## Table of Contents
|
|
128
|
+
|
|
129
|
+
- [Installation](#installation)
|
|
130
|
+
- [Quick Start](#quick-start)
|
|
131
|
+
- [Authentication](#authentication)
|
|
132
|
+
- [Basic Transcription](#basic-transcription)
|
|
133
|
+
- [Real-time Streaming](#real-time-streaming)
|
|
134
|
+
- [Model Selection](#model-selection)
|
|
135
|
+
- [Async Usage](#async-usage)
|
|
136
|
+
- [Balance Management](#balance-management)
|
|
137
|
+
- [Error Handling](#error-handling)
|
|
138
|
+
- [API Reference](#api-reference)
|
|
139
|
+
- [Supported Languages](#supported-languages)
|
|
140
|
+
- [Supported Formats](#supported-formats)
|
|
141
|
+
- [Troubleshooting](#troubleshooting)
|
|
142
|
+
|
|
143
|
+
## Authentication
|
|
144
|
+
|
|
145
|
+
Get your API key from the [OrbitalsAI Dashboard](https://dashboard.orbitalsai.com).
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
import orbitalsai
|
|
149
|
+
|
|
150
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Basic Transcription
|
|
154
|
+
|
|
155
|
+
### Simple Transcription
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
import orbitalsai
|
|
159
|
+
|
|
160
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
161
|
+
|
|
162
|
+
# Transcribe audio file
|
|
163
|
+
transcript = client.transcribe("audio.mp3")
|
|
164
|
+
print(transcript.text)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### With Language and SRT
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
import orbitalsai
|
|
171
|
+
|
|
172
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
173
|
+
|
|
174
|
+
# Transcribe in Hausa with SRT subtitles
|
|
175
|
+
transcript = client.transcribe(
|
|
176
|
+
"audio.mp3",
|
|
177
|
+
language="hausa",
|
|
178
|
+
generate_srt=True
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
print(transcript.text)
|
|
182
|
+
print(transcript.srt_content) # SRT subtitle content
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Real-time Streaming
|
|
188
|
+
|
|
189
|
+
Stream audio and receive transcriptions in real-time via WebSocket.
|
|
190
|
+
|
|
191
|
+
### Installation
|
|
192
|
+
|
|
193
|
+
Streaming requires additional dependencies:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Basic streaming
|
|
197
|
+
pip install orbitalsai
|
|
198
|
+
|
|
199
|
+
# With audio file conversion (MP3, WAV, etc.)
|
|
200
|
+
pip install orbitalsai[audio]
|
|
201
|
+
|
|
202
|
+
# With microphone support
|
|
203
|
+
pip install sounddevice
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Async Streaming (Recommended)
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
import asyncio
|
|
210
|
+
from orbitalsai.streaming import (
|
|
211
|
+
AsyncStreamingClient,
|
|
212
|
+
StreamingConfig,
|
|
213
|
+
PrintingEventHandlers,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
async def main():
|
|
217
|
+
# Configure streaming
|
|
218
|
+
config = StreamingConfig(
|
|
219
|
+
language="english",
|
|
220
|
+
sample_rate=16000,
|
|
221
|
+
interim_results=True, # Get partial transcripts
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
async with AsyncStreamingClient(api_key="your_key", config=config) as client:
|
|
225
|
+
await client.connect(PrintingEventHandlers())
|
|
226
|
+
|
|
227
|
+
# Stream raw PCM audio
|
|
228
|
+
with open("audio.pcm", "rb") as f:
|
|
229
|
+
while chunk := f.read(16000): # 500ms chunks
|
|
230
|
+
await client.send_audio(chunk)
|
|
231
|
+
await asyncio.sleep(0.5) # Real-time pacing
|
|
232
|
+
|
|
233
|
+
await client.flush()
|
|
234
|
+
|
|
235
|
+
asyncio.run(main())
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Synchronous Streaming
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
import time
|
|
242
|
+
from orbitalsai.streaming import StreamingClient, StreamingEventHandlers
|
|
243
|
+
|
|
244
|
+
class MyHandlers(StreamingEventHandlers):
|
|
245
|
+
def on_transcript_partial(self, text):
|
|
246
|
+
print(f"Partial: {text}")
|
|
247
|
+
|
|
248
|
+
def on_transcript_final(self, text, metadata):
|
|
249
|
+
print(f"Final: {text}")
|
|
250
|
+
print(f"Cost: ${metadata['cost']:.4f}")
|
|
251
|
+
|
|
252
|
+
with StreamingClient(api_key="your_key") as client:
|
|
253
|
+
client.connect(MyHandlers())
|
|
254
|
+
|
|
255
|
+
with open("audio.pcm", "rb") as f:
|
|
256
|
+
while chunk := f.read(16000):
|
|
257
|
+
client.send_audio(chunk)
|
|
258
|
+
time.sleep(0.5)
|
|
259
|
+
|
|
260
|
+
client.flush()
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Stream from Audio Files (MP3, WAV, etc.)
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
import asyncio
|
|
267
|
+
from orbitalsai.streaming import (
|
|
268
|
+
AsyncStreamingClient,
|
|
269
|
+
PrintingEventHandlers,
|
|
270
|
+
AudioConverter,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
async def stream_file(file_path: str):
|
|
274
|
+
# Convert any audio format to PCM16
|
|
275
|
+
audio_bytes, sample_rate = AudioConverter.from_file(
|
|
276
|
+
file_path,
|
|
277
|
+
target_sample_rate=16000
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# Split into chunks
|
|
281
|
+
chunks = AudioConverter.split_chunks(audio_bytes, chunk_size=8000)
|
|
282
|
+
|
|
283
|
+
async with AsyncStreamingClient(api_key="your_key") as client:
|
|
284
|
+
await client.connect(PrintingEventHandlers())
|
|
285
|
+
|
|
286
|
+
for chunk in chunks:
|
|
287
|
+
await client.send_audio(chunk)
|
|
288
|
+
await asyncio.sleep(0.5)
|
|
289
|
+
|
|
290
|
+
await client.flush()
|
|
291
|
+
|
|
292
|
+
asyncio.run(stream_file("speech.mp3"))
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Stream from Microphone
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
import asyncio
|
|
299
|
+
import numpy as np
|
|
300
|
+
import sounddevice as sd
|
|
301
|
+
from orbitalsai.streaming import AsyncStreamingClient, PrintingEventHandlers
|
|
302
|
+
|
|
303
|
+
async def stream_microphone(duration: int = 30):
|
|
304
|
+
audio_queue = asyncio.Queue()
|
|
305
|
+
|
|
306
|
+
def callback(indata, frames, time_info, status):
|
|
307
|
+
audio_queue.put_nowait(indata.tobytes())
|
|
308
|
+
|
|
309
|
+
async with AsyncStreamingClient(api_key="your_key") as client:
|
|
310
|
+
await client.connect(PrintingEventHandlers())
|
|
311
|
+
|
|
312
|
+
with sd.InputStream(
|
|
313
|
+
samplerate=16000,
|
|
314
|
+
channels=1,
|
|
315
|
+
dtype="int16",
|
|
316
|
+
blocksize=8000,
|
|
317
|
+
callback=callback
|
|
318
|
+
):
|
|
319
|
+
end_time = asyncio.get_event_loop().time() + duration
|
|
320
|
+
|
|
321
|
+
while asyncio.get_event_loop().time() < end_time:
|
|
322
|
+
audio = await asyncio.wait_for(audio_queue.get(), timeout=1.0)
|
|
323
|
+
await client.send_audio(audio)
|
|
324
|
+
|
|
325
|
+
await client.flush()
|
|
326
|
+
|
|
327
|
+
asyncio.run(stream_microphone(30))
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Custom Event Handlers
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
from orbitalsai.streaming import StreamingEventHandlers
|
|
334
|
+
|
|
335
|
+
class MyHandlers(StreamingEventHandlers):
|
|
336
|
+
def __init__(self):
|
|
337
|
+
self.transcripts = []
|
|
338
|
+
self.total_cost = 0.0
|
|
339
|
+
|
|
340
|
+
def on_open(self, session_info):
|
|
341
|
+
print(f"Connected: {session_info['session_id']}")
|
|
342
|
+
|
|
343
|
+
def on_transcript_partial(self, text):
|
|
344
|
+
# Partial transcripts may change
|
|
345
|
+
print(f"[Partial] {text}")
|
|
346
|
+
|
|
347
|
+
def on_transcript_final(self, text, metadata):
|
|
348
|
+
# Final transcripts are stable
|
|
349
|
+
self.transcripts.append(text)
|
|
350
|
+
self.total_cost += metadata["cost"]
|
|
351
|
+
print(f"[Final] {text}")
|
|
352
|
+
print(f" Cost: ${metadata['cost']:.4f}")
|
|
353
|
+
print(f" Duration: {metadata['audio_seconds']:.1f}s")
|
|
354
|
+
|
|
355
|
+
def on_speech_start(self):
|
|
356
|
+
print("🎤 Speech detected")
|
|
357
|
+
|
|
358
|
+
def on_speech_end(self):
|
|
359
|
+
print("🔇 Silence detected")
|
|
360
|
+
|
|
361
|
+
def on_credits_warning(self, remaining_percent):
|
|
362
|
+
print(f"⚠️ Credits low: {remaining_percent}% remaining")
|
|
363
|
+
|
|
364
|
+
def on_credits_exhausted(self):
|
|
365
|
+
print("❌ Credits exhausted!")
|
|
366
|
+
|
|
367
|
+
def on_error(self, error):
|
|
368
|
+
print(f"Error: {error}")
|
|
369
|
+
|
|
370
|
+
def on_close(self, code, reason):
|
|
371
|
+
print(f"Disconnected: {reason}")
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Callback-style Handlers
|
|
375
|
+
|
|
376
|
+
For simpler use cases, use `CallbackEventHandlers`:
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
from orbitalsai.streaming import AsyncStreamingClient, CallbackEventHandlers
|
|
380
|
+
|
|
381
|
+
handlers = CallbackEventHandlers(
|
|
382
|
+
on_final=lambda text, meta: print(f"Transcript: {text}"),
|
|
383
|
+
on_error=lambda e: print(f"Error: {e}"),
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
async with AsyncStreamingClient(api_key="your_key") as client:
|
|
387
|
+
await client.connect(handlers)
|
|
388
|
+
# ... stream audio ...
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Accumulate Transcripts
|
|
392
|
+
|
|
393
|
+
Use `StreamingTranscriptAccumulator` to collect all transcripts:
|
|
394
|
+
|
|
395
|
+
```python
|
|
396
|
+
from orbitalsai.streaming import StreamingClient, StreamingTranscriptAccumulator
|
|
397
|
+
|
|
398
|
+
accumulator = StreamingTranscriptAccumulator()
|
|
399
|
+
|
|
400
|
+
with StreamingClient(api_key="your_key") as client:
|
|
401
|
+
client.connect(accumulator)
|
|
402
|
+
# ... stream audio ...
|
|
403
|
+
client.flush()
|
|
404
|
+
|
|
405
|
+
# Get results
|
|
406
|
+
print(accumulator.get_full_transcript())
|
|
407
|
+
print(f"Total cost: ${accumulator.total_cost:.4f}")
|
|
408
|
+
print(f"Total duration: {accumulator.total_seconds:.1f}s")
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Streaming Configuration
|
|
412
|
+
|
|
413
|
+
```python
|
|
414
|
+
from orbitalsai.streaming import StreamingConfig
|
|
415
|
+
|
|
416
|
+
config = StreamingConfig(
|
|
417
|
+
# Audio settings
|
|
418
|
+
sample_rate=16000, # 8000-48000 Hz (16kHz recommended)
|
|
419
|
+
chunk_size=8000, # Samples per chunk (500ms at 16kHz)
|
|
420
|
+
|
|
421
|
+
# Language
|
|
422
|
+
language="english", # english, hausa, igbo, yoruba
|
|
423
|
+
|
|
424
|
+
# Connection settings
|
|
425
|
+
max_retries=5, # Reconnection attempts
|
|
426
|
+
retry_delay=1.0, # Initial retry delay (exponential backoff)
|
|
427
|
+
connection_timeout=30.0, # Connection timeout in seconds
|
|
428
|
+
|
|
429
|
+
# Processing
|
|
430
|
+
interim_results=True, # Receive partial transcripts
|
|
431
|
+
)
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Dynamic Configuration
|
|
435
|
+
|
|
436
|
+
Change language or sample rate during streaming:
|
|
437
|
+
|
|
438
|
+
```python
|
|
439
|
+
await client.configure(language="hausa")
|
|
440
|
+
await client.configure(sample_rate=8000)
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## Model Selection
|
|
446
|
+
|
|
447
|
+
Choose which model to use for transcription. Different models have different pricing.
|
|
448
|
+
|
|
449
|
+
### List Available Models
|
|
450
|
+
|
|
451
|
+
```python
|
|
452
|
+
import orbitalsai
|
|
453
|
+
|
|
454
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
455
|
+
|
|
456
|
+
# Get all available models
|
|
457
|
+
models = client.get_models()
|
|
458
|
+
|
|
459
|
+
for model in models:
|
|
460
|
+
print(f"{model.model_name}: ${model.transcription_rate_per_hour:.2f}/hour")
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Transcribe with Specific Model
|
|
464
|
+
|
|
465
|
+
```python
|
|
466
|
+
import orbitalsai
|
|
467
|
+
|
|
468
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
469
|
+
|
|
470
|
+
# Transcribe with Perigee-1 model
|
|
471
|
+
transcript = client.transcribe(
|
|
472
|
+
"audio.mp3",
|
|
473
|
+
language="hausa",
|
|
474
|
+
model_name="Perigee-1" # Specify the model
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
print(transcript.text)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Choose Model Based on Budget
|
|
481
|
+
|
|
482
|
+
```python
|
|
483
|
+
import orbitalsai
|
|
484
|
+
|
|
485
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
486
|
+
|
|
487
|
+
# Get the cheapest available model
|
|
488
|
+
models = client.get_models()
|
|
489
|
+
cheapest_model = min(models, key=lambda m: m.transcription_rate_per_hour)
|
|
490
|
+
|
|
491
|
+
print(f"Using {cheapest_model.model_name} at ${cheapest_model.transcription_rate_per_hour:.2f}/hour")
|
|
492
|
+
|
|
493
|
+
transcript = client.transcribe(
|
|
494
|
+
"audio.mp3",
|
|
495
|
+
language="english",
|
|
496
|
+
model_name=cheapest_model.model_name
|
|
497
|
+
)
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
## Async Usage
|
|
501
|
+
|
|
502
|
+
For processing multiple files or use in async applications.
|
|
503
|
+
|
|
504
|
+
```python
|
|
505
|
+
import asyncio
|
|
506
|
+
import orbitalsai
|
|
507
|
+
|
|
508
|
+
async def main():
|
|
509
|
+
async with orbitalsai.AsyncClient(api_key="your_api_key_here") as client:
|
|
510
|
+
# List available models
|
|
511
|
+
models = await client.get_models()
|
|
512
|
+
print(f"Available models: {[m.model_name for m in models]}")
|
|
513
|
+
|
|
514
|
+
# Transcribe multiple files concurrently
|
|
515
|
+
tasks = await asyncio.gather(
|
|
516
|
+
client.transcribe("audio1.mp3", model_name="Perigee-1"),
|
|
517
|
+
client.transcribe("audio2.wav", model_name="Perigee-1"),
|
|
518
|
+
client.transcribe("audio3.m4a", model_name="Perigee-1")
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
for transcript in tasks:
|
|
522
|
+
print(transcript.text)
|
|
523
|
+
|
|
524
|
+
asyncio.run(main())
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
## Balance Management
|
|
528
|
+
|
|
529
|
+
### Check Balance
|
|
530
|
+
|
|
531
|
+
```python
|
|
532
|
+
import orbitalsai
|
|
533
|
+
|
|
534
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
535
|
+
|
|
536
|
+
balance = client.get_balance()
|
|
537
|
+
print(f"Current balance: ${balance.balance:.2f}")
|
|
538
|
+
print(f"Last updated: {balance.last_updated}")
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### Usage History
|
|
542
|
+
|
|
543
|
+
```python
|
|
544
|
+
import orbitalsai
|
|
545
|
+
from datetime import date, timedelta
|
|
546
|
+
|
|
547
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
548
|
+
|
|
549
|
+
# Get last 7 days of usage
|
|
550
|
+
end_date = date.today()
|
|
551
|
+
start_date = end_date - timedelta(days=7)
|
|
552
|
+
|
|
553
|
+
usage = client.get_daily_usage(start_date=start_date, end_date=end_date)
|
|
554
|
+
print(f"Total cost: ${usage.total_cost:.2f}")
|
|
555
|
+
print(f"Total audio processed: {usage.total_audio_seconds:.1f} seconds")
|
|
556
|
+
|
|
557
|
+
for day in usage.daily_records:
|
|
558
|
+
print(f"{day.date}: ${day.total_cost:.4f} ({day.transcription_usage:.1f}s transcription)")
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
## Other Features
|
|
562
|
+
|
|
563
|
+
### List All Tasks
|
|
564
|
+
|
|
565
|
+
```python
|
|
566
|
+
import orbitalsai
|
|
567
|
+
|
|
568
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
569
|
+
|
|
570
|
+
tasks = client.list_tasks()
|
|
571
|
+
for task in tasks:
|
|
572
|
+
print(f"Task {task.task_id}: {task.status} - {task.original_filename}")
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Get User Information
|
|
576
|
+
|
|
577
|
+
```python
|
|
578
|
+
import orbitalsai
|
|
579
|
+
|
|
580
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
581
|
+
|
|
582
|
+
user = client.get_user()
|
|
583
|
+
print(f"User: {user.first_name} {user.last_name} ({user.email})")
|
|
584
|
+
print(f"Verified: {user.is_verified}")
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## Error Handling
|
|
588
|
+
|
|
589
|
+
### Batch Transcription Errors
|
|
590
|
+
|
|
591
|
+
```python
|
|
592
|
+
import orbitalsai
|
|
593
|
+
from orbitalsai.exceptions import (
|
|
594
|
+
AuthenticationError, InsufficientBalanceError,
|
|
595
|
+
UnsupportedFileError, UnsupportedLanguageError,
|
|
596
|
+
TranscriptionError, TimeoutError
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
client = orbitalsai.Client(api_key="your_api_key_here")
|
|
600
|
+
|
|
601
|
+
try:
|
|
602
|
+
transcript = client.transcribe("audio.mp3", language="hausa")
|
|
603
|
+
print(transcript.text)
|
|
604
|
+
|
|
605
|
+
except UnsupportedFileError:
|
|
606
|
+
print("File format not supported")
|
|
607
|
+
except UnsupportedLanguageError:
|
|
608
|
+
print("Language not supported")
|
|
609
|
+
except InsufficientBalanceError:
|
|
610
|
+
print("Not enough credits")
|
|
611
|
+
except AuthenticationError:
|
|
612
|
+
print("Invalid API key")
|
|
613
|
+
except TranscriptionError as e:
|
|
614
|
+
print(f"Transcription failed: {e}")
|
|
615
|
+
except TimeoutError:
|
|
616
|
+
print("Transcription timed out")
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### Streaming Errors
|
|
620
|
+
|
|
621
|
+
```python
|
|
622
|
+
from orbitalsai.streaming import AsyncStreamingClient, StreamingEventHandlers
|
|
623
|
+
from orbitalsai.streaming.exceptions import (
|
|
624
|
+
ConnectionError,
|
|
625
|
+
AuthenticationError,
|
|
626
|
+
InsufficientCreditsError,
|
|
627
|
+
ReconnectionFailedError,
|
|
628
|
+
SessionClosedError,
|
|
629
|
+
)
|
|
630
|
+
|
|
631
|
+
class MyHandlers(StreamingEventHandlers):
|
|
632
|
+
def on_error(self, error):
|
|
633
|
+
if isinstance(error, AuthenticationError):
|
|
634
|
+
print("Invalid API key")
|
|
635
|
+
elif isinstance(error, InsufficientCreditsError):
|
|
636
|
+
print("Credits exhausted - please top up")
|
|
637
|
+
elif isinstance(error, ReconnectionFailedError):
|
|
638
|
+
print(f"Failed to reconnect after {error.attempts} attempts")
|
|
639
|
+
else:
|
|
640
|
+
print(f"Error: {error}")
|
|
641
|
+
|
|
642
|
+
try:
|
|
643
|
+
async with AsyncStreamingClient(api_key="your_key") as client:
|
|
644
|
+
await client.connect(MyHandlers())
|
|
645
|
+
# ... stream audio ...
|
|
646
|
+
except ConnectionError as e:
|
|
647
|
+
print(f"Connection failed: {e}")
|
|
648
|
+
except SessionClosedError:
|
|
649
|
+
print("Session was closed")
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
## API Reference
|
|
653
|
+
|
|
654
|
+
### Batch Client Methods
|
|
655
|
+
|
|
656
|
+
#### `get_models()`
|
|
657
|
+
Get all available AI models with their pricing information.
|
|
658
|
+
|
|
659
|
+
**Returns:** List of `Model` objects
|
|
660
|
+
|
|
661
|
+
#### `transcribe(file_path, language="english", generate_srt=False, model_name="Perigee-1", wait=True, timeout=300, poll_interval=5)`
|
|
662
|
+
Transcribe an audio file.
|
|
663
|
+
|
|
664
|
+
**Parameters:**
|
|
665
|
+
- `file_path` (str): Path to the audio file
|
|
666
|
+
- `language` (str): Language code (default: "english")
|
|
667
|
+
- `generate_srt` (bool): Generate SRT subtitles (default: False)
|
|
668
|
+
- `model_name` (str): AI model to use (default: "Perigee-1")
|
|
669
|
+
- `wait` (bool): Wait for completion (default: True)
|
|
670
|
+
- `timeout` (int): Maximum wait time in seconds (default: 300)
|
|
671
|
+
- `poll_interval` (int): Seconds between status checks (default: 5)
|
|
672
|
+
|
|
673
|
+
**Returns:** `Transcript` object (if wait=True) or `TranscriptTask` object (if wait=False)
|
|
674
|
+
|
|
675
|
+
#### `get_task(task_id)`
|
|
676
|
+
Get the status of a transcription task.
|
|
677
|
+
|
|
678
|
+
**Returns:** `TranscriptTask` object
|
|
679
|
+
|
|
680
|
+
#### `wait_for_task(task_id, timeout=300, poll_interval=5)`
|
|
681
|
+
Wait for a task to complete.
|
|
682
|
+
|
|
683
|
+
**Returns:** `Transcript` object
|
|
684
|
+
|
|
685
|
+
#### `list_tasks()`
|
|
686
|
+
Get all transcription tasks for the current user.
|
|
687
|
+
|
|
688
|
+
**Returns:** List of `TranscriptTask` objects
|
|
689
|
+
|
|
690
|
+
#### `get_balance()`
|
|
691
|
+
Get the current user's balance.
|
|
692
|
+
|
|
693
|
+
**Returns:** `Balance` object
|
|
694
|
+
|
|
695
|
+
#### `get_daily_usage(start_date=None, end_date=None, page=1, page_size=30)`
|
|
696
|
+
Get daily usage history for the current user.
|
|
697
|
+
|
|
698
|
+
**Returns:** `DailyUsage` object
|
|
699
|
+
|
|
700
|
+
#### `get_user()`
|
|
701
|
+
Get current user details.
|
|
702
|
+
|
|
703
|
+
**Returns:** `User` object
|
|
704
|
+
|
|
705
|
+
### Streaming Client Methods
|
|
706
|
+
|
|
707
|
+
#### `connect(handlers)`
|
|
708
|
+
Establish WebSocket connection and start receiving events.
|
|
709
|
+
|
|
710
|
+
**Parameters:**
|
|
711
|
+
- `handlers` (StreamingEventHandlers): Event handler instance
|
|
712
|
+
|
|
713
|
+
#### `send_audio(audio_data)`
|
|
714
|
+
Send PCM16 audio chunk.
|
|
715
|
+
|
|
716
|
+
**Parameters:**
|
|
717
|
+
- `audio_data` (bytes): Raw PCM16 mono little-endian bytes
|
|
718
|
+
|
|
719
|
+
#### `configure(language=None, sample_rate=None)`
|
|
720
|
+
Update session configuration dynamically.
|
|
721
|
+
|
|
722
|
+
#### `flush()`
|
|
723
|
+
Force transcription of remaining audio buffer.
|
|
724
|
+
|
|
725
|
+
#### `disconnect()`
|
|
726
|
+
Close connection gracefully.
|
|
727
|
+
|
|
728
|
+
### Data Models
|
|
729
|
+
|
|
730
|
+
#### `Transcript`
|
|
731
|
+
- `text` (str): Transcribed text
|
|
732
|
+
- `srt_content` (str, optional): SRT subtitle content
|
|
733
|
+
- `task_id` (int): Task ID
|
|
734
|
+
- `original_filename` (str): Original filename
|
|
735
|
+
- `audio_url` (str, optional): URL to processed audio
|
|
736
|
+
|
|
737
|
+
#### `TranscriptTask`
|
|
738
|
+
- `task_id` (int): Task ID
|
|
739
|
+
- `status` (str): Task status ("pending", "processing", "completed", "failed")
|
|
740
|
+
- `original_filename` (str): Original filename
|
|
741
|
+
- `audio_url` (str, optional): URL to processed audio
|
|
742
|
+
- `srt_requested` (bool): Whether SRT was requested
|
|
743
|
+
- `result_text` (str, optional): Transcribed text
|
|
744
|
+
- `srt_content` (str, optional): SRT subtitle content
|
|
745
|
+
- `error` (str, optional): Error message if failed
|
|
746
|
+
|
|
747
|
+
#### `Balance`
|
|
748
|
+
- `balance` (float): Current balance in credits
|
|
749
|
+
- `last_updated` (datetime): Last update timestamp
|
|
750
|
+
|
|
751
|
+
#### `Model`
|
|
752
|
+
- `id` (int): Model ID
|
|
753
|
+
- `model_name` (str): Name of the model (e.g., "Perigee-1")
|
|
754
|
+
- `transcription_rate_per_second` (float): Cost per second of audio
|
|
755
|
+
- `transcription_rate_per_hour` (float): Cost per hour of audio
|
|
756
|
+
- `is_active` (bool): Whether the model is currently available
|
|
757
|
+
|
|
758
|
+
#### `StreamingConfig`
|
|
759
|
+
- `sample_rate` (int): Audio sample rate (8000-48000 Hz)
|
|
760
|
+
- `chunk_size` (int): Samples per chunk
|
|
761
|
+
- `language` (str): Transcription language
|
|
762
|
+
- `max_retries` (int): Maximum reconnection attempts
|
|
763
|
+
- `retry_delay` (float): Initial retry delay
|
|
764
|
+
- `connection_timeout` (float): Connection timeout
|
|
765
|
+
- `interim_results` (bool): Whether to receive partial transcripts
|
|
766
|
+
|
|
767
|
+
## Supported Languages
|
|
768
|
+
|
|
769
|
+
| Language | Code |
|
|
770
|
+
|----------|------|
|
|
771
|
+
| English | `english` |
|
|
772
|
+
| Hausa | `hausa` |
|
|
773
|
+
| Igbo | `igbo` |
|
|
774
|
+
| Yoruba | `yoruba` |
|
|
775
|
+
| Swahili | `swahili` |
|
|
776
|
+
| Pidgin | `pidgin` |
|
|
777
|
+
| Kinyarwanda | `kinyarwanda` |
|
|
778
|
+
|
|
779
|
+
## Supported Formats
|
|
780
|
+
|
|
781
|
+
### Batch Transcription
|
|
782
|
+
- WAV (`.wav`, `.wave`)
|
|
783
|
+
- MP3 (`.mp3`, `.mpeg`)
|
|
784
|
+
- OGG (`.ogg`, `.oga`)
|
|
785
|
+
- FLAC (`.flac`)
|
|
786
|
+
- AAC (`.aac`)
|
|
787
|
+
- M4A (`.m4a`)
|
|
788
|
+
- WMA (`.wma`)
|
|
789
|
+
- AMR (`.amr`)
|
|
790
|
+
- 3GP (`.3gp`)
|
|
791
|
+
|
|
792
|
+
### Streaming
|
|
793
|
+
- **Input:** PCM16 mono little-endian (raw bytes)
|
|
794
|
+
- **Conversion supported:** All batch formats via `AudioConverter`
|
|
795
|
+
|
|
796
|
+
### Maximum File Size (Batch)
|
|
797
|
+
- **200 MB** per file
|
|
798
|
+
|
|
799
|
+
## Troubleshooting
|
|
800
|
+
|
|
801
|
+
### Common Issues
|
|
802
|
+
|
|
803
|
+
**Q: I get "Invalid API key" error**
|
|
804
|
+
A: Make sure your API key is correct. Get it from the [OrbitalsAI Dashboard](https://dashboard.orbitalsai.com).
|
|
805
|
+
|
|
806
|
+
**Q: I get "Insufficient balance" error**
|
|
807
|
+
A: Add credits to your account through the dashboard.
|
|
808
|
+
|
|
809
|
+
**Q: I get "Unsupported file format" error**
|
|
810
|
+
A: Make sure your audio file is in a supported format (see [Supported Formats](#supported-formats)).
|
|
811
|
+
|
|
812
|
+
**Q: Transcription takes too long**
|
|
813
|
+
A: Large files take longer to process. You can increase the timeout:
|
|
814
|
+
```python
|
|
815
|
+
transcript = client.transcribe("large_file.mp3", timeout=600) # 10 minutes
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
**Q: Streaming connection keeps dropping**
|
|
819
|
+
A: The SDK auto-reconnects with exponential backoff. You can configure this:
|
|
820
|
+
```python
|
|
821
|
+
config = StreamingConfig(max_retries=10, retry_delay=2.0)
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
**Q: How do I convert audio files for streaming?**
|
|
825
|
+
A: Use the `AudioConverter` utility:
|
|
826
|
+
```python
|
|
827
|
+
from orbitalsai.streaming import AudioConverter
|
|
828
|
+
audio_bytes, sample_rate = AudioConverter.from_file("speech.mp3")
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Q: Streaming shows "Credits exhausted"**
|
|
832
|
+
A: Your account ran out of credits during streaming. The connection will close automatically. Top up your credits and reconnect.
|
|
833
|
+
|
|
834
|
+
### Getting Help
|
|
835
|
+
|
|
836
|
+
- 📧 Email: support@orbitalsai.com
|
|
837
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/orbitalsai/orbitalsai-python-sdk/issues)
|
|
838
|
+
- 📖 Docs: [Documentation](https://docs.orbitalsai.com)
|
|
839
|
+
|
|
840
|
+
## License
|
|
841
|
+
|
|
842
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
843
|
+
|
|
844
|
+
## Contributing
|
|
845
|
+
|
|
846
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
847
|
+
|
|
848
|
+
---
|
|
849
|
+
|
|
850
|
+
Made by OrbitalsAI
|