Skip to content

Commit e1d8a29

Browse files
SilkWebclaude
andcommitted
Add ElevenLabs TTS proxy and update agent voices
- TTS proxy at /api/v1/tts/{voice_id} — keeps API key server-side - Elizabeth, Clara, and Titan voices assigned to 20 agents - Agent pages use ElevenLabs with Web Speech API fallback Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 13667f7 commit e1d8a29

25 files changed

Lines changed: 10674 additions & 1 deletion

api/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ class Settings(BaseSettings):
2828
api_key_prefix: str = "sw_live_"
2929
api_key_test_prefix: str = "sw_test_"
3030

31+
# ElevenLabs TTS
32+
elevenlabs_api_key: str = Field(
33+
default="",
34+
description="ElevenLabs API key for text-to-speech",
35+
)
36+
3137
# OAuth
3238
google_client_id: str = Field(
3339
default="",

api/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from api.config import settings
2222
from api.middleware.rate_limit import RateLimitMiddleware
2323
from api.middleware.security import SecurityHeadersMiddleware
24-
from api.routers import agents, agents_proxy, auth, discovery, health, receipts, tasks
24+
from api.routers import agents, agents_proxy, auth, discovery, health, receipts, tasks, tts
2525

2626
# Logging
2727
logging.basicConfig(
@@ -95,6 +95,7 @@ def create_app() -> FastAPI:
9595
app.include_router(tasks.router)
9696
app.include_router(receipts.router)
9797
app.include_router(agents_proxy.router)
98+
app.include_router(tts.router)
9899

99100
return app
100101

api/routers/tts.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""Text-to-Speech proxy — forwards requests to ElevenLabs with server-side API key."""
2+
3+
import httpx
4+
from fastapi import APIRouter, Request, Response
5+
6+
from api.config import settings
7+
8+
router = APIRouter()
9+
10+
ELEVENLABS_API = "https://api.elevenlabs.io/v1/text-to-speech"
11+
12+
13+
@router.post("/api/v1/tts/{voice_id}")
14+
async def tts_proxy(voice_id: str, request: Request):
15+
"""Proxy TTS requests to ElevenLabs without exposing the API key."""
16+
api_key = getattr(settings, "elevenlabs_api_key", None)
17+
if not api_key:
18+
return Response(content="TTS not configured", status_code=503)
19+
20+
body = await request.body()
21+
22+
async with httpx.AsyncClient(timeout=30.0) as client:
23+
try:
24+
resp = await client.post(
25+
f"{ELEVENLABS_API}/{voice_id}",
26+
content=body,
27+
headers={
28+
"Content-Type": "application/json",
29+
"xi-api-key": api_key,
30+
"Accept": "audio/mpeg",
31+
},
32+
)
33+
return Response(
34+
content=resp.content,
35+
status_code=resp.status_code,
36+
media_type="audio/mpeg",
37+
headers={
38+
"Access-Control-Allow-Origin": "*",
39+
"Cache-Control": "public, max-age=86400",
40+
},
41+
)
42+
except Exception:
43+
return Response(content="TTS request failed", status_code=502)

silkweb-landing/agents/_generate.js

Lines changed: 735 additions & 0 deletions
Large diffs are not rendered by default.

silkweb-landing/agents/advocate.html

Lines changed: 487 additions & 0 deletions
Large diffs are not rendered by default.

silkweb-landing/agents/anvil.html

Lines changed: 487 additions & 0 deletions
Large diffs are not rendered by default.

silkweb-landing/agents/atlas.html

Lines changed: 488 additions & 0 deletions
Large diffs are not rendered by default.

silkweb-landing/agents/bazaar.html

Lines changed: 487 additions & 0 deletions
Large diffs are not rendered by default.

silkweb-landing/agents/builder.html

Lines changed: 487 additions & 0 deletions
Large diffs are not rendered by default.

silkweb-landing/agents/canvas-agent.html

Lines changed: 487 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)