runapi-fish-audio 0.1.0__tar.gz
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.
- runapi_fish_audio-0.1.0/PKG-INFO +24 -0
- runapi_fish_audio-0.1.0/README.md +7 -0
- runapi_fish_audio-0.1.0/pyproject.toml +34 -0
- runapi_fish_audio-0.1.0/src/runapi/fish_audio/__init__.py +20 -0
- runapi_fish_audio-0.1.0/src/runapi/fish_audio/client.py +19 -0
- runapi_fish_audio-0.1.0/src/runapi/fish_audio/contract_gen.py +17 -0
- runapi_fish_audio-0.1.0/src/runapi/fish_audio/py.typed +1 -0
- runapi_fish_audio-0.1.0/src/runapi/fish_audio/resources/__init__.py +3 -0
- runapi_fish_audio-0.1.0/src/runapi/fish_audio/resources/text_to_speech.py +22 -0
- runapi_fish_audio-0.1.0/src/runapi/fish_audio/types.py +21 -0
- runapi_fish_audio-0.1.0/tests/test_client.py +39 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: runapi-fish-audio
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: RunAPI Fish Audio SDK for speech generation in JavaScript, Python, Ruby, Go, Java, and PHP
|
|
5
|
+
Project-URL: Homepage, https://runapi.ai/models/fish-audio
|
|
6
|
+
Project-URL: Documentation, https://runapi.ai/docs#sdk-fish-audio
|
|
7
|
+
Project-URL: Source, https://github.com/runapi-ai/fish-audio-sdk
|
|
8
|
+
Project-URL: Issues, https://github.com/runapi-ai/fish-audio-sdk/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/runapi-ai/fish-audio-sdk/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Release Notes, https://github.com/runapi-ai/fish-audio-sdk/releases/tag/python%2Fv0.1.0
|
|
11
|
+
Author-email: RunAPI <contact@runapi.ai>
|
|
12
|
+
License-Expression: Apache-2.0
|
|
13
|
+
Keywords: api,audio,fish-audio,golang,java,maven,python,ruby,runapi,runapi-ai,sdk,speech,tts,typescript
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Requires-Dist: runapi-core>=0.2.0
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# Fish Audio Python SDK for RunAPI
|
|
19
|
+
|
|
20
|
+
Install `runapi-fish-audio`, create `FishAudioClient`, and call `client.text_to_speech.run(model="s1", text="Hello")`.
|
|
21
|
+
|
|
22
|
+
Model details and pricing: https://runapi.ai/models/fish-audio
|
|
23
|
+
|
|
24
|
+
Licensed under the Apache License, Version 2.0.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Fish Audio Python SDK for RunAPI
|
|
2
|
+
|
|
3
|
+
Install `runapi-fish-audio`, create `FishAudioClient`, and call `client.text_to_speech.run(model="s1", text="Hello")`.
|
|
4
|
+
|
|
5
|
+
Model details and pricing: https://runapi.ai/models/fish-audio
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "runapi-fish-audio"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "RunAPI Fish Audio SDK for speech generation in JavaScript, Python, Ruby, Go, Java, and PHP"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
authors = [{ name = "RunAPI", email = "contact@runapi.ai" }]
|
|
13
|
+
keywords = ["runapi", "runapi-ai", "fish-audio", "tts", "speech", "audio", "api", "sdk", "typescript", "python", "ruby", "golang", "java", "maven"]
|
|
14
|
+
dependencies = ["runapi-core>=0.2.0"]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://runapi.ai/models/fish-audio"
|
|
18
|
+
Documentation = "https://runapi.ai/docs#sdk-fish-audio"
|
|
19
|
+
Source = "https://github.com/runapi-ai/fish-audio-sdk"
|
|
20
|
+
Issues = "https://github.com/runapi-ai/fish-audio-sdk/issues"
|
|
21
|
+
Changelog = "https://github.com/runapi-ai/fish-audio-sdk/blob/main/CHANGELOG.md"
|
|
22
|
+
"Release Notes" = "https://github.com/runapi-ai/fish-audio-sdk/releases/tag/python%2Fv0.1.0"
|
|
23
|
+
|
|
24
|
+
[tool.hatch.build.targets.wheel]
|
|
25
|
+
packages = ["src/runapi"]
|
|
26
|
+
|
|
27
|
+
[tool.uv]
|
|
28
|
+
package = true
|
|
29
|
+
|
|
30
|
+
[dependency-groups]
|
|
31
|
+
dev = ["pytest>=8"]
|
|
32
|
+
|
|
33
|
+
[tool.runapi]
|
|
34
|
+
slug = "fish-audio"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Fish Audio client for RunAPI."""
|
|
2
|
+
|
|
3
|
+
from runapi.core import (
|
|
4
|
+
AuthenticationError,
|
|
5
|
+
InsufficientCreditsError,
|
|
6
|
+
NotFoundError,
|
|
7
|
+
RateLimitError,
|
|
8
|
+
ValidationError,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from .client import FishAudioClient
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"FishAudioClient",
|
|
15
|
+
"AuthenticationError",
|
|
16
|
+
"RateLimitError",
|
|
17
|
+
"InsufficientCreditsError",
|
|
18
|
+
"NotFoundError",
|
|
19
|
+
"ValidationError",
|
|
20
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Fish Audio client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
from runapi.core import ClientOptions, HttpClient, resolve_api_key
|
|
8
|
+
|
|
9
|
+
from .resources.text_to_speech import TextToSpeech
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FishAudioClient:
|
|
13
|
+
"""Fish Audio speech generation client."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, api_key: Optional[str] = None, **options: Any) -> None:
|
|
16
|
+
resolved_api_key = resolve_api_key(api_key)
|
|
17
|
+
client_options = ClientOptions(api_key=resolved_api_key, **options)
|
|
18
|
+
http = client_options.http_client or HttpClient(client_options)
|
|
19
|
+
self.text_to_speech = TextToSpeech(http)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Fish Audio text-to-speech resource."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
from runapi.core import RequestOptions, Resource
|
|
8
|
+
|
|
9
|
+
from ..contract_gen import CONTRACT
|
|
10
|
+
from ..types import TextToSpeechResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TextToSpeech(Resource):
|
|
14
|
+
"""Generate a RunAPI-managed MP3 from text."""
|
|
15
|
+
|
|
16
|
+
ENDPOINT = "/api/v1/fish_audio/text_to_speech"
|
|
17
|
+
RESPONSE_CLASS = TextToSpeechResponse
|
|
18
|
+
|
|
19
|
+
def run(self, options: Optional[RequestOptions] = None, **params: Any) -> Any:
|
|
20
|
+
compacted = self._compact_params(params)
|
|
21
|
+
self._validate_contract(CONTRACT["text-to-speech"], compacted)
|
|
22
|
+
return self._request("post", self.ENDPOINT, body=compacted, options=options)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Fish Audio response models."""
|
|
2
|
+
|
|
3
|
+
from runapi.core import BaseModel, optional, required
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Audio(BaseModel):
|
|
7
|
+
"""A RunAPI-managed MP3 audio result."""
|
|
8
|
+
|
|
9
|
+
url = required(str)
|
|
10
|
+
format = required(str)
|
|
11
|
+
mime_type = required(str)
|
|
12
|
+
size_bytes = required(int)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TextToSpeechResponse(BaseModel):
|
|
16
|
+
"""Completed synchronous text-to-speech response."""
|
|
17
|
+
|
|
18
|
+
id = required(str)
|
|
19
|
+
status = required(str)
|
|
20
|
+
audios = required([lambda: Audio])
|
|
21
|
+
error = optional(str)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from runapi.core import config
|
|
4
|
+
from runapi.core.errors import ValidationError
|
|
5
|
+
from runapi.fish_audio import FishAudioClient
|
|
6
|
+
from runapi.fish_audio.types import TextToSpeechResponse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FakeHttp:
|
|
10
|
+
def __init__(self, *responses):
|
|
11
|
+
self._responses = list(responses)
|
|
12
|
+
self.calls = []
|
|
13
|
+
|
|
14
|
+
def request(self, method, path, body=None, options=None):
|
|
15
|
+
self.calls.append((method, path, body))
|
|
16
|
+
return self._responses.pop(0)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.fixture(autouse=True)
|
|
20
|
+
def reset_config(monkeypatch):
|
|
21
|
+
monkeypatch.delenv("RUNAPI_API_KEY", raising=False)
|
|
22
|
+
monkeypatch.setattr(config, "api_key", None)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_run_posts_params_and_decodes_managed_audio():
|
|
26
|
+
fake = FakeHttp({"id": "task_1", "status": "completed", "audios": [{"url": "https://runapi.ai/audio.mp3", "format": "mp3", "mime_type": "audio/mpeg", "size_bytes": 128}]})
|
|
27
|
+
client = FishAudioClient(api_key="k", http_client=fake)
|
|
28
|
+
|
|
29
|
+
result = client.text_to_speech.run(model="s1", text="Hello")
|
|
30
|
+
|
|
31
|
+
assert fake.calls == [("post", "/api/v1/fish_audio/text_to_speech", {"model": "s1", "text": "Hello"})]
|
|
32
|
+
assert isinstance(result, TextToSpeechResponse)
|
|
33
|
+
assert result.audios[0].format == "mp3"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_run_requires_text():
|
|
37
|
+
client = FishAudioClient(api_key="k", http_client=FakeHttp())
|
|
38
|
+
with pytest.raises(ValidationError, match="text is required"):
|
|
39
|
+
client.text_to_speech.run(model="s1")
|