audiopod 1.4.0__py3-none-any.whl → 2.1.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,28 +0,0 @@
1
- """
2
- AudioPod SDK Services
3
- """
4
-
5
- from .base import BaseService
6
- from .voice import VoiceService
7
- from .music import MusicService
8
- from .transcription import TranscriptionService
9
- from .translation import TranslationService
10
- from .speaker import SpeakerService
11
- from .denoiser import DenoiserService
12
- from .credits import CreditService
13
- from .stem_extraction import StemExtractionService
14
- from .wallet import WalletService
15
-
16
- __all__ = [
17
- "BaseService",
18
- "VoiceService",
19
- "MusicService",
20
- "TranscriptionService",
21
- "TranslationService",
22
- "SpeakerService",
23
- "DenoiserService",
24
- "CreditService",
25
- "StemExtractionService",
26
- "WalletService",
27
- ]
28
-
audiopod/services/base.py DELETED
@@ -1,69 +0,0 @@
1
- """
2
- Base Service Class
3
- """
4
-
5
- import time
6
- from typing import Any, Dict, Optional, Tuple, BinaryIO
7
-
8
-
9
- class BaseService:
10
- """Base class for all services"""
11
-
12
- def __init__(self, client: Any, async_mode: bool = False):
13
- self.client = client
14
- self.async_mode = async_mode
15
-
16
- def _prepare_file_upload(
17
- self, file_path: str, field_name: str = "file"
18
- ) -> Dict[str, Tuple[str, BinaryIO, str]]:
19
- """Prepare file for upload."""
20
- import mimetypes
21
-
22
- mime_type, _ = mimetypes.guess_type(file_path)
23
- mime_type = mime_type or "application/octet-stream"
24
-
25
- file_handle = open(file_path, "rb")
26
- filename = file_path.split("/")[-1]
27
-
28
- return {field_name: (filename, file_handle, mime_type)}
29
-
30
- def _wait_for_completion(
31
- self, job_id: int, timeout: int = 900, poll_interval: int = 5
32
- ) -> Dict[str, Any]:
33
- """Wait for job completion."""
34
- start_time = time.time()
35
-
36
- while time.time() - start_time < timeout:
37
- response = self.client.request("GET", f"/api/v1/jobs/{job_id}")
38
-
39
- status = response.get("status", "").upper()
40
- if status == "COMPLETED":
41
- return response
42
- elif status in ["FAILED", "ERROR"]:
43
- raise Exception(f"Job failed: {response.get('error_message', 'Unknown error')}")
44
-
45
- time.sleep(poll_interval)
46
-
47
- raise TimeoutError(f"Job {job_id} did not complete within {timeout} seconds")
48
-
49
- async def _async_wait_for_completion(
50
- self, job_id: int, timeout: int = 900, poll_interval: int = 5
51
- ) -> Dict[str, Any]:
52
- """Async wait for job completion."""
53
- import asyncio
54
-
55
- start_time = time.time()
56
-
57
- while time.time() - start_time < timeout:
58
- response = await self.client.request("GET", f"/api/v1/jobs/{job_id}")
59
-
60
- status = response.get("status", "").upper()
61
- if status == "COMPLETED":
62
- return response
63
- elif status in ["FAILED", "ERROR"]:
64
- raise Exception(f"Job failed: {response.get('error_message', 'Unknown error')}")
65
-
66
- await asyncio.sleep(poll_interval)
67
-
68
- raise TimeoutError(f"Job {job_id} did not complete within {timeout} seconds")
69
-
@@ -1,42 +0,0 @@
1
- """
2
- Credits Service - User credits and usage (subscription credits)
3
- """
4
-
5
- from typing import List, Dict, Any
6
- from .base import BaseService
7
-
8
-
9
- class CreditService(BaseService):
10
- """
11
- Service for managing subscription credits.
12
-
13
- Note: For API wallet (USD-based billing), use client.wallet instead.
14
- """
15
-
16
- def get_balance(self) -> Dict[str, Any]:
17
- """Get subscription credit balance."""
18
- if self.async_mode:
19
- return self._async_get_balance()
20
- return self.client.request("GET", "/api/v1/credits")
21
-
22
- async def _async_get_balance(self) -> Dict[str, Any]:
23
- return await self.client.request("GET", "/api/v1/credits")
24
-
25
- def get_usage_history(self) -> List[Dict[str, Any]]:
26
- """Get credit usage history."""
27
- if self.async_mode:
28
- return self._async_get_usage_history()
29
- return self.client.request("GET", "/api/v1/credits/usage")
30
-
31
- async def _async_get_usage_history(self) -> List[Dict[str, Any]]:
32
- return await self.client.request("GET", "/api/v1/credits/usage")
33
-
34
- def get_multipliers(self) -> Dict[str, float]:
35
- """Get credit multipliers for services."""
36
- if self.async_mode:
37
- return self._async_get_multipliers()
38
- return self.client.request("GET", "/api/v1/credits/multipliers")
39
-
40
- async def _async_get_multipliers(self) -> Dict[str, float]:
41
- return await self.client.request("GET", "/api/v1/credits/multipliers")
42
-
@@ -1,131 +0,0 @@
1
- """
2
- Denoiser Service - Audio noise reduction
3
-
4
- API Routes:
5
- - POST /api/v1/denoiser/denoise - Denoise audio
6
- - GET /api/v1/denoiser/jobs/{id} - Get job details
7
- - GET /api/v1/denoiser/jobs - List jobs
8
- - DELETE /api/v1/denoiser/jobs/{id} - Delete job
9
- """
10
-
11
- from typing import Optional, Dict, Any, List
12
- from .base import BaseService
13
-
14
-
15
- class DenoiserService(BaseService):
16
- """Service for audio noise reduction."""
17
-
18
- def denoise(
19
- self,
20
- audio_file: Optional[str] = None,
21
- url: Optional[str] = None,
22
- mode: str = "balanced",
23
- wait_for_completion: bool = False,
24
- timeout: int = 300,
25
- ) -> Dict[str, Any]:
26
- """
27
- Remove noise from audio.
28
-
29
- Args:
30
- audio_file: Path to local audio file
31
- url: URL of audio file
32
- mode: Denoise mode ("balanced", "studio", or "ultra")
33
- wait_for_completion: Wait for completion
34
- timeout: Max wait time in seconds
35
-
36
- Returns:
37
- Job dict with denoised audio URL when completed
38
- """
39
- data = {"mode": mode}
40
- if url:
41
- data["url"] = url
42
-
43
- files = self._prepare_file_upload(audio_file, "file") if audio_file else None
44
-
45
- if self.async_mode:
46
- return self._async_denoise(data, files, wait_for_completion, timeout)
47
-
48
- response = self.client.request("POST", "/api/v1/denoiser/denoise", data=data, files=files)
49
-
50
- if wait_for_completion:
51
- job_id = response.get("id") or response.get("job_id")
52
- return self._wait_for_denoise(job_id, timeout)
53
- return response
54
-
55
- async def _async_denoise(
56
- self, data: Dict, files: Optional[Dict], wait_for_completion: bool, timeout: int
57
- ) -> Dict[str, Any]:
58
- response = await self.client.request("POST", "/api/v1/denoiser/denoise", data=data, files=files)
59
- if wait_for_completion:
60
- job_id = response.get("id") or response.get("job_id")
61
- return await self._async_wait_for_denoise(job_id, timeout)
62
- return response
63
-
64
- def get_job(self, job_id: int) -> Dict[str, Any]:
65
- """Get denoise job details and status."""
66
- if self.async_mode:
67
- return self._async_get_job(job_id)
68
- return self.client.request("GET", f"/api/v1/denoiser/jobs/{job_id}")
69
-
70
- async def _async_get_job(self, job_id: int) -> Dict[str, Any]:
71
- return await self.client.request("GET", f"/api/v1/denoiser/jobs/{job_id}")
72
-
73
- def list_jobs(self, skip: int = 0, limit: int = 50) -> List[Dict[str, Any]]:
74
- """List denoiser jobs."""
75
- if self.async_mode:
76
- return self._async_list_jobs(skip, limit)
77
- return self.client.request(
78
- "GET", "/api/v1/denoiser/jobs", params={"skip": skip, "limit": limit}
79
- )
80
-
81
- async def _async_list_jobs(self, skip: int, limit: int) -> List[Dict[str, Any]]:
82
- return await self.client.request(
83
- "GET", "/api/v1/denoiser/jobs", params={"skip": skip, "limit": limit}
84
- )
85
-
86
- def delete_job(self, job_id: int) -> Dict[str, str]:
87
- """Delete a denoiser job."""
88
- if self.async_mode:
89
- return self._async_delete_job(job_id)
90
- return self.client.request("DELETE", f"/api/v1/denoiser/jobs/{job_id}")
91
-
92
- async def _async_delete_job(self, job_id: int) -> Dict[str, str]:
93
- return await self.client.request("DELETE", f"/api/v1/denoiser/jobs/{job_id}")
94
-
95
- def _wait_for_denoise(self, job_id: int, timeout: int) -> Dict[str, Any]:
96
- """Wait for denoise job completion."""
97
- import time
98
- start_time = time.time()
99
-
100
- while time.time() - start_time < timeout:
101
- job = self.get_job(job_id)
102
- status = job.get("status", "").upper()
103
-
104
- if status == "COMPLETED":
105
- return job
106
- elif status in ("FAILED", "ERROR"):
107
- raise Exception(f"Denoising failed: {job.get('error_message', 'Unknown error')}")
108
-
109
- time.sleep(3)
110
-
111
- raise TimeoutError(f"Denoising {job_id} did not complete within {timeout} seconds")
112
-
113
- async def _async_wait_for_denoise(self, job_id: int, timeout: int) -> Dict[str, Any]:
114
- """Async wait for denoise job completion."""
115
- import asyncio
116
- import time
117
- start_time = time.time()
118
-
119
- while time.time() - start_time < timeout:
120
- job = await self.get_job(job_id)
121
- status = job.get("status", "").upper()
122
-
123
- if status == "COMPLETED":
124
- return job
125
- elif status in ("FAILED", "ERROR"):
126
- raise Exception(f"Denoising failed: {job.get('error_message', 'Unknown error')}")
127
-
128
- await asyncio.sleep(3)
129
-
130
- raise TimeoutError(f"Denoising {job_id} did not complete within {timeout} seconds")
131
-
@@ -1,217 +0,0 @@
1
- """
2
- Music Service - Music generation
3
-
4
- API Routes:
5
- - POST /api/v1/music/text2music - Generate music with vocals
6
- - POST /api/v1/music/prompt2instrumental - Generate instrumental music
7
- - POST /api/v1/music/lyric2vocals - Generate vocals from lyrics
8
- - POST /api/v1/music/text2rap - Generate rap music
9
- - GET /api/v1/music/jobs/{id}/status - Get job status
10
- - GET /api/v1/music/jobs - List jobs
11
- - DELETE /api/v1/music/jobs/{id} - Delete job
12
- - GET /api/v1/music/presets - Get genre presets
13
- """
14
-
15
- from typing import Optional, Dict, Any, List, Literal
16
- from .base import BaseService
17
-
18
-
19
- MusicTask = Literal["text2music", "prompt2instrumental", "lyric2vocals", "text2rap", "text2samples"]
20
-
21
-
22
- class MusicService(BaseService):
23
- """Service for AI music generation."""
24
-
25
- def generate(
26
- self,
27
- prompt: str,
28
- task: MusicTask = "prompt2instrumental",
29
- duration: int = 30,
30
- lyrics: Optional[str] = None,
31
- genre_preset: Optional[str] = None,
32
- display_name: Optional[str] = None,
33
- wait_for_completion: bool = False,
34
- timeout: int = 600,
35
- ) -> Dict[str, Any]:
36
- """
37
- Generate music from text prompt.
38
-
39
- Args:
40
- prompt: Text description of desired music
41
- task: Generation task type:
42
- - "prompt2instrumental": Instrumental music (no vocals)
43
- - "text2music": Music with vocals (requires lyrics)
44
- - "text2rap": Rap music (requires lyrics)
45
- - "lyric2vocals": Generate vocals from lyrics
46
- duration: Duration in seconds (default 30, max varies by task)
47
- lyrics: Lyrics for vocal tasks
48
- genre_preset: Genre preset name
49
- display_name: Custom name for the job
50
- wait_for_completion: Wait for completion
51
- timeout: Max wait time in seconds
52
-
53
- Returns:
54
- Job dict with audio URL when completed
55
- """
56
- data = {
57
- "prompt": prompt,
58
- "audio_duration": duration,
59
- }
60
-
61
- if lyrics:
62
- data["lyrics"] = lyrics
63
- if genre_preset:
64
- data["genre_preset"] = genre_preset
65
- if display_name:
66
- data["display_name"] = display_name
67
-
68
- endpoint = f"/api/v1/music/{task}"
69
-
70
- if self.async_mode:
71
- return self._async_generate(endpoint, data, wait_for_completion, timeout)
72
-
73
- response = self.client.request("POST", endpoint, json_data=data)
74
-
75
- if wait_for_completion:
76
- job_id = response.get("id") or response.get("job_id")
77
- return self._wait_for_music(job_id, timeout)
78
- return response
79
-
80
- async def _async_generate(
81
- self, endpoint: str, data: Dict, wait_for_completion: bool, timeout: int
82
- ) -> Dict[str, Any]:
83
- response = await self.client.request("POST", endpoint, json_data=data)
84
- if wait_for_completion:
85
- job_id = response.get("id") or response.get("job_id")
86
- return await self._async_wait_for_music(job_id, timeout)
87
- return response
88
-
89
- def instrumental(
90
- self,
91
- prompt: str,
92
- duration: int = 30,
93
- wait_for_completion: bool = False,
94
- timeout: int = 600,
95
- ) -> Dict[str, Any]:
96
- """Generate instrumental music (no vocals)."""
97
- return self.generate(
98
- prompt=prompt,
99
- task="prompt2instrumental",
100
- duration=duration,
101
- wait_for_completion=wait_for_completion,
102
- timeout=timeout,
103
- )
104
-
105
- def song(
106
- self,
107
- prompt: str,
108
- lyrics: str,
109
- duration: int = 60,
110
- wait_for_completion: bool = False,
111
- timeout: int = 600,
112
- ) -> Dict[str, Any]:
113
- """Generate a song with vocals."""
114
- return self.generate(
115
- prompt=prompt,
116
- task="text2music",
117
- lyrics=lyrics,
118
- duration=duration,
119
- wait_for_completion=wait_for_completion,
120
- timeout=timeout,
121
- )
122
-
123
- def rap(
124
- self,
125
- prompt: str,
126
- lyrics: str,
127
- duration: int = 60,
128
- wait_for_completion: bool = False,
129
- timeout: int = 600,
130
- ) -> Dict[str, Any]:
131
- """Generate rap music."""
132
- return self.generate(
133
- prompt=prompt,
134
- task="text2rap",
135
- lyrics=lyrics,
136
- duration=duration,
137
- wait_for_completion=wait_for_completion,
138
- timeout=timeout,
139
- )
140
-
141
- def get_job(self, job_id: int) -> Dict[str, Any]:
142
- """Get music generation job status."""
143
- if self.async_mode:
144
- return self._async_get_job(job_id)
145
- return self.client.request("GET", f"/api/v1/music/jobs/{job_id}/status")
146
-
147
- async def _async_get_job(self, job_id: int) -> Dict[str, Any]:
148
- return await self.client.request("GET", f"/api/v1/music/jobs/{job_id}/status")
149
-
150
- def list_jobs(self, skip: int = 0, limit: int = 50, task: Optional[str] = None) -> List[Dict[str, Any]]:
151
- """List music generation jobs."""
152
- params = {"skip": skip, "limit": limit}
153
- if task:
154
- params["task"] = task
155
-
156
- if self.async_mode:
157
- return self._async_list_jobs(params)
158
- return self.client.request("GET", "/api/v1/music/jobs", params=params)
159
-
160
- async def _async_list_jobs(self, params: Dict) -> List[Dict[str, Any]]:
161
- return await self.client.request("GET", "/api/v1/music/jobs", params=params)
162
-
163
- def delete_job(self, job_id: int) -> Dict[str, str]:
164
- """Delete a music generation job."""
165
- if self.async_mode:
166
- return self._async_delete_job(job_id)
167
- return self.client.request("DELETE", f"/api/v1/music/jobs/{job_id}")
168
-
169
- async def _async_delete_job(self, job_id: int) -> Dict[str, str]:
170
- return await self.client.request("DELETE", f"/api/v1/music/jobs/{job_id}")
171
-
172
- def get_presets(self) -> Dict[str, Any]:
173
- """Get available genre presets."""
174
- if self.async_mode:
175
- return self._async_get_presets()
176
- return self.client.request("GET", "/api/v1/music/presets")
177
-
178
- async def _async_get_presets(self) -> Dict[str, Any]:
179
- return await self.client.request("GET", "/api/v1/music/presets")
180
-
181
- def _wait_for_music(self, job_id: int, timeout: int) -> Dict[str, Any]:
182
- """Wait for music generation job completion."""
183
- import time
184
- start_time = time.time()
185
-
186
- while time.time() - start_time < timeout:
187
- job = self.get_job(job_id)
188
- status = job.get("status", "").upper()
189
-
190
- if status == "COMPLETED":
191
- return job
192
- elif status in ("FAILED", "ERROR"):
193
- raise Exception(f"Music generation failed: {job.get('error_message', 'Unknown error')}")
194
-
195
- time.sleep(5)
196
-
197
- raise TimeoutError(f"Music generation {job_id} did not complete within {timeout} seconds")
198
-
199
- async def _async_wait_for_music(self, job_id: int, timeout: int) -> Dict[str, Any]:
200
- """Async wait for music generation job completion."""
201
- import asyncio
202
- import time
203
- start_time = time.time()
204
-
205
- while time.time() - start_time < timeout:
206
- job = await self.get_job(job_id)
207
- status = job.get("status", "").upper()
208
-
209
- if status == "COMPLETED":
210
- return job
211
- elif status in ("FAILED", "ERROR"):
212
- raise Exception(f"Music generation failed: {job.get('error_message', 'Unknown error')}")
213
-
214
- await asyncio.sleep(5)
215
-
216
- raise TimeoutError(f"Music generation {job_id} did not complete within {timeout} seconds")
217
-
@@ -1,134 +0,0 @@
1
- """
2
- Speaker Service - Speaker diarization and extraction
3
- """
4
-
5
- from typing import Optional, Dict, Any, List
6
- from .base import BaseService
7
-
8
-
9
- class SpeakerService(BaseService):
10
- """Service for speaker diarization and extraction."""
11
-
12
- def diarize(
13
- self,
14
- audio_file: Optional[str] = None,
15
- url: Optional[str] = None,
16
- num_speakers: Optional[int] = None,
17
- wait_for_completion: bool = False,
18
- timeout: int = 600,
19
- ) -> Dict[str, Any]:
20
- """
21
- Identify and separate speakers in audio.
22
-
23
- Args:
24
- audio_file: Path to local audio file
25
- url: URL of audio file
26
- num_speakers: Expected number of speakers (auto-detected if not provided)
27
- wait_for_completion: Wait for completion
28
- timeout: Max wait time in seconds
29
-
30
- Returns:
31
- Job dict with speaker segments when completed
32
- """
33
- data = {}
34
- if num_speakers:
35
- data["num_speakers"] = num_speakers
36
- if url:
37
- data["url"] = url
38
-
39
- files = self._prepare_file_upload(audio_file, "file") if audio_file else None
40
-
41
- if self.async_mode:
42
- return self._async_diarize(data, files, wait_for_completion, timeout)
43
-
44
- response = self.client.request("POST", "/api/v1/speaker/diarize", data=data, files=files)
45
-
46
- if wait_for_completion:
47
- return self._wait_for_completion(response["id"], timeout)
48
- return response
49
-
50
- async def _async_diarize(
51
- self, data: Dict, files: Optional[Dict], wait_for_completion: bool, timeout: int
52
- ) -> Dict[str, Any]:
53
- response = await self.client.request(
54
- "POST", "/api/v1/speaker/diarize", data=data, files=files
55
- )
56
- if wait_for_completion:
57
- return await self._async_wait_for_completion(response["id"], timeout)
58
- return response
59
-
60
- def extract(
61
- self,
62
- audio_file: Optional[str] = None,
63
- url: Optional[str] = None,
64
- wait_for_completion: bool = False,
65
- timeout: int = 600,
66
- ) -> Dict[str, Any]:
67
- """
68
- Extract individual speaker audio tracks.
69
-
70
- Args:
71
- audio_file: Path to local audio file
72
- url: URL of audio file
73
- wait_for_completion: Wait for completion
74
- timeout: Max wait time in seconds
75
-
76
- Returns:
77
- Job dict with speaker audio URLs when completed
78
- """
79
- data = {}
80
- if url:
81
- data["url"] = url
82
-
83
- files = self._prepare_file_upload(audio_file, "file") if audio_file else None
84
-
85
- if self.async_mode:
86
- return self._async_extract(data, files, wait_for_completion, timeout)
87
-
88
- response = self.client.request("POST", "/api/v1/speaker/extract", data=data, files=files)
89
-
90
- if wait_for_completion:
91
- return self._wait_for_completion(response["id"], timeout)
92
- return response
93
-
94
- async def _async_extract(
95
- self, data: Dict, files: Optional[Dict], wait_for_completion: bool, timeout: int
96
- ) -> Dict[str, Any]:
97
- response = await self.client.request(
98
- "POST", "/api/v1/speaker/extract", data=data, files=files
99
- )
100
- if wait_for_completion:
101
- return await self._async_wait_for_completion(response["id"], timeout)
102
- return response
103
-
104
- def get_job(self, job_id: int) -> Dict[str, Any]:
105
- """Get speaker job details and status."""
106
- if self.async_mode:
107
- return self._async_get_job(job_id)
108
- return self.client.request("GET", f"/api/v1/speaker/jobs/{job_id}")
109
-
110
- async def _async_get_job(self, job_id: int) -> Dict[str, Any]:
111
- return await self.client.request("GET", f"/api/v1/speaker/jobs/{job_id}")
112
-
113
- def list_jobs(self, skip: int = 0, limit: int = 50) -> List[Dict[str, Any]]:
114
- """List speaker jobs."""
115
- if self.async_mode:
116
- return self._async_list_jobs(skip, limit)
117
- return self.client.request(
118
- "GET", "/api/v1/speaker/jobs", params={"skip": skip, "limit": limit}
119
- )
120
-
121
- async def _async_list_jobs(self, skip: int, limit: int) -> List[Dict[str, Any]]:
122
- return await self.client.request(
123
- "GET", "/api/v1/speaker/jobs", params={"skip": skip, "limit": limit}
124
- )
125
-
126
- def delete_job(self, job_id: int) -> Dict[str, str]:
127
- """Delete a speaker job."""
128
- if self.async_mode:
129
- return self._async_delete_job(job_id)
130
- return self.client.request("DELETE", f"/api/v1/speaker/jobs/{job_id}")
131
-
132
- async def _async_delete_job(self, job_id: int) -> Dict[str, str]:
133
- return await self.client.request("DELETE", f"/api/v1/speaker/jobs/{job_id}")
134
-