orbitalsai 1.0.0__py3-none-any.whl → 1.2.0__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.
- orbitalsai/__init__.py +26 -3
- orbitalsai/async_client.py +25 -1
- orbitalsai/client.py +26 -50
- orbitalsai/models.py +10 -0
- orbitalsai/streaming/__init__.py +117 -0
- orbitalsai/streaming/async_client.py +507 -0
- orbitalsai/streaming/audio/__init__.py +33 -0
- orbitalsai/streaming/audio/buffer.py +171 -0
- orbitalsai/streaming/audio/converter.py +327 -0
- orbitalsai/streaming/audio/formats.py +112 -0
- orbitalsai/streaming/audio/source.py +317 -0
- orbitalsai/streaming/client.py +384 -0
- orbitalsai/streaming/config.py +207 -0
- orbitalsai/streaming/connection.py +298 -0
- orbitalsai/streaming/events.py +360 -0
- orbitalsai/streaming/exceptions.py +179 -0
- orbitalsai/streaming/protocol.py +245 -0
- orbitalsai-1.2.0.dist-info/METADATA +850 -0
- orbitalsai-1.2.0.dist-info/RECORD +24 -0
- {orbitalsai-1.0.0.dist-info → orbitalsai-1.2.0.dist-info}/WHEEL +1 -1
- orbitalsai-1.0.0.dist-info/METADATA +0 -439
- orbitalsai-1.0.0.dist-info/RECORD +0 -11
- {orbitalsai-1.0.0.dist-info → orbitalsai-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {orbitalsai-1.0.0.dist-info → orbitalsai-1.2.0.dist-info}/top_level.txt +0 -0
orbitalsai/__init__.py
CHANGED
|
@@ -3,7 +3,7 @@ OrbitalsAI Python SDK
|
|
|
3
3
|
|
|
4
4
|
A simple and powerful Python SDK for the OrbitalsAI API.
|
|
5
5
|
|
|
6
|
-
Example:
|
|
6
|
+
Example (Batch Transcription):
|
|
7
7
|
import orbitalsai
|
|
8
8
|
|
|
9
9
|
# Synchronous usage
|
|
@@ -15,12 +15,28 @@ Example:
|
|
|
15
15
|
async with orbitalsai.AsyncClient(api_key="your_api_key_here") as client:
|
|
16
16
|
transcript = await client.transcribe("audio.mp3")
|
|
17
17
|
print(transcript.text)
|
|
18
|
+
|
|
19
|
+
Example (Real-time Streaming):
|
|
20
|
+
from orbitalsai.streaming import AsyncStreamingClient, PrintingEventHandlers
|
|
21
|
+
import asyncio
|
|
22
|
+
|
|
23
|
+
async def main():
|
|
24
|
+
async with AsyncStreamingClient(api_key="your_key") as client:
|
|
25
|
+
await client.connect(PrintingEventHandlers())
|
|
26
|
+
|
|
27
|
+
with open("audio.pcm", "rb") as f:
|
|
28
|
+
while chunk := f.read(16000):
|
|
29
|
+
await client.send_audio(chunk)
|
|
30
|
+
|
|
31
|
+
await client.flush()
|
|
32
|
+
|
|
33
|
+
asyncio.run(main())
|
|
18
34
|
"""
|
|
19
35
|
|
|
20
36
|
from .client import Client
|
|
21
37
|
from .async_client import AsyncClient
|
|
22
38
|
from .models import (
|
|
23
|
-
TranscriptTask, Transcript, Balance, UsageHistory, DailyUsage, User,
|
|
39
|
+
TranscriptTask, Transcript, Balance, UsageHistory, DailyUsage, User, Model,
|
|
24
40
|
SUPPORTED_LANGUAGES, SUPPORTED_AUDIO_FORMATS, SUPPORTED_AUDIO_MIMETYPES
|
|
25
41
|
)
|
|
26
42
|
from .exceptions import (
|
|
@@ -29,7 +45,10 @@ from .exceptions import (
|
|
|
29
45
|
TaskNotFoundError, TranscriptionError, TimeoutError, APIError
|
|
30
46
|
)
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
# Streaming module (imported as submodule)
|
|
49
|
+
from . import streaming
|
|
50
|
+
|
|
51
|
+
__version__ = "2.0.0"
|
|
33
52
|
__author__ = "OrbitalsAI"
|
|
34
53
|
__email__ = "support@orbitalsai.com"
|
|
35
54
|
|
|
@@ -38,6 +57,9 @@ __all__ = [
|
|
|
38
57
|
"Client",
|
|
39
58
|
"AsyncClient",
|
|
40
59
|
|
|
60
|
+
# Streaming Module
|
|
61
|
+
"streaming",
|
|
62
|
+
|
|
41
63
|
# Models
|
|
42
64
|
"TranscriptTask",
|
|
43
65
|
"Transcript",
|
|
@@ -45,6 +67,7 @@ __all__ = [
|
|
|
45
67
|
"UsageHistory",
|
|
46
68
|
"DailyUsage",
|
|
47
69
|
"User",
|
|
70
|
+
"Model",
|
|
48
71
|
|
|
49
72
|
# Constants
|
|
50
73
|
"SUPPORTED_LANGUAGES",
|
orbitalsai/async_client.py
CHANGED
|
@@ -11,7 +11,7 @@ from datetime import datetime, date
|
|
|
11
11
|
|
|
12
12
|
from .models import (
|
|
13
13
|
TranscriptTask, Transcript, Balance, UsageHistory, DailyUsage,
|
|
14
|
-
User, APIKey, UsageRecord, DailyUsageRecord
|
|
14
|
+
User, APIKey, UsageRecord, DailyUsageRecord, Model
|
|
15
15
|
)
|
|
16
16
|
from .exceptions import (
|
|
17
17
|
OrbitalsAIError, AuthenticationError, InsufficientBalanceError,
|
|
@@ -101,11 +101,33 @@ class AsyncClient:
|
|
|
101
101
|
except aiohttp.ClientError as e:
|
|
102
102
|
raise OrbitalsAIError(f"Request failed: {str(e)}")
|
|
103
103
|
|
|
104
|
+
async def get_models(self) -> List[Model]:
|
|
105
|
+
"""
|
|
106
|
+
Get all available AI models with their pricing information.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
List of Model objects with pricing details
|
|
110
|
+
"""
|
|
111
|
+
response = await self._make_request("GET", "/models")
|
|
112
|
+
|
|
113
|
+
models = []
|
|
114
|
+
for model_data in response:
|
|
115
|
+
models.append(Model(
|
|
116
|
+
id=model_data["id"],
|
|
117
|
+
model_name=model_data["model_name"],
|
|
118
|
+
transcription_rate_per_second=model_data["transcription_rate_per_second"],
|
|
119
|
+
transcription_rate_per_hour=model_data["transcription_rate_per_hour"],
|
|
120
|
+
is_active=model_data["is_active"]
|
|
121
|
+
))
|
|
122
|
+
|
|
123
|
+
return models
|
|
124
|
+
|
|
104
125
|
async def transcribe(
|
|
105
126
|
self,
|
|
106
127
|
file_path: str,
|
|
107
128
|
language: str = "english",
|
|
108
129
|
generate_srt: bool = False,
|
|
130
|
+
model_name: str = "Perigee-1",
|
|
109
131
|
wait: bool = True,
|
|
110
132
|
timeout: int = 300,
|
|
111
133
|
poll_interval: int = 5
|
|
@@ -117,6 +139,7 @@ class AsyncClient:
|
|
|
117
139
|
file_path: Path to the audio file
|
|
118
140
|
language: Language of the audio (default: "english")
|
|
119
141
|
generate_srt: Whether to generate SRT subtitles (default: False)
|
|
142
|
+
model_name: AI model to use for transcription (default: "Perigee-1")
|
|
120
143
|
wait: Whether to wait for completion (default: True)
|
|
121
144
|
timeout: Maximum time to wait in seconds (default: 300)
|
|
122
145
|
poll_interval: Seconds to wait between status checks (default: 5)
|
|
@@ -141,6 +164,7 @@ class AsyncClient:
|
|
|
141
164
|
data.add_field('file', f, filename=file_path.split('/')[-1], content_type='audio/mpeg')
|
|
142
165
|
data.add_field('language', language)
|
|
143
166
|
data.add_field('generate_srt', str(generate_srt).lower())
|
|
167
|
+
data.add_field('model_name', model_name)
|
|
144
168
|
|
|
145
169
|
# Upload file
|
|
146
170
|
response = await self._make_request("POST", "/audio/upload", data=data)
|
orbitalsai/client.py
CHANGED
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
|
12
12
|
|
|
13
13
|
from .models import (
|
|
14
14
|
TranscriptTask, Transcript, Balance, UsageHistory, DailyUsage,
|
|
15
|
-
User, APIKey, UsageRecord, DailyUsageRecord
|
|
15
|
+
User, APIKey, UsageRecord, DailyUsageRecord, Model
|
|
16
16
|
)
|
|
17
17
|
from .exceptions import (
|
|
18
18
|
OrbitalsAIError, AuthenticationError, InsufficientBalanceError,
|
|
@@ -89,11 +89,33 @@ class Client:
|
|
|
89
89
|
except requests.exceptions.RequestException as e:
|
|
90
90
|
raise OrbitalsAIError(f"Request failed: {str(e)}")
|
|
91
91
|
|
|
92
|
+
def get_models(self) -> List[Model]:
|
|
93
|
+
"""
|
|
94
|
+
Get all available AI models with their pricing information.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
List of Model objects with pricing details
|
|
98
|
+
"""
|
|
99
|
+
response = self._make_request("GET", "/models")
|
|
100
|
+
|
|
101
|
+
models = []
|
|
102
|
+
for model_data in response:
|
|
103
|
+
models.append(Model(
|
|
104
|
+
id=model_data["id"],
|
|
105
|
+
model_name=model_data["model_name"],
|
|
106
|
+
transcription_rate_per_second=model_data["transcription_rate_per_second"],
|
|
107
|
+
transcription_rate_per_hour=model_data["transcription_rate_per_hour"],
|
|
108
|
+
is_active=model_data["is_active"]
|
|
109
|
+
))
|
|
110
|
+
|
|
111
|
+
return models
|
|
112
|
+
|
|
92
113
|
def transcribe(
|
|
93
114
|
self,
|
|
94
115
|
file_path: str,
|
|
95
116
|
language: str = "english",
|
|
96
117
|
generate_srt: bool = False,
|
|
118
|
+
model_name: str = "Perigee-1",
|
|
97
119
|
wait: bool = True,
|
|
98
120
|
timeout: int = 300,
|
|
99
121
|
poll_interval: int = 5
|
|
@@ -105,6 +127,7 @@ class Client:
|
|
|
105
127
|
file_path: Path to the audio file
|
|
106
128
|
language: Language of the audio (default: "english")
|
|
107
129
|
generate_srt: Whether to generate SRT subtitles (default: False)
|
|
130
|
+
model_name: AI model to use for transcription (default: "Perigee-1")
|
|
108
131
|
wait: Whether to wait for completion (default: True)
|
|
109
132
|
timeout: Maximum time to wait in seconds (default: 300)
|
|
110
133
|
poll_interval: Seconds to wait between status checks (default: 5)
|
|
@@ -128,7 +151,8 @@ class Client:
|
|
|
128
151
|
files = {"file": (Path(file_path).name, f, "audio/mpeg")}
|
|
129
152
|
data = {
|
|
130
153
|
"language": language,
|
|
131
|
-
"generate_srt": str(generate_srt).lower()
|
|
154
|
+
"generate_srt": str(generate_srt).lower(),
|
|
155
|
+
"model_name": model_name
|
|
132
156
|
}
|
|
133
157
|
|
|
134
158
|
# Upload file
|
|
@@ -249,54 +273,6 @@ class Client:
|
|
|
249
273
|
last_updated=datetime.fromisoformat(response["last_updated"].replace('Z', '+00:00'))
|
|
250
274
|
)
|
|
251
275
|
|
|
252
|
-
def get_usage_history(
|
|
253
|
-
self,
|
|
254
|
-
start_date: Optional[datetime] = None,
|
|
255
|
-
end_date: Optional[datetime] = None,
|
|
256
|
-
page: int = 1,
|
|
257
|
-
page_size: int = 50
|
|
258
|
-
) -> UsageHistory:
|
|
259
|
-
"""
|
|
260
|
-
Get usage history for the current user.
|
|
261
|
-
|
|
262
|
-
Args:
|
|
263
|
-
start_date: Start date for the history (default: 30 days ago)
|
|
264
|
-
end_date: End date for the history (default: now)
|
|
265
|
-
page: Page number (default: 1)
|
|
266
|
-
page_size: Number of records per page (default: 50)
|
|
267
|
-
|
|
268
|
-
Returns:
|
|
269
|
-
UsageHistory object with usage records
|
|
270
|
-
"""
|
|
271
|
-
params = {"page": page, "page_size": page_size}
|
|
272
|
-
if start_date:
|
|
273
|
-
params["start_date"] = start_date.isoformat()
|
|
274
|
-
if end_date:
|
|
275
|
-
params["end_date"] = end_date.isoformat()
|
|
276
|
-
|
|
277
|
-
response = self._make_request("GET", "/billing/usage-history", params=params)
|
|
278
|
-
|
|
279
|
-
records = []
|
|
280
|
-
for record_data in response["records"]:
|
|
281
|
-
records.append(UsageRecord(
|
|
282
|
-
id=record_data["id"],
|
|
283
|
-
service_type=record_data["service_type"],
|
|
284
|
-
usage_amount=record_data["total_audio_usage"],
|
|
285
|
-
cost=record_data["cost"],
|
|
286
|
-
timestamp=datetime.fromisoformat(record_data["timestamp"].replace('Z', '+00:00')),
|
|
287
|
-
api_key_id=record_data.get("api_key_id")
|
|
288
|
-
))
|
|
289
|
-
|
|
290
|
-
return UsageHistory(
|
|
291
|
-
records=records,
|
|
292
|
-
total_records=response["total_records"],
|
|
293
|
-
total_pages=response["total_pages"],
|
|
294
|
-
current_page=response["current_page"],
|
|
295
|
-
start_date=datetime.fromisoformat(response["start_date"].replace('Z', '+00:00')),
|
|
296
|
-
end_date=datetime.fromisoformat(response["end_date"].replace('Z', '+00:00')),
|
|
297
|
-
period_summary=response["period_summary"]
|
|
298
|
-
)
|
|
299
|
-
|
|
300
276
|
def get_daily_usage(
|
|
301
277
|
self,
|
|
302
278
|
start_date: Optional[date] = None,
|
orbitalsai/models.py
CHANGED
|
@@ -114,6 +114,16 @@ class APIKey:
|
|
|
114
114
|
last_used: Optional[datetime] = None
|
|
115
115
|
|
|
116
116
|
|
|
117
|
+
@dataclass
|
|
118
|
+
class Model:
|
|
119
|
+
"""Represents an AI model with pricing information."""
|
|
120
|
+
id: int
|
|
121
|
+
model_name: str
|
|
122
|
+
transcription_rate_per_second: float
|
|
123
|
+
transcription_rate_per_hour: float
|
|
124
|
+
is_active: bool
|
|
125
|
+
|
|
126
|
+
|
|
117
127
|
# Supported languages and file formats
|
|
118
128
|
SUPPORTED_LANGUAGES = [
|
|
119
129
|
"english", "hausa", "igbo", "yoruba", "swahili", "pidgin", "kinyarwanda"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OrbitalsAI Streaming Module
|
|
3
|
+
|
|
4
|
+
Real-time streaming transcription via WebSocket.
|
|
5
|
+
|
|
6
|
+
Example (Async - Recommended):
|
|
7
|
+
import asyncio
|
|
8
|
+
from orbitalsai.streaming import AsyncStreamingClient, PrintingEventHandlers
|
|
9
|
+
|
|
10
|
+
async def main():
|
|
11
|
+
async with AsyncStreamingClient(api_key="your_key") as client:
|
|
12
|
+
await client.connect(PrintingEventHandlers())
|
|
13
|
+
|
|
14
|
+
# Stream audio file
|
|
15
|
+
with open("audio.pcm", "rb") as f:
|
|
16
|
+
while chunk := f.read(16000):
|
|
17
|
+
await client.send_audio(chunk)
|
|
18
|
+
|
|
19
|
+
await client.flush()
|
|
20
|
+
|
|
21
|
+
asyncio.run(main())
|
|
22
|
+
|
|
23
|
+
Example (Sync):
|
|
24
|
+
import time
|
|
25
|
+
from orbitalsai.streaming import StreamingClient, StreamingEventHandlers
|
|
26
|
+
|
|
27
|
+
class MyHandlers(StreamingEventHandlers):
|
|
28
|
+
def on_transcript_final(self, transcript, metadata):
|
|
29
|
+
print(f"Final: {transcript}")
|
|
30
|
+
print(f"Cost: ${metadata['cost']:.4f}")
|
|
31
|
+
|
|
32
|
+
with StreamingClient(api_key="your_key") as client:
|
|
33
|
+
client.connect(MyHandlers())
|
|
34
|
+
|
|
35
|
+
with open("audio.pcm", "rb") as f:
|
|
36
|
+
while chunk := f.read(16000):
|
|
37
|
+
client.send_audio(chunk)
|
|
38
|
+
time.sleep(0.5) # Real-time pacing
|
|
39
|
+
|
|
40
|
+
client.flush()
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from .config import (
|
|
44
|
+
StreamingConfig,
|
|
45
|
+
STREAMING_SUPPORTED_LANGUAGES,
|
|
46
|
+
DEFAULT_SAMPLE_RATE,
|
|
47
|
+
DEFAULT_CHUNK_SIZE,
|
|
48
|
+
)
|
|
49
|
+
from .events import (
|
|
50
|
+
StreamingEventHandlers,
|
|
51
|
+
PrintingEventHandlers,
|
|
52
|
+
CallbackEventHandlers,
|
|
53
|
+
)
|
|
54
|
+
from .exceptions import (
|
|
55
|
+
StreamingError,
|
|
56
|
+
ConnectionError,
|
|
57
|
+
AuthenticationError,
|
|
58
|
+
AudioFormatError,
|
|
59
|
+
InsufficientCreditsError,
|
|
60
|
+
ReconnectionFailedError,
|
|
61
|
+
ServiceUnavailableError,
|
|
62
|
+
ServerBusyError,
|
|
63
|
+
SessionClosedError,
|
|
64
|
+
ProtocolError,
|
|
65
|
+
)
|
|
66
|
+
from .async_client import AsyncStreamingClient
|
|
67
|
+
from .client import StreamingClient, StreamingTranscriptAccumulator
|
|
68
|
+
from .audio import (
|
|
69
|
+
AudioBuffer,
|
|
70
|
+
AudioConverter,
|
|
71
|
+
AudioFormat,
|
|
72
|
+
PCM16_MONO,
|
|
73
|
+
AudioSource,
|
|
74
|
+
FileAudioSource,
|
|
75
|
+
RawPCMFileSource,
|
|
76
|
+
MicrophoneSource,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
__all__ = [
|
|
80
|
+
# Clients
|
|
81
|
+
"AsyncStreamingClient",
|
|
82
|
+
"StreamingClient",
|
|
83
|
+
|
|
84
|
+
# Configuration
|
|
85
|
+
"StreamingConfig",
|
|
86
|
+
"STREAMING_SUPPORTED_LANGUAGES",
|
|
87
|
+
"DEFAULT_SAMPLE_RATE",
|
|
88
|
+
"DEFAULT_CHUNK_SIZE",
|
|
89
|
+
|
|
90
|
+
# Event Handlers
|
|
91
|
+
"StreamingEventHandlers",
|
|
92
|
+
"PrintingEventHandlers",
|
|
93
|
+
"CallbackEventHandlers",
|
|
94
|
+
"StreamingTranscriptAccumulator",
|
|
95
|
+
|
|
96
|
+
# Exceptions
|
|
97
|
+
"StreamingError",
|
|
98
|
+
"ConnectionError",
|
|
99
|
+
"AuthenticationError",
|
|
100
|
+
"AudioFormatError",
|
|
101
|
+
"InsufficientCreditsError",
|
|
102
|
+
"ReconnectionFailedError",
|
|
103
|
+
"ServiceUnavailableError",
|
|
104
|
+
"ServerBusyError",
|
|
105
|
+
"SessionClosedError",
|
|
106
|
+
"ProtocolError",
|
|
107
|
+
|
|
108
|
+
# Audio Utilities
|
|
109
|
+
"AudioBuffer",
|
|
110
|
+
"AudioConverter",
|
|
111
|
+
"AudioFormat",
|
|
112
|
+
"PCM16_MONO",
|
|
113
|
+
"AudioSource",
|
|
114
|
+
"FileAudioSource",
|
|
115
|
+
"RawPCMFileSource",
|
|
116
|
+
"MicrophoneSource",
|
|
117
|
+
]
|