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.
- audiopod/__init__.py +13 -8
- audiopod/client.py +125 -233
- audiopod/exceptions.py +27 -19
- audiopod/resources/__init__.py +23 -0
- audiopod/resources/denoiser.py +116 -0
- audiopod/resources/music.py +166 -0
- audiopod/resources/speaker.py +132 -0
- audiopod/resources/stems.py +267 -0
- audiopod/resources/transcription.py +205 -0
- audiopod/resources/voice.py +139 -0
- audiopod/resources/wallet.py +110 -0
- audiopod-2.1.0.dist-info/METADATA +205 -0
- audiopod-2.1.0.dist-info/RECORD +16 -0
- {audiopod-1.4.0.dist-info → audiopod-2.1.0.dist-info}/WHEEL +1 -1
- audiopod/config.py +0 -17
- audiopod/services/__init__.py +0 -28
- audiopod/services/base.py +0 -69
- audiopod/services/credits.py +0 -42
- audiopod/services/denoiser.py +0 -131
- audiopod/services/music.py +0 -217
- audiopod/services/speaker.py +0 -134
- audiopod/services/stem_extraction.py +0 -168
- audiopod/services/transcription.py +0 -187
- audiopod/services/translation.py +0 -135
- audiopod/services/voice.py +0 -187
- audiopod/services/wallet.py +0 -235
- audiopod-1.4.0.dist-info/METADATA +0 -206
- audiopod-1.4.0.dist-info/RECORD +0 -20
- {audiopod-1.4.0.dist-info → audiopod-2.1.0.dist-info}/licenses/LICENSE +0 -0
- {audiopod-1.4.0.dist-info → audiopod-2.1.0.dist-info}/top_level.txt +0 -0
audiopod/services/__init__.py
DELETED
|
@@ -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
|
-
|
audiopod/services/credits.py
DELETED
|
@@ -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
|
-
|
audiopod/services/denoiser.py
DELETED
|
@@ -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
|
-
|
audiopod/services/music.py
DELETED
|
@@ -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
|
-
|
audiopod/services/speaker.py
DELETED
|
@@ -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
|
-
|