mirror of
https://github.com/calesthio/OpenMontage.git
synced 2026-08-15 05:04:42 +08:00
fix: refresh Fish Audio promotion and schema
This commit is contained in:
@@ -26,11 +26,11 @@ The backend model is chosen with the `model` **HTTP header**, not a body field.
|
||||
`model` is **required — there is no default**. Pass one of:
|
||||
|
||||
- `s2.1-pro` — latest generation. Best quality: inline emotion tags, 80+ languages, multi-speaker. Hero narration.
|
||||
- `s2.1-pro-free` — **promotional** free access to s2.1-pro. Drafts, samples, and validation runs at $0 during the promo window only. Per the [fish.audio announcement](https://fish.audio/ar/blog/s2-1-pro-free-api/?articleLocale=en): free through end of July 2026, subject to Fair Use, no SLA/latency guarantee, requests may be retained, and commercial use is restricted. Never route production or client narration through it.
|
||||
- `s2.1-pro-free` — **promotional** free access to s2.1-pro. Drafts, samples, and validation runs at $0 during the promo window only. Per the [fish.audio announcement](https://fish.audio/ko/blog/s2-1-pro-free-api/?articleLocale=en): free through August 31, 2026, subject to Fair Use, no SLA/latency guarantee, requests may be retained, and commercial use is restricted. Never route production or client narration through it.
|
||||
- `s2-pro` — first S2 generation. Stable high quality with emotion-tag support.
|
||||
- `s1` — previous flagship. Kept for compatibility with existing integrations.
|
||||
|
||||
Billing is **per UTF-8 byte of input text** (not per character). CJK text and emoji cost 3-4x an ASCII character of the same visible length. Approximate: `s1` / `s2-pro` / `s2.1-pro` ≈ $15 per 1M bytes, `s2.1-pro-free` = $0 during the promo window only (the tool's `estimate_cost()` switches to the paid `s2.1-pro` rate after end of July 2026). Verify current pricing at https://fish.audio before large batches.
|
||||
Billing is **per UTF-8 byte of input text** (not per character). CJK text and emoji cost 3-4x an ASCII character of the same visible length. Current list pricing: `s1` / `s2-pro` / `s2.1-pro` = $15 per 1M bytes, `s2.1-pro-free` = $0 during the promo window only (the tool's `estimate_cost()` switches to the paid `s2.1-pro` rate after August 31, 2026). Verify current pricing at https://docs.fish.audio/developer-guide/models-pricing/pricing-and-rate-limits before large batches.
|
||||
|
||||
## Inline emotion tags (S2 models only)
|
||||
|
||||
|
||||
@@ -323,13 +323,13 @@ No subscription — pure pay-as-you-go, no minimum spend.
|
||||
| `s2-pro` | First S2 generation — stable high quality with emotion-tag support |
|
||||
| `s1` | Previous flagship, kept for compatibility (no emotion tags) |
|
||||
|
||||
**`s2.1-pro-free` caveats — promotional, not a durable free tier.** Per the [fish.audio announcement](https://fish.audio/ar/blog/s2-1-pro-free-api/?articleLocale=en), free API access runs **through the end of July 2026** and is subject to Fair Use limits, carries **no SLA or latency guarantee**, requests **may be retained** by fish.audio, and **commercial use is restricted**. Don't route client work or production narration through it, and don't plan long-term costs at $0 — `fish_audio_tts.estimate_cost()` falls back to the paid `s2.1-pro` rate after the promotional window ends.
|
||||
**`s2.1-pro-free` caveats — promotional, not a durable free tier.** Per the [fish.audio announcement](https://fish.audio/ko/blog/s2-1-pro-free-api/?articleLocale=en), free API access runs **through August 31, 2026** and is subject to Fair Use limits, carries **no SLA or latency guarantee**, requests **may be retained** by fish.audio, and **commercial use is restricted**. Don't route client work or production narration through it, and don't plan long-term costs at $0 — `fish_audio_tts.estimate_cost()` falls back to the paid `s2.1-pro` rate after the promotional window ends.
|
||||
|
||||
The legacy `speech-1.x` tier and `s1-mini` have been removed from the fish.audio API and are not supported.
|
||||
|
||||
#### Pricing
|
||||
|
||||
Billing is **per UTF-8 byte of input text** (not per character) — CJK text and emoji cost 3-4x an ASCII character of the same visible length. Approximate: `s1` / `s2-pro` / `s2.1-pro` ≈ $15 per 1M bytes; `s2.1-pro-free` is $0 only during the promotional window (through end of July 2026 — see caveats above). Verify current pricing at [fish.audio](https://fish.audio) before large batches.
|
||||
Billing is **per UTF-8 byte of input text** (not per character) — CJK text and emoji cost 3-4x an ASCII character of the same visible length. Current list pricing: `s1` / `s2-pro` / `s2.1-pro` = $15 per 1M bytes; `s2.1-pro-free` is $0 only during the promotional window (through August 31, 2026 — see caveats above). Verify current pricing in the [official pricing guide](https://docs.fish.audio/developer-guide/models-pricing/pricing-and-rate-limits) before large batches.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -80,9 +80,13 @@ class TestModelContract:
|
||||
assert result.success is False
|
||||
assert "Unknown fish.audio model" in result.error
|
||||
|
||||
def test_schema_declares_model_required(self):
|
||||
def test_schema_requires_model_or_selector_alias(self):
|
||||
schema = FishAudioTTS.input_schema
|
||||
assert "model" in schema["required"]
|
||||
assert schema["required"] == ["text"]
|
||||
assert {tuple(option["required"]) for option in schema["anyOf"]} == {
|
||||
("model",),
|
||||
("model_id",),
|
||||
}
|
||||
assert "model_id" in schema["properties"]
|
||||
|
||||
def test_model_id_alias_accepted(self, api_key, tmp_path):
|
||||
@@ -252,12 +256,12 @@ class TestCost:
|
||||
|
||||
def test_s2_1_pro_free_costs_zero_during_promo_window(self):
|
||||
tool = FishAudioTTS()
|
||||
with patch.object(FishAudioTTS, "_today", return_value=date(2026, 7, 1)):
|
||||
with patch.object(FishAudioTTS, "_today", return_value=date(2026, 8, 31)):
|
||||
assert tool.estimate_cost({"text": "same text here", "model": "s2.1-pro-free"}) == 0.0
|
||||
|
||||
def test_s2_1_pro_free_charged_at_paid_rate_after_promo_window(self):
|
||||
tool = FishAudioTTS()
|
||||
with patch.object(FishAudioTTS, "_today", return_value=date(2026, 8, 1)):
|
||||
with patch.object(FishAudioTTS, "_today", return_value=date(2026, 9, 1)):
|
||||
free_after = tool.estimate_cost({"text": "same text here", "model": "s2.1-pro-free"})
|
||||
paid = tool.estimate_cost({"text": "same text here", "model": "s2.1-pro"})
|
||||
assert free_after == paid
|
||||
|
||||
@@ -77,7 +77,11 @@ class FishAudioTTS(BaseTool):
|
||||
|
||||
input_schema = {
|
||||
"type": "object",
|
||||
"required": ["text", "model"],
|
||||
"required": ["text"],
|
||||
"anyOf": [
|
||||
{"required": ["model"]},
|
||||
{"required": ["model_id"]},
|
||||
],
|
||||
"properties": {
|
||||
"text": {"type": "string", "description": "Text to convert to speech"},
|
||||
"model": {
|
||||
@@ -229,11 +233,11 @@ class FishAudioTTS(BaseTool):
|
||||
_DEFAULT_RATE = 0.000015
|
||||
|
||||
# s2.1-pro-free is a promotion, not a durable free tier: free API access runs
|
||||
# through the end of July 2026, subject to Fair Use, with no SLA/latency
|
||||
# through August 31, 2026, subject to Fair Use, with no SLA/latency
|
||||
# guarantee, possible request retention, and commercial-use restrictions
|
||||
# (https://fish.audio/ar/blog/s2-1-pro-free-api/?articleLocale=en). After the
|
||||
# window, cost planning falls back to the paid s2.1-pro rate.
|
||||
_S21_PRO_FREE_PROMO_END = date(2026, 7, 31)
|
||||
_S21_PRO_FREE_PROMO_END = date(2026, 8, 31)
|
||||
|
||||
# Effective API defaults for output-affecting inputs. Applied when computing
|
||||
# the idempotency key so an omitted field and its explicit default hash the
|
||||
|
||||
Reference in New Issue
Block a user