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.
@@ -1,205 +0,0 @@
1
- """
2
- Transcription Service - Speech-to-Text
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 Transcription:
16
- """Speech-to-text transcription service."""
17
-
18
- def __init__(self, client: "AudioPod"):
19
- self._client = client
20
-
21
- def create(
22
- self,
23
- *,
24
- url: Optional[str] = None,
25
- urls: Optional[List[str]] = None,
26
- language: Optional[str] = None,
27
- speaker_diarization: bool = False,
28
- min_speakers: Optional[int] = None,
29
- max_speakers: Optional[int] = None,
30
- word_timestamps: bool = True,
31
- ) -> Dict[str, Any]:
32
- """
33
- Create a transcription job from URL(s).
34
-
35
- Args:
36
- url: Single URL to transcribe
37
- urls: List of URLs to transcribe
38
- language: Language code (ISO 639-1). Auto-detected if not specified
39
- speaker_diarization: Enable speaker diarization
40
- min_speakers: Minimum number of speakers (hint for diarization)
41
- max_speakers: Maximum number of speakers (hint for diarization)
42
- word_timestamps: Enable word-level timestamps
43
-
44
- Returns:
45
- Job object with id and status
46
-
47
- Example:
48
- >>> job = client.transcription.create(
49
- ... url="https://youtube.com/watch?v=...",
50
- ... speaker_diarization=True,
51
- ... )
52
- """
53
- source_urls = urls or ([url] if url else [])
54
- if not source_urls:
55
- raise ValueError("At least one URL is required")
56
-
57
- return self._client.post(
58
- "/api/v1/transcribe/transcribe",
59
- json_data={
60
- "source_urls": source_urls,
61
- "language": language,
62
- "enable_speaker_diarization": speaker_diarization,
63
- "min_speakers": min_speakers,
64
- "max_speakers": max_speakers,
65
- "enable_word_timestamps": word_timestamps,
66
- },
67
- )
68
-
69
- def upload(
70
- self,
71
- file_path: str,
72
- *,
73
- language: Optional[str] = None,
74
- speaker_diarization: bool = False,
75
- ) -> Dict[str, Any]:
76
- """
77
- Upload a file for transcription.
78
-
79
- Args:
80
- file_path: Path to the audio file
81
- language: Language code (ISO 639-1)
82
- speaker_diarization: Enable speaker diarization
83
-
84
- Returns:
85
- Job object with id and status
86
- """
87
- return self._client.upload(
88
- "/api/v1/transcribe/transcribe-upload",
89
- file_path,
90
- field_name="files",
91
- additional_fields={
92
- "language": language,
93
- "enable_speaker_diarization": speaker_diarization,
94
- },
95
- )
96
-
97
- def get(self, job_id: int) -> Dict[str, Any]:
98
- """Get a transcription job by ID."""
99
- return self._client.get(f"/api/v1/transcribe/jobs/{job_id}")
100
-
101
- def list(
102
- self,
103
- *,
104
- skip: int = 0,
105
- limit: int = 50,
106
- status: Optional[str] = None,
107
- ) -> List[Dict[str, Any]]:
108
- """List transcription jobs."""
109
- return self._client.get(
110
- "/api/v1/transcribe/jobs",
111
- params={"offset": skip, "limit": limit, "status": status},
112
- )
113
-
114
- def delete(self, job_id: int) -> None:
115
- """Delete a transcription job."""
116
- self._client.delete(f"/api/v1/transcribe/jobs/{job_id}")
117
-
118
- def get_transcript(
119
- self, job_id: int, format: str = "json"
120
- ) -> Any:
121
- """
122
- Get transcript content.
123
-
124
- Args:
125
- job_id: Job ID
126
- format: Output format ('json', 'txt', 'srt', 'vtt')
127
- """
128
- return self._client.get(
129
- f"/api/v1/transcribe/jobs/{job_id}/transcript",
130
- params={"format": format},
131
- )
132
-
133
- def wait_for_completion(
134
- self, job_id: int, timeout: int = DEFAULT_TIMEOUT
135
- ) -> Dict[str, Any]:
136
- """
137
- Wait for a transcription job to complete.
138
-
139
- Args:
140
- job_id: Job ID to wait for
141
- timeout: Maximum time to wait in seconds
142
-
143
- Returns:
144
- Completed job object
145
-
146
- Raises:
147
- TimeoutError: If job doesn't complete within timeout
148
- RuntimeError: If job fails
149
- """
150
- start_time = time.time()
151
-
152
- while time.time() - start_time < timeout:
153
- job = self.get(job_id)
154
- status = job.get("status", "")
155
-
156
- if status == "COMPLETED":
157
- return job
158
- if status == "FAILED":
159
- raise RuntimeError(
160
- f"Transcription failed: {job.get('error_message', 'Unknown error')}"
161
- )
162
- if status == "CANCELLED":
163
- raise RuntimeError("Transcription was cancelled")
164
-
165
- time.sleep(POLL_INTERVAL)
166
-
167
- raise TimeoutError(f"Transcription timed out after {timeout}s")
168
-
169
- def transcribe(
170
- self,
171
- *,
172
- url: Optional[str] = None,
173
- urls: Optional[List[str]] = None,
174
- language: Optional[str] = None,
175
- speaker_diarization: bool = False,
176
- min_speakers: Optional[int] = None,
177
- max_speakers: Optional[int] = None,
178
- timeout: int = DEFAULT_TIMEOUT,
179
- ) -> Dict[str, Any]:
180
- """
181
- Create and wait for transcription to complete.
182
-
183
- This is a convenience method that combines create() and wait_for_completion().
184
-
185
- Example:
186
- >>> result = client.transcription.transcribe(
187
- ... url="https://youtube.com/watch?v=...",
188
- ... speaker_diarization=True,
189
- ... )
190
- >>> print(result["detected_language"])
191
- """
192
- job = self.create(
193
- url=url,
194
- urls=urls,
195
- language=language,
196
- speaker_diarization=speaker_diarization,
197
- min_speakers=min_speakers,
198
- max_speakers=max_speakers,
199
- )
200
- job_id = job.get("id") or job.get("job_id")
201
- return self.wait_for_completion(job_id, timeout=timeout)
202
-
203
-
204
-
205
-
@@ -1,139 +0,0 @@
1
- """
2
- Voice Service - Voice Cloning & Text-to-Speech
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 = 2 # seconds
12
- DEFAULT_TIMEOUT = 300 # 5 minutes
13
-
14
-
15
- class Voice:
16
- """Voice cloning and text-to-speech service."""
17
-
18
- def __init__(self, client: "AudioPod"):
19
- self._client = client
20
-
21
- def list(self) -> List[Dict[str, Any]]:
22
- """List all available voices."""
23
- return self._client.get("/api/v1/voice/voices")
24
-
25
- def get(self, voice_id: int) -> Dict[str, Any]:
26
- """Get a voice by ID."""
27
- return self._client.get(f"/api/v1/voice/voices/{voice_id}")
28
-
29
- def create(
30
- self,
31
- name: str,
32
- audio_file: str,
33
- *,
34
- description: Optional[str] = None,
35
- ) -> Dict[str, Any]:
36
- """
37
- Create a new voice clone.
38
-
39
- Args:
40
- name: Name for the voice
41
- audio_file: Path to audio sample file
42
- description: Optional description
43
-
44
- Returns:
45
- Created voice object
46
-
47
- Example:
48
- >>> voice = client.voice.create(
49
- ... name="My Voice",
50
- ... audio_file="./sample.mp3",
51
- ... )
52
- """
53
- return self._client.upload(
54
- "/api/v1/voice/voices",
55
- audio_file,
56
- field_name="audio_file",
57
- additional_fields={"name": name, "description": description},
58
- )
59
-
60
- def delete(self, voice_id: int) -> None:
61
- """Delete a voice."""
62
- self._client.delete(f"/api/v1/voice/voices/{voice_id}")
63
-
64
- def speak(
65
- self,
66
- text: str,
67
- voice_id: int,
68
- *,
69
- speed: float = 1.0,
70
- ) -> Dict[str, Any]:
71
- """
72
- Generate speech from text.
73
-
74
- Args:
75
- text: Text to convert to speech
76
- voice_id: Voice ID to use
77
- speed: Speech speed (0.5 to 2.0)
78
-
79
- Returns:
80
- TTS job object
81
- """
82
- return self._client.post(
83
- "/api/v1/voice/tts/generate",
84
- json_data={
85
- "text": text,
86
- "voice_id": voice_id,
87
- "speed": speed,
88
- },
89
- )
90
-
91
- def get_job(self, job_id: int) -> Dict[str, Any]:
92
- """Get TTS job status."""
93
- return self._client.get(f"/api/v1/voice/tts/status/{job_id}")
94
-
95
- def wait_for_completion(
96
- self, job_id: int, timeout: int = DEFAULT_TIMEOUT
97
- ) -> Dict[str, Any]:
98
- """Wait for TTS job to complete."""
99
- start_time = time.time()
100
-
101
- while time.time() - start_time < timeout:
102
- job = self.get_job(job_id)
103
- status = job.get("status", "")
104
-
105
- if status == "COMPLETED":
106
- return job
107
- if status == "FAILED":
108
- raise RuntimeError(
109
- f"TTS generation failed: {job.get('error_message', 'Unknown error')}"
110
- )
111
-
112
- time.sleep(POLL_INTERVAL)
113
-
114
- raise TimeoutError(f"TTS generation timed out after {timeout}s")
115
-
116
- def generate(
117
- self,
118
- text: str,
119
- voice_id: int,
120
- *,
121
- speed: float = 1.0,
122
- timeout: int = DEFAULT_TIMEOUT,
123
- ) -> Dict[str, Any]:
124
- """
125
- Generate speech and wait for completion.
126
-
127
- Example:
128
- >>> result = client.voice.generate(
129
- ... text="Hello, world!",
130
- ... voice_id=123,
131
- ... )
132
- >>> print(result["output_url"])
133
- """
134
- job = self.speak(text, voice_id, speed=speed)
135
- return self.wait_for_completion(job["id"], timeout=timeout)
136
-
137
-
138
-
139
-
@@ -1,110 +0,0 @@
1
- """
2
- Wallet Service - API Wallet & Billing
3
- """
4
-
5
- from typing import Optional, Dict, Any, TYPE_CHECKING
6
-
7
- if TYPE_CHECKING:
8
- from ..client import AudioPod
9
-
10
-
11
- class Wallet:
12
- """API wallet and billing service."""
13
-
14
- def __init__(self, client: "AudioPod"):
15
- self._client = client
16
-
17
- def get_balance(self) -> Dict[str, Any]:
18
- """
19
- Get current wallet balance.
20
-
21
- Returns:
22
- Balance information including balance_cents, balance_usd, etc.
23
-
24
- Example:
25
- >>> balance = client.wallet.get_balance()
26
- >>> print(f"Balance: {balance['balance_usd']}")
27
- """
28
- return self._client.get("/api/v1/api-wallet/balance")
29
-
30
- def get_usage(
31
- self,
32
- *,
33
- page: int = 1,
34
- limit: int = 50,
35
- api_key_id: Optional[str] = None,
36
- ) -> Dict[str, Any]:
37
- """
38
- Get usage history.
39
-
40
- Args:
41
- page: Page number
42
- limit: Items per page
43
- api_key_id: Filter by specific API key
44
- """
45
- return self._client.get(
46
- "/api/v1/api-wallet/usage",
47
- params={"page": page, "limit": limit, "api_key_id": api_key_id},
48
- )
49
-
50
- def get_pricing(self) -> Dict[str, Any]:
51
- """
52
- Get pricing information for all services.
53
-
54
- Returns:
55
- Pricing table with rates per service
56
- """
57
- return self._client.get("/api/v1/api-wallet/pricing")
58
-
59
- def estimate_cost(
60
- self, service_type: str, duration_seconds: int
61
- ) -> Dict[str, Any]:
62
- """
63
- Estimate cost for an operation.
64
-
65
- Args:
66
- service_type: Service type (e.g., 'transcription', 'stem_extraction')
67
- duration_seconds: Duration in seconds
68
-
69
- Returns:
70
- Cost estimate with cost_cents and cost_usd
71
-
72
- Example:
73
- >>> estimate = client.wallet.estimate_cost(
74
- ... service_type="transcription",
75
- ... duration_seconds=3600,
76
- ... )
77
- >>> print(f"Estimated cost: {estimate['cost_usd']}")
78
- """
79
- return self._client.post(
80
- "/api/v1/api-wallet/estimate",
81
- json_data={
82
- "service_type": service_type,
83
- "duration_seconds": duration_seconds,
84
- },
85
- )
86
-
87
- def check_balance(
88
- self, service_type: str, duration_seconds: int
89
- ) -> Dict[str, Any]:
90
- """
91
- Check if balance is sufficient for an operation.
92
-
93
- Args:
94
- service_type: Service type
95
- duration_seconds: Duration in seconds
96
-
97
- Returns:
98
- Object with 'sufficient' boolean and cost details
99
- """
100
- return self._client.post(
101
- "/api/v1/api-wallet/check-balance",
102
- json_data={
103
- "service_type": service_type,
104
- "duration_seconds": duration_seconds,
105
- },
106
- )
107
-
108
-
109
-
110
-
@@ -1,205 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: audiopod
3
- Version: 2.1.0
4
- Summary: Official 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-sdk-python
10
- Project-URL: Issues, https://github.com/AudiopodAI/audiopod-sdk-python/issues
11
- Keywords: audiopod,audio,ai,speech-to-text,transcription,text-to-speech,tts,voice-cloning,music-generation,stem-separation,denoiser,speaker-diarization
12
- Classifier: Development Status :: 5 - Production/Stable
13
- Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: MIT License
15
- Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.8
18
- Classifier: Programming Language :: Python :: 3.9
19
- Classifier: Programming Language :: Python :: 3.10
20
- Classifier: Programming Language :: Python :: 3.11
21
- Classifier: Programming Language :: Python :: 3.12
22
- Classifier: Topic :: Multimedia :: Sound/Audio
23
- Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
24
- Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
25
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
26
- Classifier: Typing :: Typed
27
- Requires-Python: >=3.8
28
- Description-Content-Type: text/markdown
29
- License-File: LICENSE
30
- Requires-Dist: requests>=2.28.0
31
- Requires-Dist: urllib3>=1.26.0
32
- Provides-Extra: dev
33
- Requires-Dist: pytest>=7.0.0; extra == "dev"
34
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
35
- Requires-Dist: black>=23.0.0; extra == "dev"
36
- Requires-Dist: isort>=5.12.0; extra == "dev"
37
- Requires-Dist: mypy>=1.0.0; extra == "dev"
38
- Requires-Dist: types-requests>=2.28.0; extra == "dev"
39
- Dynamic: license-file
40
-
41
- # AudioPod Python SDK
42
-
43
- Official Python SDK for [AudioPod AI](https://audiopod.ai) - Professional Audio Processing powered by AI.
44
-
45
- [![PyPI version](https://badge.fury.io/py/audiopod.svg)](https://pypi.org/project/audiopod/)
46
- [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
47
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
48
-
49
- ## Installation
50
-
51
- ```bash
52
- pip install audiopod
53
- ```
54
-
55
- ## Quick Start
56
-
57
- ```python
58
- from audiopod import AudioPod
59
-
60
- # Initialize client
61
- client = AudioPod(api_key="ap_your_api_key")
62
-
63
- # Separate audio into 6 stems
64
- result = client.stems.separate(
65
- url="https://youtube.com/watch?v=VIDEO_ID",
66
- mode="six"
67
- )
68
-
69
- # Download stems
70
- for stem, url in result["download_urls"].items():
71
- print(f"{stem}: {url}")
72
- ```
73
-
74
- ## Stem Separation
75
-
76
- Extract individual audio components from mixed recordings.
77
-
78
- ### Available Modes
79
-
80
- | Mode | Stems | Output |
81
- |------|-------|--------|
82
- | `single` | 1 | Specified stem only (vocals, drums, bass, guitar, piano, other) |
83
- | `two` | 2 | Vocals + Instrumental |
84
- | `four` | 4 | Vocals, Drums, Bass, Other |
85
- | `six` | 6 | Vocals, Drums, Bass, Guitar, Piano, Other |
86
- | `producer` | 8 | + Kick, Snare, Hihat |
87
- | `studio` | 12 | Full production toolkit |
88
- | `mastering` | 16 | Maximum detail |
89
-
90
- ### Examples
91
-
92
- ```python
93
- from audiopod import AudioPod
94
-
95
- client = AudioPod(api_key="ap_your_api_key")
96
-
97
- # Six-stem separation from YouTube
98
- job = client.stems.extract(
99
- url="https://youtube.com/watch?v=VIDEO_ID",
100
- mode="six"
101
- )
102
- print(f"Job ID: {job['id']}")
103
-
104
- # Wait for completion
105
- result = client.stems.wait_for_completion(job["id"])
106
- print(result["download_urls"])
107
-
108
- # Or use the convenience method (extract + wait)
109
- result = client.stems.separate(
110
- url="https://youtube.com/watch?v=VIDEO_ID",
111
- mode="six"
112
- )
113
-
114
- # From local file
115
- result = client.stems.separate(
116
- file="./song.mp3",
117
- mode="four"
118
- )
119
-
120
- # Extract only vocals
121
- result = client.stems.separate(
122
- url="https://youtube.com/watch?v=VIDEO_ID",
123
- mode="single",
124
- stem="vocals"
125
- )
126
-
127
- # Get available modes
128
- modes = client.stems.modes()
129
- for m in modes["modes"]:
130
- print(f"{m['mode']}: {m['description']}")
131
- ```
132
-
133
- ## API Wallet
134
-
135
- Check balance and manage your wallet.
136
-
137
- ```python
138
- # Check balance
139
- balance = client.wallet.balance()
140
- print(f"Balance: {balance['balance_usd']}")
141
-
142
- # Estimate cost
143
- estimate = client.wallet.estimate("stem_extraction", duration_seconds=180)
144
- print(f"Estimated cost: {estimate['cost_usd']}")
145
-
146
- # Get usage history
147
- usage = client.wallet.usage()
148
- for log in usage["logs"]:
149
- print(f"{log['service_type']}: {log['amount_usd']}")
150
- ```
151
-
152
- ## Other Services
153
-
154
- ```python
155
- # Transcription
156
- job = client.transcription.create(url="https://...")
157
- result = client.transcription.wait_for_completion(job["id"])
158
-
159
- # Voice cloning
160
- voice = client.voice.clone(file="./sample.wav", name="My Voice")
161
-
162
- # Music generation
163
- song = client.music.generate(prompt="upbeat electronic dance music")
164
-
165
- # Noise reduction
166
- clean = client.denoiser.denoise(file="./noisy.wav")
167
-
168
- # Speaker diarization
169
- speakers = client.speaker.diarize(url="https://...")
170
- ```
171
-
172
- ## Error Handling
173
-
174
- ```python
175
- from audiopod import AudioPod, InsufficientBalanceError, AuthenticationError
176
-
177
- try:
178
- client = AudioPod(api_key="ap_...")
179
- result = client.stems.separate(url="...", mode="six")
180
- except AuthenticationError:
181
- print("Invalid API key")
182
- except InsufficientBalanceError as e:
183
- print(f"Need more credits. Required: {e.required_cents} cents")
184
- ```
185
-
186
- ## Environment Variables
187
-
188
- ```bash
189
- export AUDIOPOD_API_KEY="ap_your_api_key"
190
- ```
191
-
192
- ```python
193
- # Client reads from env automatically
194
- client = AudioPod()
195
- ```
196
-
197
- ## Documentation
198
-
199
- - [API Documentation](https://docs.audiopod.ai)
200
- - [API Reference](https://docs.audiopod.ai/api-reference/stem-splitter)
201
- - [Get API Key](https://www.audiopod.ai/dashboard/account/api-keys)
202
-
203
- ## License
204
-
205
- MIT License - see [LICENSE](LICENSE) for details.
@@ -1,16 +0,0 @@
1
- audiopod/__init__.py,sha256=UacaYDOzZMyFlXUtfNBnIZZPC5wjePjhYgxClJ31wio,661
2
- audiopod/client.py,sha256=mt9rYyxecSnODywkW7xuPQ9SZqhPO560VFLY7c-4f84,6632
3
- audiopod/exceptions.py,sha256=Xg3tNIwb0MoVyLZFqg5ifLIhh3mHgt-poneUB_a--Ag,1301
4
- audiopod/resources/__init__.py,sha256=I4R-sJmLwLCDbliAmhHwfjqVILCo2RnxjxYaI6PYDTs,375
5
- audiopod/resources/denoiser.py,sha256=n6-vyAor7FZnbEDZxgAtpnWIlMmHAIyoZsV5hY9xryQ,2996
6
- audiopod/resources/music.py,sha256=pXScN9DXNXYgFtvgjhiDShJpGNx5A0r_HsqTFiweBZ8,4742
7
- audiopod/resources/speaker.py,sha256=uEGbfuIUNGof6FJe9vODKwQ8NG-3Tz293ZUYEfd96NA,3612
8
- audiopod/resources/stems.py,sha256=kaYvJq84rJOH8wFDzVhN9kECzr2LeCseoa7_dXV4dsc,8524
9
- audiopod/resources/transcription.py,sha256=p-X5l8mbXrcUnsjqcdvN4SiZtM4EOitAg9Ipf_ubjkQ,6142
10
- audiopod/resources/voice.py,sha256=CCsRA23r3IMjVrU6sM2uiSMDs-D4Vi2pcu_nUGp9iAk,3646
11
- audiopod/resources/wallet.py,sha256=PksHlUv8jPcjwIpH0s2uYvr2y_g8BQWBhwyPwFr6Qco,2898
12
- audiopod-2.1.0.dist-info/licenses/LICENSE,sha256=hqEjnOaGNbnLSBxbtbC7WQVREU2vQI8FmwecCiZlMfA,1068
13
- audiopod-2.1.0.dist-info/METADATA,sha256=MIJ9npAwwfraOMxfrrN1LZtOC7y1VQw363t-5EbFoTk,5769
14
- audiopod-2.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- audiopod-2.1.0.dist-info/top_level.txt,sha256=M6yyOFFNpLdH4i1AMRqJZLRIgfpg1NvrQVmnPd8A6N8,9
16
- audiopod-2.1.0.dist-info/RECORD,,