audiopod 1.0.0__py3-none-any.whl → 1.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.
- audiopod/__init__.py +1 -1
- audiopod/client.py +4 -1
- audiopod/py.typed +2 -0
- audiopod/services/__init__.py +3 -1
- audiopod/services/music.py +104 -16
- audiopod/services/stem_extraction.py +180 -0
- {audiopod-1.0.0.dist-info → audiopod-1.1.0.dist-info}/METADATA +5 -4
- {audiopod-1.0.0.dist-info → audiopod-1.1.0.dist-info}/RECORD +12 -9
- audiopod-1.1.0.dist-info/licenses/LICENSE +21 -0
- {audiopod-1.0.0.dist-info → audiopod-1.1.0.dist-info}/WHEEL +0 -0
- {audiopod-1.0.0.dist-info → audiopod-1.1.0.dist-info}/entry_points.txt +0 -0
- {audiopod-1.0.0.dist-info → audiopod-1.1.0.dist-info}/top_level.txt +0 -0
audiopod/__init__.py
CHANGED
audiopod/client.py
CHANGED
|
@@ -23,7 +23,8 @@ from .services import (
|
|
|
23
23
|
SpeakerService,
|
|
24
24
|
DenoiserService,
|
|
25
25
|
KaraokeService,
|
|
26
|
-
CreditService
|
|
26
|
+
CreditService,
|
|
27
|
+
StemExtractionService
|
|
27
28
|
)
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
@@ -139,6 +140,7 @@ class Client(BaseClient):
|
|
|
139
140
|
self.denoiser = DenoiserService(self)
|
|
140
141
|
self.karaoke = KaraokeService(self)
|
|
141
142
|
self.credits = CreditService(self)
|
|
143
|
+
self.stem_extraction = StemExtractionService(self)
|
|
142
144
|
|
|
143
145
|
def request(
|
|
144
146
|
self,
|
|
@@ -227,6 +229,7 @@ class AsyncClient(BaseClient):
|
|
|
227
229
|
self.denoiser = DenoiserService(self, async_mode=True)
|
|
228
230
|
self.karaoke = KaraokeService(self, async_mode=True)
|
|
229
231
|
self.credits = CreditService(self, async_mode=True)
|
|
232
|
+
self.stem_extraction = StemExtractionService(self, async_mode=True)
|
|
230
233
|
|
|
231
234
|
@property
|
|
232
235
|
def session(self) -> aiohttp.ClientSession:
|
audiopod/py.typed
ADDED
audiopod/services/__init__.py
CHANGED
|
@@ -11,6 +11,7 @@ from .speaker import SpeakerService
|
|
|
11
11
|
from .denoiser import DenoiserService
|
|
12
12
|
from .karaoke import KaraokeService
|
|
13
13
|
from .credits import CreditService
|
|
14
|
+
from .stem_extraction import StemExtractionService
|
|
14
15
|
|
|
15
16
|
__all__ = [
|
|
16
17
|
"VoiceService",
|
|
@@ -20,5 +21,6 @@ __all__ = [
|
|
|
20
21
|
"SpeakerService",
|
|
21
22
|
"DenoiserService",
|
|
22
23
|
"KaraokeService",
|
|
23
|
-
"CreditService"
|
|
24
|
+
"CreditService",
|
|
25
|
+
"StemExtractionService"
|
|
24
26
|
]
|
audiopod/services/music.py
CHANGED
|
@@ -51,15 +51,15 @@ class MusicService(BaseService):
|
|
|
51
51
|
if seed is not None and (seed < 0 or seed > 2**32 - 1):
|
|
52
52
|
raise ValidationError("Seed must be between 0 and 2^32 - 1")
|
|
53
53
|
|
|
54
|
-
# Prepare request data
|
|
54
|
+
# Prepare request data - FIXED: Use correct parameter names matching API schema
|
|
55
55
|
data = {
|
|
56
56
|
"prompt": prompt,
|
|
57
|
-
"
|
|
57
|
+
"audio_duration": duration, # FIXED: API expects "audio_duration" not "duration"
|
|
58
58
|
"guidance_scale": guidance_scale,
|
|
59
|
-
"
|
|
59
|
+
"infer_step": num_inference_steps # FIXED: API expects "infer_step" not "num_inference_steps"
|
|
60
60
|
}
|
|
61
61
|
if seed is not None:
|
|
62
|
-
data["
|
|
62
|
+
data["manual_seeds"] = [seed] # FIXED: API expects "manual_seeds" list not "seed"
|
|
63
63
|
if display_name:
|
|
64
64
|
data["display_name"] = display_name.strip()
|
|
65
65
|
|
|
@@ -68,7 +68,9 @@ class MusicService(BaseService):
|
|
|
68
68
|
return self._async_generate_music(data, wait_for_completion, timeout)
|
|
69
69
|
else:
|
|
70
70
|
response = self.client.request("POST", "/api/v1/music/text2music", data=data)
|
|
71
|
-
job
|
|
71
|
+
# FIXED: Handle response format correctly - API returns {"job": {...}, "message": "..."}
|
|
72
|
+
job_data = response.get("job", response)
|
|
73
|
+
job = Job.from_dict(job_data)
|
|
72
74
|
|
|
73
75
|
if wait_for_completion:
|
|
74
76
|
completed_job = self._wait_for_completion(job.id, timeout)
|
|
@@ -84,7 +86,9 @@ class MusicService(BaseService):
|
|
|
84
86
|
) -> Union[Job, MusicGenerationResult]:
|
|
85
87
|
"""Async version of generate_music"""
|
|
86
88
|
response = await self.client.request("POST", "/api/v1/music/text2music", data=data)
|
|
87
|
-
|
|
89
|
+
# FIXED: Handle response format correctly
|
|
90
|
+
job_data = response.get("job", response)
|
|
91
|
+
job = Job.from_dict(job_data)
|
|
88
92
|
|
|
89
93
|
if wait_for_completion:
|
|
90
94
|
completed_job = await self._async_wait_for_completion(job.id, timeout)
|
|
@@ -122,11 +126,14 @@ class MusicService(BaseService):
|
|
|
122
126
|
if style not in ["modern", "classic", "trap"]:
|
|
123
127
|
raise ValidationError("Style must be 'modern', 'classic', or 'trap'")
|
|
124
128
|
|
|
125
|
-
# Prepare request data
|
|
129
|
+
# Prepare request data - FIXED: Match API schema for text2rap
|
|
126
130
|
data = {
|
|
131
|
+
"prompt": f"rap music, {style} style", # FIXED: API expects "prompt" field
|
|
127
132
|
"lyrics": lyrics,
|
|
128
|
-
"
|
|
129
|
-
"
|
|
133
|
+
"audio_duration": 120.0, # Default duration
|
|
134
|
+
"guidance_scale": 7.5,
|
|
135
|
+
"infer_step": 50,
|
|
136
|
+
"lora_name_or_path": "ACE-Step/ACE-Step-v1-chinese-rap-LoRA" # Rap-specific LoRA
|
|
130
137
|
}
|
|
131
138
|
if display_name:
|
|
132
139
|
data["display_name"] = display_name.strip()
|
|
@@ -136,7 +143,9 @@ class MusicService(BaseService):
|
|
|
136
143
|
return self._async_generate_rap(data, wait_for_completion, timeout)
|
|
137
144
|
else:
|
|
138
145
|
response = self.client.request("POST", "/api/v1/music/text2rap", data=data)
|
|
139
|
-
|
|
146
|
+
# FIXED: Handle response format correctly
|
|
147
|
+
job_data = response.get("job", response)
|
|
148
|
+
job = Job.from_dict(job_data)
|
|
140
149
|
|
|
141
150
|
if wait_for_completion:
|
|
142
151
|
completed_job = self._wait_for_completion(job.id, timeout)
|
|
@@ -152,7 +161,9 @@ class MusicService(BaseService):
|
|
|
152
161
|
) -> Union[Job, MusicGenerationResult]:
|
|
153
162
|
"""Async version of generate_rap"""
|
|
154
163
|
response = await self.client.request("POST", "/api/v1/music/text2rap", data=data)
|
|
155
|
-
|
|
164
|
+
# FIXED: Handle response format correctly
|
|
165
|
+
job_data = response.get("job", response)
|
|
166
|
+
job = Job.from_dict(job_data)
|
|
156
167
|
|
|
157
168
|
if wait_for_completion:
|
|
158
169
|
completed_job = await self._async_wait_for_completion(job.id, timeout)
|
|
@@ -194,10 +205,12 @@ class MusicService(BaseService):
|
|
|
194
205
|
if tempo is not None and not 60 <= tempo <= 200:
|
|
195
206
|
raise ValidationError("Tempo must be between 60 and 200 BPM")
|
|
196
207
|
|
|
197
|
-
# Prepare request data
|
|
208
|
+
# Prepare request data - FIXED: Match API schema for prompt2instrumental
|
|
198
209
|
data = {
|
|
199
210
|
"prompt": prompt,
|
|
200
|
-
"
|
|
211
|
+
"audio_duration": duration, # FIXED: API expects "audio_duration"
|
|
212
|
+
"guidance_scale": 7.5,
|
|
213
|
+
"infer_step": 50
|
|
201
214
|
}
|
|
202
215
|
if instruments:
|
|
203
216
|
data["instruments"] = instruments
|
|
@@ -213,7 +226,9 @@ class MusicService(BaseService):
|
|
|
213
226
|
return self._async_generate_instrumental(data, wait_for_completion, timeout)
|
|
214
227
|
else:
|
|
215
228
|
response = self.client.request("POST", "/api/v1/music/prompt2instrumental", data=data)
|
|
216
|
-
|
|
229
|
+
# FIXED: Handle response format correctly
|
|
230
|
+
job_data = response.get("job", response)
|
|
231
|
+
job = Job.from_dict(job_data)
|
|
217
232
|
|
|
218
233
|
if wait_for_completion:
|
|
219
234
|
completed_job = self._wait_for_completion(job.id, timeout)
|
|
@@ -229,7 +244,80 @@ class MusicService(BaseService):
|
|
|
229
244
|
) -> Union[Job, MusicGenerationResult]:
|
|
230
245
|
"""Async version of generate_instrumental"""
|
|
231
246
|
response = await self.client.request("POST", "/api/v1/music/prompt2instrumental", data=data)
|
|
232
|
-
|
|
247
|
+
# FIXED: Handle response format correctly
|
|
248
|
+
job_data = response.get("job", response)
|
|
249
|
+
job = Job.from_dict(job_data)
|
|
250
|
+
|
|
251
|
+
if wait_for_completion:
|
|
252
|
+
completed_job = await self._async_wait_for_completion(job.id, timeout)
|
|
253
|
+
return MusicGenerationResult.from_dict(completed_job.result or completed_job.__dict__)
|
|
254
|
+
|
|
255
|
+
return job
|
|
256
|
+
|
|
257
|
+
def generate_vocals(
|
|
258
|
+
self,
|
|
259
|
+
lyrics: str,
|
|
260
|
+
prompt: str = "vocals",
|
|
261
|
+
duration: float = 120.0,
|
|
262
|
+
display_name: Optional[str] = None,
|
|
263
|
+
wait_for_completion: bool = False,
|
|
264
|
+
timeout: int = 600
|
|
265
|
+
) -> Union[Job, MusicGenerationResult]:
|
|
266
|
+
"""
|
|
267
|
+
Generate vocals from lyrics - NEW METHOD matching API lyric2vocals endpoint
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
lyrics: Song lyrics
|
|
271
|
+
prompt: Vocal style description
|
|
272
|
+
duration: Duration in seconds
|
|
273
|
+
display_name: Custom name for the track
|
|
274
|
+
wait_for_completion: Whether to wait for completion
|
|
275
|
+
timeout: Maximum time to wait
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
Job object or generation result
|
|
279
|
+
"""
|
|
280
|
+
# Validate inputs
|
|
281
|
+
lyrics = self._validate_text_input(lyrics, max_length=10000)
|
|
282
|
+
prompt = self._validate_text_input(prompt, max_length=2000)
|
|
283
|
+
if not 10.0 <= duration <= 600.0:
|
|
284
|
+
raise ValidationError("Duration must be between 10 and 600 seconds")
|
|
285
|
+
|
|
286
|
+
# Prepare request data - Match API schema for lyric2vocals
|
|
287
|
+
data = {
|
|
288
|
+
"prompt": prompt,
|
|
289
|
+
"lyrics": lyrics,
|
|
290
|
+
"audio_duration": duration,
|
|
291
|
+
"guidance_scale": 7.5,
|
|
292
|
+
"infer_step": 50
|
|
293
|
+
}
|
|
294
|
+
if display_name:
|
|
295
|
+
data["display_name"] = display_name.strip()
|
|
296
|
+
|
|
297
|
+
# Make request
|
|
298
|
+
if self.async_mode:
|
|
299
|
+
return self._async_generate_vocals(data, wait_for_completion, timeout)
|
|
300
|
+
else:
|
|
301
|
+
response = self.client.request("POST", "/api/v1/music/lyric2vocals", data=data)
|
|
302
|
+
job_data = response.get("job", response)
|
|
303
|
+
job = Job.from_dict(job_data)
|
|
304
|
+
|
|
305
|
+
if wait_for_completion:
|
|
306
|
+
completed_job = self._wait_for_completion(job.id, timeout)
|
|
307
|
+
return MusicGenerationResult.from_dict(completed_job.result or completed_job.__dict__)
|
|
308
|
+
|
|
309
|
+
return job
|
|
310
|
+
|
|
311
|
+
async def _async_generate_vocals(
|
|
312
|
+
self,
|
|
313
|
+
data: Dict[str, Any],
|
|
314
|
+
wait_for_completion: bool,
|
|
315
|
+
timeout: int
|
|
316
|
+
) -> Union[Job, MusicGenerationResult]:
|
|
317
|
+
"""Async version of generate_vocals"""
|
|
318
|
+
response = await self.client.request("POST", "/api/v1/music/lyric2vocals", data=data)
|
|
319
|
+
job_data = response.get("job", response)
|
|
320
|
+
job = Job.from_dict(job_data)
|
|
233
321
|
|
|
234
322
|
if wait_for_completion:
|
|
235
323
|
completed_job = await self._async_wait_for_completion(job.id, timeout)
|
|
@@ -322,7 +410,7 @@ class MusicService(BaseService):
|
|
|
322
410
|
"""
|
|
323
411
|
params = {
|
|
324
412
|
"limit": limit,
|
|
325
|
-
"skip": offset
|
|
413
|
+
"skip": offset # FIXED: API uses "skip" parameter for offset
|
|
326
414
|
}
|
|
327
415
|
if status:
|
|
328
416
|
params["status"] = status
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Stem Extraction Service - Audio stem separation operations
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional, Dict, Any, Union
|
|
6
|
+
from .base import BaseService
|
|
7
|
+
from ..models import Job
|
|
8
|
+
from ..exceptions import ValidationError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StemExtractionService(BaseService):
|
|
12
|
+
"""Service for audio stem extraction operations"""
|
|
13
|
+
|
|
14
|
+
def extract_stems(
|
|
15
|
+
self,
|
|
16
|
+
audio_file: Optional[str] = None,
|
|
17
|
+
url: Optional[str] = None,
|
|
18
|
+
stem_types: List[str] = None,
|
|
19
|
+
model_name: str = "htdemucs",
|
|
20
|
+
two_stems_mode: Optional[str] = None,
|
|
21
|
+
wait_for_completion: bool = False,
|
|
22
|
+
timeout: int = 900
|
|
23
|
+
) -> Job:
|
|
24
|
+
"""
|
|
25
|
+
Extract stems from audio file
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
audio_file: Path to audio file to process
|
|
29
|
+
url: URL of audio file to process (alternative to audio_file)
|
|
30
|
+
stem_types: List of stems to extract (e.g., ['vocals', 'drums', 'bass', 'other'])
|
|
31
|
+
model_name: Model to use for separation ('htdemucs' or 'htdemucs_6s')
|
|
32
|
+
two_stems_mode: Two-stem mode for vocals/instrumental separation
|
|
33
|
+
wait_for_completion: Whether to wait for completion
|
|
34
|
+
timeout: Maximum time to wait
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Job object with stem extraction details
|
|
38
|
+
"""
|
|
39
|
+
if not audio_file and not url:
|
|
40
|
+
raise ValidationError("Either audio_file or url must be provided")
|
|
41
|
+
|
|
42
|
+
if audio_file and url:
|
|
43
|
+
raise ValidationError("Provide either audio_file or url, not both")
|
|
44
|
+
|
|
45
|
+
# Set default stem types based on model
|
|
46
|
+
if stem_types is None:
|
|
47
|
+
if model_name == "htdemucs_6s":
|
|
48
|
+
stem_types = ["vocals", "drums", "bass", "other", "piano", "guitar"]
|
|
49
|
+
else:
|
|
50
|
+
stem_types = ["vocals", "drums", "bass", "other"]
|
|
51
|
+
|
|
52
|
+
# Validate model name
|
|
53
|
+
if model_name not in ["htdemucs", "htdemucs_6s"]:
|
|
54
|
+
raise ValidationError("Model name must be 'htdemucs' or 'htdemucs_6s'")
|
|
55
|
+
|
|
56
|
+
# Prepare request
|
|
57
|
+
files = {}
|
|
58
|
+
data = {
|
|
59
|
+
"stem_types": str(stem_types), # API expects string representation
|
|
60
|
+
"model_name": model_name
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if audio_file:
|
|
64
|
+
files = self._prepare_file_upload(audio_file, "file")
|
|
65
|
+
|
|
66
|
+
if url:
|
|
67
|
+
data["url"] = url
|
|
68
|
+
|
|
69
|
+
if two_stems_mode:
|
|
70
|
+
data["two_stems_mode"] = two_stems_mode
|
|
71
|
+
|
|
72
|
+
if self.async_mode:
|
|
73
|
+
return self._async_extract_stems(files, data, wait_for_completion, timeout)
|
|
74
|
+
else:
|
|
75
|
+
response = self.client.request(
|
|
76
|
+
"POST",
|
|
77
|
+
"/api/v1/stem-extraction/extract",
|
|
78
|
+
data=data,
|
|
79
|
+
files=files if files else None
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
job = Job.from_dict(response)
|
|
83
|
+
|
|
84
|
+
if wait_for_completion:
|
|
85
|
+
return self._wait_for_completion(job.id, timeout)
|
|
86
|
+
|
|
87
|
+
return job
|
|
88
|
+
|
|
89
|
+
async def _async_extract_stems(
|
|
90
|
+
self,
|
|
91
|
+
files: Dict[str, Any],
|
|
92
|
+
data: Dict[str, Any],
|
|
93
|
+
wait_for_completion: bool,
|
|
94
|
+
timeout: int
|
|
95
|
+
) -> Job:
|
|
96
|
+
"""Async version of extract_stems"""
|
|
97
|
+
response = await self.client.request(
|
|
98
|
+
"POST",
|
|
99
|
+
"/api/v1/stem-extraction/extract",
|
|
100
|
+
data=data,
|
|
101
|
+
files=files if files else None
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
job = Job.from_dict(response)
|
|
105
|
+
|
|
106
|
+
if wait_for_completion:
|
|
107
|
+
return await self._async_wait_for_completion(job.id, timeout)
|
|
108
|
+
|
|
109
|
+
return job
|
|
110
|
+
|
|
111
|
+
def get_stem_job(self, job_id: int) -> Job:
|
|
112
|
+
"""
|
|
113
|
+
Get stem extraction job status
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
job_id: ID of the stem extraction job
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Job object with current status
|
|
120
|
+
"""
|
|
121
|
+
if self.async_mode:
|
|
122
|
+
return self._async_get_stem_job(job_id)
|
|
123
|
+
else:
|
|
124
|
+
response = self.client.request("GET", f"/api/v1/stem-extraction/status/{job_id}")
|
|
125
|
+
return Job.from_dict(response)
|
|
126
|
+
|
|
127
|
+
async def _async_get_stem_job(self, job_id: int) -> Job:
|
|
128
|
+
"""Async version of get_stem_job"""
|
|
129
|
+
response = await self.client.request("GET", f"/api/v1/stem-extraction/status/{job_id}")
|
|
130
|
+
return Job.from_dict(response)
|
|
131
|
+
|
|
132
|
+
def list_stem_jobs(
|
|
133
|
+
self,
|
|
134
|
+
skip: int = 0,
|
|
135
|
+
limit: int = 50
|
|
136
|
+
) -> List[Job]:
|
|
137
|
+
"""
|
|
138
|
+
List stem extraction jobs
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
skip: Number of jobs to skip
|
|
142
|
+
limit: Maximum number of jobs to return
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
List of stem extraction jobs
|
|
146
|
+
"""
|
|
147
|
+
params = {
|
|
148
|
+
"skip": skip,
|
|
149
|
+
"limit": limit
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if self.async_mode:
|
|
153
|
+
return self._async_list_stem_jobs(params)
|
|
154
|
+
else:
|
|
155
|
+
response = self.client.request("GET", "/api/v1/stem-extraction/jobs", params=params)
|
|
156
|
+
return [Job.from_dict(job_data) for job_data in response]
|
|
157
|
+
|
|
158
|
+
async def _async_list_stem_jobs(self, params: Dict[str, Any]) -> List[Job]:
|
|
159
|
+
"""Async version of list_stem_jobs"""
|
|
160
|
+
response = await self.client.request("GET", "/api/v1/stem-extraction/jobs", params=params)
|
|
161
|
+
return [Job.from_dict(job_data) for job_data in response]
|
|
162
|
+
|
|
163
|
+
def delete_stem_job(self, job_id: int) -> Dict[str, str]:
|
|
164
|
+
"""
|
|
165
|
+
Delete a stem extraction job
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
job_id: ID of the job to delete
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Deletion confirmation
|
|
172
|
+
"""
|
|
173
|
+
if self.async_mode:
|
|
174
|
+
return self._async_delete_stem_job(job_id)
|
|
175
|
+
else:
|
|
176
|
+
return self.client.request("DELETE", f"/api/v1/stem-extraction/jobs/{job_id}")
|
|
177
|
+
|
|
178
|
+
async def _async_delete_stem_job(self, job_id: int) -> Dict[str, str]:
|
|
179
|
+
"""Async version of delete_stem_job"""
|
|
180
|
+
return await self.client.request("DELETE", f"/api/v1/stem-extraction/jobs/{job_id}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: audiopod
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Professional Audio Processing API Client for Python
|
|
5
5
|
Home-page: https://github.com/audiopod-ai/audiopod-python
|
|
6
6
|
Author: AudioPod AI
|
|
@@ -25,6 +25,7 @@ Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
|
|
|
25
25
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
26
|
Requires-Python: >=3.8
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
28
29
|
Requires-Dist: requests>=2.28.0
|
|
29
30
|
Requires-Dist: aiohttp>=3.8.0
|
|
30
31
|
Requires-Dist: pydantic>=1.10.0
|
|
@@ -46,6 +47,7 @@ Requires-Dist: sphinx-rtd-theme>=1.2.0; extra == "docs"
|
|
|
46
47
|
Requires-Dist: sphinx-autodoc-typehints>=1.19.0; extra == "docs"
|
|
47
48
|
Dynamic: author
|
|
48
49
|
Dynamic: home-page
|
|
50
|
+
Dynamic: license-file
|
|
49
51
|
Dynamic: requires-python
|
|
50
52
|
|
|
51
53
|
# AudioPod Python SDK
|
|
@@ -380,11 +382,10 @@ audiopod transcription transcribe audio.mp3 --language en
|
|
|
380
382
|
|
|
381
383
|
## Support
|
|
382
384
|
|
|
383
|
-
- 📖 [
|
|
384
|
-
- 🎯 [API Reference](https://api.audiopod.ai/docs)
|
|
385
|
+
- 📖 [API Reference](https://docs.audiopod.ai)
|
|
385
386
|
- 💬 [Discord Community](https://discord.gg/audiopod)
|
|
386
387
|
- 📧 [Email Support](mailto:support@audiopod.ai)
|
|
387
|
-
- 🐛 [Bug Reports](https://github.com/
|
|
388
|
+
- 🐛 [Bug Reports](https://github.com/AudiopodAI/audiopod)
|
|
388
389
|
|
|
389
390
|
## License
|
|
390
391
|
|
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
audiopod/__init__.py,sha256=
|
|
1
|
+
audiopod/__init__.py,sha256=U12jbLmXps3-NP3yXcucGMQbr8b6VCoWAXZSitK1pp4,1790
|
|
2
2
|
audiopod/cli.py,sha256=ZYzAQ3UpoYuOEWivMwMneJUf2z8DGGYTx1Nb6yRfdVY,9339
|
|
3
|
-
audiopod/client.py,sha256=
|
|
3
|
+
audiopod/client.py,sha256=67oPSInSNssJpTR00ZuYSdk9lbx5KiRnDQw8UYKNVsA,11742
|
|
4
4
|
audiopod/config.py,sha256=fuGtbuES4tXdHwqQqoZa5izCH6nVfFRP06D8eK1Cg10,1683
|
|
5
5
|
audiopod/exceptions.py,sha256=c3Ym2tWyRE1kemVkXDaXFcfP3h6AokhKcUcCBImwGes,2386
|
|
6
6
|
audiopod/models.py,sha256=gAfQkufA_hZdYBkniFJ_EXETy9ts-wr-soUEbT7ZKFM,7827
|
|
7
|
-
audiopod/
|
|
7
|
+
audiopod/py.typed,sha256=ixa8YukDZ3kLo0WsFJRGohLMyHzbMur1ALmmASML2cs,64
|
|
8
|
+
audiopod/services/__init__.py,sha256=9Ycl9VVscwwY42joBCSL67v8DrITW2T2QyuaokbpehM,653
|
|
8
9
|
audiopod/services/base.py,sha256=mNbziYy2KsWWZrdHFlTl9pKLvoQUW-ZkkJuVWfCVP74,6731
|
|
9
10
|
audiopod/services/credits.py,sha256=CjE2W8kmYjM4B02BwfPvvB3kl0YdVimM2kR7lhg43h8,1796
|
|
10
11
|
audiopod/services/denoiser.py,sha256=Oi_1rCKs_L5lCG_2QuKwHzLe8_mbEIzlzM2X8TJ7Rnc,1750
|
|
11
12
|
audiopod/services/karaoke.py,sha256=M0Befh4Y2DNM_uWFTmCIrzKfjqkvygrzCt0f_Dubj2o,2012
|
|
12
|
-
audiopod/services/music.py,sha256=
|
|
13
|
+
audiopod/services/music.py,sha256=hDPjTSj-gAeEWBVB7PRPQrptMHJyQTz8e9p-p7yaRPI,20032
|
|
13
14
|
audiopod/services/speaker.py,sha256=OPSOwArfrGXVzRgciS13n1QsCJSK1PB-Mz6VgwxuHAA,1866
|
|
15
|
+
audiopod/services/stem_extraction.py,sha256=3ibMFKFR25xKHpVs3WGMNriZ88sB5PriFNa_s2Bvon4,6026
|
|
14
16
|
audiopod/services/transcription.py,sha256=HyH6WpGWZsggYxIvt2dhB6_5UHaigk3XwXsVgarWzcE,7565
|
|
15
17
|
audiopod/services/translation.py,sha256=Gpxmom-ZSLMXBwSQlOL5PyqxQCwRYNT2IUp2ZD5QhYc,3177
|
|
16
18
|
audiopod/services/voice.py,sha256=_IHv3zU3k184kfijxr1QRBenrIpmhhPOBS96DddZ8yw,13456
|
|
17
|
-
audiopod-1.
|
|
18
|
-
audiopod-1.
|
|
19
|
-
audiopod-1.
|
|
20
|
-
audiopod-1.
|
|
21
|
-
audiopod-1.
|
|
19
|
+
audiopod-1.1.0.dist-info/licenses/LICENSE,sha256=hqEjnOaGNbnLSBxbtbC7WQVREU2vQI8FmwecCiZlMfA,1068
|
|
20
|
+
audiopod-1.1.0.dist-info/METADATA,sha256=ee2Zg4iwkglAgnk3xwNuYg11LFZbKJQeUcxgG8Z_Dw0,10931
|
|
21
|
+
audiopod-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
22
|
+
audiopod-1.1.0.dist-info/entry_points.txt,sha256=uLcNDzXuOXnJAz9j91TDGayVjjZ7-ZiHBGDydqNUErU,47
|
|
23
|
+
audiopod-1.1.0.dist-info/top_level.txt,sha256=M6yyOFFNpLdH4i1AMRqJZLRIgfpg1NvrQVmnPd8A6N8,9
|
|
24
|
+
audiopod-1.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 AudioPod AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|