audiopod 2.1.0__py3-none-any.whl → 2.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.
@@ -0,0 +1,235 @@
1
+ """
2
+ API Wallet Service - Manage API billing and balance
3
+ """
4
+
5
+ from typing import Dict, Any, Optional, List
6
+ from .base import BaseService
7
+
8
+
9
+ class WalletService(BaseService):
10
+ """
11
+ Service for managing API wallet balance and billing.
12
+
13
+ Example:
14
+ ```python
15
+ from audiopod import Client
16
+
17
+ client = Client()
18
+
19
+ # Get balance
20
+ balance = client.wallet.get_balance()
21
+ print(f"Balance: {balance['balance_usd']}")
22
+
23
+ # Estimate cost
24
+ estimate = client.wallet.estimate_cost("stem_extraction", 300)
25
+ print(f"Cost: {estimate['cost_usd']}")
26
+
27
+ # Create top-up checkout
28
+ checkout = client.wallet.create_topup_checkout(2500) # $25.00
29
+ print(f"Pay at: {checkout['url']}")
30
+ ```
31
+ """
32
+
33
+ def get_balance(self) -> Dict[str, Any]:
34
+ """
35
+ Get current API wallet balance.
36
+
37
+ Returns:
38
+ Dict with balance_cents, balance_usd, total_topup_cents, total_spent_cents
39
+ """
40
+ if self.async_mode:
41
+ return self._async_get_balance()
42
+ return self.client.request("GET", "/api/v1/api-wallet/balance")
43
+
44
+ async def _async_get_balance(self) -> Dict[str, Any]:
45
+ return await self.client.request("GET", "/api/v1/api-wallet/balance")
46
+
47
+ def get_pricing(self) -> Dict[str, Any]:
48
+ """
49
+ Get pricing table for all services.
50
+
51
+ Returns:
52
+ Dict with services pricing and wallet configuration
53
+ """
54
+ if self.async_mode:
55
+ return self._async_get_pricing()
56
+ return self.client.request("GET", "/api/v1/api-wallet/pricing")
57
+
58
+ async def _async_get_pricing(self) -> Dict[str, Any]:
59
+ return await self.client.request("GET", "/api/v1/api-wallet/pricing")
60
+
61
+ def estimate_cost(self, service_type: str, duration_seconds: int) -> Dict[str, Any]:
62
+ """
63
+ Estimate cost for a service operation.
64
+
65
+ Args:
66
+ service_type: Type of service (e.g., "stem_extraction", "transcription")
67
+ duration_seconds: Duration of audio in seconds
68
+
69
+ Returns:
70
+ Dict with cost_cents, cost_usd, duration_minutes
71
+ """
72
+ if self.async_mode:
73
+ return self._async_estimate_cost(service_type, duration_seconds)
74
+ return self.client.request(
75
+ "POST",
76
+ "/api/v1/api-wallet/estimate",
77
+ json_data={"service_type": service_type, "duration_seconds": duration_seconds},
78
+ )
79
+
80
+ async def _async_estimate_cost(self, service_type: str, duration_seconds: int) -> Dict[str, Any]:
81
+ return await self.client.request(
82
+ "POST",
83
+ "/api/v1/api-wallet/estimate",
84
+ json_data={"service_type": service_type, "duration_seconds": duration_seconds},
85
+ )
86
+
87
+ def check_balance(self, service_type: str, duration_seconds: int) -> Dict[str, Any]:
88
+ """
89
+ Check if balance is sufficient for an operation.
90
+
91
+ Args:
92
+ service_type: Type of service
93
+ duration_seconds: Duration of audio in seconds
94
+
95
+ Returns:
96
+ Dict with can_proceed, cost_cents, current_balance_cents
97
+
98
+ Raises:
99
+ InsufficientBalanceError: If balance is insufficient (402 response)
100
+ """
101
+ if self.async_mode:
102
+ return self._async_check_balance(service_type, duration_seconds)
103
+ return self.client.request(
104
+ "POST",
105
+ "/api/v1/api-wallet/check-balance",
106
+ json_data={"service_type": service_type, "duration_seconds": duration_seconds},
107
+ )
108
+
109
+ async def _async_check_balance(self, service_type: str, duration_seconds: int) -> Dict[str, Any]:
110
+ return await self.client.request(
111
+ "POST",
112
+ "/api/v1/api-wallet/check-balance",
113
+ json_data={"service_type": service_type, "duration_seconds": duration_seconds},
114
+ )
115
+
116
+ def create_topup_checkout(self, amount_cents: int) -> Dict[str, Any]:
117
+ """
118
+ Create a Stripe checkout session to top up wallet.
119
+
120
+ Args:
121
+ amount_cents: Amount in cents (min 100 = $1.00, max 1000000 = $10,000)
122
+
123
+ Returns:
124
+ Dict with session_id, url, amount_cents, amount_usd
125
+ """
126
+ if self.async_mode:
127
+ return self._async_create_topup_checkout(amount_cents)
128
+ return self.client.request(
129
+ "POST",
130
+ "/api/v1/api-wallet/topup/checkout",
131
+ json_data={"amount_cents": amount_cents},
132
+ )
133
+
134
+ async def _async_create_topup_checkout(self, amount_cents: int) -> Dict[str, Any]:
135
+ return await self.client.request(
136
+ "POST",
137
+ "/api/v1/api-wallet/topup/checkout",
138
+ json_data={"amount_cents": amount_cents},
139
+ )
140
+
141
+ def create_topup_payment_intent(self, amount_cents: int) -> Dict[str, Any]:
142
+ """
143
+ Create a Stripe PaymentIntent for custom payment flows.
144
+
145
+ Args:
146
+ amount_cents: Amount in cents
147
+
148
+ Returns:
149
+ Dict with client_secret, payment_intent_id, amount_cents
150
+ """
151
+ if self.async_mode:
152
+ return self._async_create_topup_payment_intent(amount_cents)
153
+ return self.client.request(
154
+ "POST",
155
+ "/api/v1/api-wallet/topup/payment-intent",
156
+ json_data={"amount_cents": amount_cents},
157
+ )
158
+
159
+ async def _async_create_topup_payment_intent(self, amount_cents: int) -> Dict[str, Any]:
160
+ return await self.client.request(
161
+ "POST",
162
+ "/api/v1/api-wallet/topup/payment-intent",
163
+ json_data={"amount_cents": amount_cents},
164
+ )
165
+
166
+ def get_usage_history(
167
+ self, page: int = 1, limit: int = 50
168
+ ) -> Dict[str, Any]:
169
+ """
170
+ Get API usage history.
171
+
172
+ Args:
173
+ page: Page number (1-indexed)
174
+ limit: Results per page (max 100)
175
+
176
+ Returns:
177
+ Dict with page, limit, logs (list of usage records)
178
+ """
179
+ if self.async_mode:
180
+ return self._async_get_usage_history(page, limit)
181
+ return self.client.request(
182
+ "GET",
183
+ "/api/v1/api-wallet/usage",
184
+ params={"page": page, "limit": limit},
185
+ )
186
+
187
+ async def _async_get_usage_history(self, page: int, limit: int) -> Dict[str, Any]:
188
+ return await self.client.request(
189
+ "GET",
190
+ "/api/v1/api-wallet/usage",
191
+ params={"page": page, "limit": limit},
192
+ )
193
+
194
+ def get_topup_history(
195
+ self, page: int = 1, limit: int = 20
196
+ ) -> Dict[str, Any]:
197
+ """
198
+ Get wallet top-up history.
199
+
200
+ Args:
201
+ page: Page number (1-indexed)
202
+ limit: Results per page (max 100)
203
+
204
+ Returns:
205
+ Dict with page, limit, topups (list of top-up records)
206
+ """
207
+ if self.async_mode:
208
+ return self._async_get_topup_history(page, limit)
209
+ return self.client.request(
210
+ "GET",
211
+ "/api/v1/api-wallet/topups",
212
+ params={"page": page, "limit": limit},
213
+ )
214
+
215
+ async def _async_get_topup_history(self, page: int, limit: int) -> Dict[str, Any]:
216
+ return await self.client.request(
217
+ "GET",
218
+ "/api/v1/api-wallet/topups",
219
+ params={"page": page, "limit": limit},
220
+ )
221
+
222
+ def get_service_types(self) -> List[str]:
223
+ """
224
+ Get list of available service types.
225
+
226
+ Returns:
227
+ List of service type strings
228
+ """
229
+ if self.async_mode:
230
+ return self._async_get_service_types()
231
+ return self.client.request("GET", "/api/v1/api-wallet/service-types")
232
+
233
+ async def _async_get_service_types(self) -> List[str]:
234
+ return await self.client.request("GET", "/api/v1/api-wallet/service-types")
235
+
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: audiopod
3
+ Version: 2.2.0
4
+ Summary: AudioPod SDK for Python - Professional Audio Processing powered by AI
5
+ Author-email: AudioPod AI <support@audiopod.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://audiopod.ai
8
+ Project-URL: Documentation, https://docs.audiopod.ai
9
+ Project-URL: Repository, https://github.com/AudiopodAI/audiopod-python
10
+ Keywords: audiopod,audio,ai,voice,cloning,transcription,stem-separation,music,sdk
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Multimedia :: Sound/Audio
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: requests>=2.28.0
26
+ Requires-Dist: aiohttp>=3.8.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
29
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
30
+ Requires-Dist: black>=23.0.0; extra == "dev"
31
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ # AudioPod Python SDK
35
+
36
+ Official Python SDK for [AudioPod AI](https://audiopod.ai) - Professional Audio Processing powered by AI.
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install audiopod
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ```python
47
+ from audiopod import Client
48
+
49
+ # Initialize client
50
+ client = Client(api_key="ap_your_api_key")
51
+ # Or set AUDIOPOD_API_KEY environment variable
52
+
53
+ # Check wallet balance
54
+ balance = client.wallet.get_balance()
55
+ print(f"Balance: {balance['balance_usd']}")
56
+
57
+ # Extract stems from audio
58
+ job = client.stem_extraction.extract_stems(
59
+ audio_file="song.mp3",
60
+ stem_types=["vocals", "drums", "bass", "other"],
61
+ wait_for_completion=True
62
+ )
63
+
64
+ # Download stems
65
+ for stem, url in job["download_urls"].items():
66
+ print(f"{stem}: {url}")
67
+ ```
68
+
69
+ ## Services
70
+
71
+ ### Wallet (API Billing)
72
+
73
+ ```python
74
+ # Get balance
75
+ balance = client.wallet.get_balance()
76
+
77
+ # Get pricing
78
+ pricing = client.wallet.get_pricing()
79
+
80
+ # Estimate cost
81
+ estimate = client.wallet.estimate_cost("stem_extraction", duration_seconds=300)
82
+
83
+ # Top up wallet
84
+ checkout = client.wallet.create_topup_checkout(amount_cents=2500) # $25
85
+ print(f"Pay at: {checkout['url']}")
86
+
87
+ # Usage history
88
+ usage = client.wallet.get_usage_history(page=1, limit=50)
89
+ ```
90
+
91
+ ### Stem Extraction
92
+
93
+ ```python
94
+ # Extract all stems
95
+ job = client.stem_extraction.extract_stems(
96
+ audio_file="song.mp3",
97
+ stem_types=["vocals", "drums", "bass", "other"],
98
+ wait_for_completion=True
99
+ )
100
+
101
+ # From URL
102
+ job = client.stem_extraction.extract_stems(
103
+ url="https://example.com/song.mp3",
104
+ stem_types=["vocals", "other"]
105
+ )
106
+
107
+ # Check status
108
+ status = client.stem_extraction.get_job(job_id=123)
109
+ ```
110
+
111
+ ### Transcription
112
+
113
+ ```python
114
+ # Transcribe audio
115
+ result = client.transcription.transcribe(
116
+ audio_file="podcast.mp3",
117
+ speaker_diarization=True,
118
+ wait_for_completion=True
119
+ )
120
+ print(result["transcript"])
121
+ ```
122
+
123
+ ### Voice Cloning & TTS
124
+
125
+ ```python
126
+ # List voices
127
+ voices = client.voice.list_voices()
128
+
129
+ # Generate speech
130
+ audio = client.voice.generate_speech(
131
+ text="Hello, world!",
132
+ voice_id=123,
133
+ wait_for_completion=True
134
+ )
135
+ ```
136
+
137
+ ### Music Generation
138
+
139
+ ```python
140
+ # Generate music
141
+ result = client.music.generate(
142
+ prompt="upbeat electronic dance music",
143
+ duration=30,
144
+ wait_for_completion=True
145
+ )
146
+ ```
147
+
148
+ ### Noise Reduction
149
+
150
+ ```python
151
+ # Denoise audio
152
+ result = client.denoiser.denoise(
153
+ audio_file="noisy.mp3",
154
+ mode="studio",
155
+ wait_for_completion=True
156
+ )
157
+ ```
158
+
159
+ ## Async Support
160
+
161
+ ```python
162
+ import asyncio
163
+ from audiopod import AsyncClient
164
+
165
+ async def main():
166
+ async with AsyncClient() as client:
167
+ balance = await client.wallet.get_balance()
168
+ print(f"Balance: {balance['balance_usd']}")
169
+
170
+ asyncio.run(main())
171
+ ```
172
+
173
+ ## Error Handling
174
+
175
+ ```python
176
+ from audiopod import Client
177
+ from audiopod.exceptions import (
178
+ AuthenticationError,
179
+ InsufficientBalanceError,
180
+ RateLimitError,
181
+ APIError
182
+ )
183
+
184
+ try:
185
+ client = Client()
186
+ job = client.stem_extraction.extract_stems(audio_file="song.mp3")
187
+ except AuthenticationError:
188
+ print("Invalid API key")
189
+ except InsufficientBalanceError as e:
190
+ print(f"Need to top up: required {e.required_cents} cents")
191
+ except RateLimitError:
192
+ print("Rate limit exceeded, try again later")
193
+ except APIError as e:
194
+ print(f"API error ({e.status_code}): {e}")
195
+ ```
196
+
197
+ ## Documentation
198
+
199
+ - [API Reference](https://docs.audiopod.ai)
200
+ - [API Wallet](https://docs.audiopod.ai/account/api-wallet)
201
+ - [Stem Separation](https://docs.audiopod.ai/api-reference/stem-splitter)
202
+
203
+ ## License
204
+
205
+ MIT
206
+
@@ -0,0 +1,21 @@
1
+ audiopod/__init__.py,sha256=1L2mJzzdEVx9vKmhMV1RDHZ_v3DqJAxMvDNd1mp7eDk,621
2
+ audiopod/client.py,sha256=UyUqCHh2l770Tr5cgThWbxf5na5T551ZOvfXp2vepE8,10482
3
+ audiopod/config.py,sha256=pbmISyy8K9QpR4aYON7xHG5kpimac2lbqgi9wXF7q-Q,316
4
+ audiopod/exceptions.py,sha256=djjLqVHGhUIe2SXFMWkVOw3TdHOZLQzFpQ5EWPjlGFM,946
5
+ audiopod/services/__init__.py,sha256=F7JgtEzVcUqDLjgavUNes6SozoqD74ebwUqPwBWRWY4,708
6
+ audiopod/services/base.py,sha256=-g3PQnXnrJyszj7wdV5Jb1SkUNSvm65TMpWqyIsh8Yo,2256
7
+ audiopod/services/credits.py,sha256=l8zk1XR77nsvMVwjSDOqN_8hUPbwWVCqSXo4JmocXrI,1450
8
+ audiopod/services/denoiser.py,sha256=LeV2zw-BVXkz-wWdXAQPx2mbtJeWBRPCvV0Q_avAAKA,4984
9
+ audiopod/services/music.py,sha256=iihNVLaGCDp5A0jDbziLNLDASdsY1XJbStWkpH6lfuQ,7676
10
+ audiopod/services/speaker.py,sha256=wrQcoKUS9VHjfYwDPYCncXJmeBSJm0bUH8fwlis-NMo,4692
11
+ audiopod/services/stem_extraction.py,sha256=JJwDT63bn7Y7UrRYNd0qXcl6lFkrV1o4yZXkmMzXdYg,10311
12
+ audiopod/services/transcription.py,sha256=OdIaqoYtVLg3O8zTZ1p3LZKH1arFprJuDJc2II9IgnU,7920
13
+ audiopod/services/translation.py,sha256=lpkXKpSGz_ounvDRMCa4vbvv9jHQtQ-Gk3BDR_9fWJo,5222
14
+ audiopod/services/video.py,sha256=y-gSpo8yu6U5bQrpOmT9wqgc4n9tuEag7PcPWyDOQRM,11711
15
+ audiopod/services/voice.py,sha256=JtlH9DCHi-D9eVSo3g95VeB99aBjdcOxTOm6RN8Re1E,7234
16
+ audiopod/services/wallet.py,sha256=Dg32Ak51w7BcbLVRl4TrI7yipA4QE5_RUZPHp2JS8T8,7735
17
+ audiopod-2.2.0.dist-info/licenses/LICENSE,sha256=hqEjnOaGNbnLSBxbtbC7WQVREU2vQI8FmwecCiZlMfA,1068
18
+ audiopod-2.2.0.dist-info/METADATA,sha256=Z1BSKVVEmm6Ez-lerTHrHqnoorAuCH9rU_bEhHaNKuQ,4819
19
+ audiopod-2.2.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
20
+ audiopod-2.2.0.dist-info/top_level.txt,sha256=M6yyOFFNpLdH4i1AMRqJZLRIgfpg1NvrQVmnPd8A6N8,9
21
+ audiopod-2.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,23 +0,0 @@
1
- """AudioPod SDK Resources"""
2
-
3
- from .transcription import Transcription
4
- from .voice import Voice
5
- from .music import Music
6
- from .stems import StemExtraction
7
- from .denoiser import Denoiser
8
- from .speaker import Speaker
9
- from .wallet import Wallet
10
-
11
- __all__ = [
12
- "Transcription",
13
- "Voice",
14
- "Music",
15
- "StemExtraction",
16
- "Denoiser",
17
- "Speaker",
18
- "Wallet",
19
- ]
20
-
21
-
22
-
23
-
@@ -1,116 +0,0 @@
1
- """
2
- Denoiser Service - Audio Noise Reduction
3
- """
4
-
5
- import time
6
- from typing import Optional, List, Dict, Any, TYPE_CHECKING
7
-
8
- if TYPE_CHECKING:
9
- from ..client import AudioPod
10
-
11
- POLL_INTERVAL = 3 # seconds
12
- DEFAULT_TIMEOUT = 600 # 10 minutes
13
-
14
-
15
- class Denoiser:
16
- """Audio noise reduction service."""
17
-
18
- def __init__(self, client: "AudioPod"):
19
- self._client = client
20
-
21
- def create(
22
- self,
23
- *,
24
- file: Optional[str] = None,
25
- url: Optional[str] = None,
26
- ) -> Dict[str, Any]:
27
- """
28
- Create a denoise job.
29
-
30
- Args:
31
- file: Path to audio file
32
- url: URL of audio/video
33
-
34
- Returns:
35
- Denoise job object
36
-
37
- Example:
38
- >>> job = client.denoiser.create(file="./noisy-audio.mp3")
39
- """
40
- if file:
41
- return self._client.upload(
42
- "/api/v1/denoiser/denoise",
43
- file,
44
- field_name="file",
45
- )
46
-
47
- if url:
48
- return self._client.post(
49
- "/api/v1/denoiser/denoise",
50
- json_data={"url": url},
51
- )
52
-
53
- raise ValueError("Either file or url must be provided")
54
-
55
- def get(self, job_id: int) -> Dict[str, Any]:
56
- """Get a denoise job by ID."""
57
- return self._client.get(f"/api/v1/denoiser/jobs/{job_id}")
58
-
59
- def list(
60
- self,
61
- *,
62
- skip: int = 0,
63
- limit: int = 50,
64
- status: Optional[str] = None,
65
- ) -> List[Dict[str, Any]]:
66
- """List denoise jobs."""
67
- return self._client.get(
68
- "/api/v1/denoiser/jobs",
69
- params={"skip": skip, "limit": limit, "status": status},
70
- )
71
-
72
- def delete(self, job_id: int) -> None:
73
- """Delete a denoise job."""
74
- self._client.delete(f"/api/v1/denoiser/jobs/{job_id}")
75
-
76
- def wait_for_completion(
77
- self, job_id: int, timeout: int = DEFAULT_TIMEOUT
78
- ) -> Dict[str, Any]:
79
- """Wait for denoising to complete."""
80
- start_time = time.time()
81
-
82
- while time.time() - start_time < timeout:
83
- job = self.get(job_id)
84
- status = job.get("status", "")
85
-
86
- if status == "COMPLETED":
87
- return job
88
- if status == "FAILED":
89
- raise RuntimeError(
90
- f"Denoising failed: {job.get('error_message', 'Unknown error')}"
91
- )
92
-
93
- time.sleep(POLL_INTERVAL)
94
-
95
- raise TimeoutError(f"Denoising timed out after {timeout}s")
96
-
97
- def denoise(
98
- self,
99
- *,
100
- file: Optional[str] = None,
101
- url: Optional[str] = None,
102
- timeout: int = DEFAULT_TIMEOUT,
103
- ) -> Dict[str, Any]:
104
- """
105
- Denoise audio and wait for completion.
106
-
107
- Example:
108
- >>> result = client.denoiser.denoise(file="./noisy-audio.mp3")
109
- >>> print(result["output_url"])
110
- """
111
- job = self.create(file=file, url=url)
112
- return self.wait_for_completion(job["id"], timeout=timeout)
113
-
114
-
115
-
116
-