Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# API Settings
API_TITLE="Kokoro TTS API"
API_DESCRIPTION="API for text-to-speech generation using Kokoro"
API_VERSION="1.0.0"
HOST="0.0.0.0"
PORT=8880

# Authentication Settings
ENABLE_AUTH=False # Set to True to enable API key authentication
API_KEYS=["sk-kokoro-1234567890abcdef", "sk-kokoro-0987654321fedcba"] # List of valid API keys

# Application Settings
OUTPUT_DIR="output"
OUTPUT_DIR_SIZE_LIMIT_MB=500.0
DEFAULT_VOICE="af_heart"
# DEFAULT_VOICE_CODE can be set to a language code like "a" for American English, "j" for Japanese, etc.
# Valid codes: a (American English), b (British English), e (Spanish), f (French), h (Hindi),
# i (Italian), p (Portuguese), j (Japanese), z (Mandarin Chinese)
# Set to null or leave commented out to use the first letter of the voice name
DEFAULT_VOICE_CODE="a"

USE_GPU=True
ALLOW_LOCAL_VOICE_SAVING=False

# Audio Settings
SAMPLE_RATE=24000

# Web Player Settings
ENABLE_WEB_PLAYER=True
WEB_PLAYER_PATH="web"
CORS_ORIGINS=["*"]
CORS_ENABLED=True

# Temp File Settings
TEMP_FILE_DIR="api/temp_files"
MAX_TEMP_DIR_SIZE_MB=2048
MAX_TEMP_DIR_AGE_HOURS=1
MAX_TEMP_DIR_COUNT=3
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,47 @@ with client.audio.speech.with_streaming_response.create(
<img src="assets/webui-screenshot.png" width="42%" alt="Web UI Screenshot" style="border: 2px solid #333; padding: 10px;">
</div>

<details>
<summary>API Authentication</summary>

The API supports OpenAI-compatible API key authentication. This feature is disabled by default but can be enabled through environment variables.

To enable authentication:

1. Create a `.env` file in the project root (or copy from `.env.example`)
2. Set the following variables:
```
ENABLE_AUTH=True
API_KEYS=["sk-kokoro-your-api-key-1", "sk-kokoro-your-api-key-2"]
```

When authentication is enabled, all OpenAI-compatible endpoints will require an API key to be provided in the `Authorization` header. The API supports both `Bearer sk-kokoro-xxx` and `sk-kokoro-xxx` formats.

Example usage with authentication:
```bash
# Using curl
curl -X POST "http://localhost:8880/v1/audio/speech" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-kokoro-your-api-key-1" \
-d '{"model":"kokoro", "input":"Hello world", "voice":"af_heart"}'

# Using Python with OpenAI client
from openai import OpenAI

client = OpenAI(
api_key="sk-kokoro-your-api-key",
base_url="http://localhost:8880/v1"
)

response = client.audio.speech.create(
model="kokoro",
voice="af_heart",
input="Hello world"
)
```

</details>

</details>


Expand Down
88 changes: 0 additions & 88 deletions Test copy.py

This file was deleted.

60 changes: 60 additions & 0 deletions api/src/core/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Authentication utilities for the API"""

from fastapi import Depends, HTTPException, Header, status
from fastapi.security import APIKeyHeader
from typing import Optional

from .config import settings

# Define API key header
api_key_header = APIKeyHeader(name="Authorization", auto_error=False)


async def verify_api_key(
authorization: Optional[str] = Depends(api_key_header),
) -> Optional[str]:
"""
Verify the API key from the Authorization header.

Args:
authorization: The Authorization header value

Returns:
The API key if valid

Raises:
HTTPException: If authentication is enabled and the API key is invalid
"""
# If authentication is disabled, allow all requests
if not settings.enable_auth:
return None

# Check if Authorization header is present
if not authorization:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={
"error": "authentication_error",
"message": "API key is required",
"type": "unauthorized",
},
)

# Extract the API key from the Authorization header
# Support both "Bearer sk-xxx" and "sk-xxx" formats
api_key = authorization
if authorization.lower().startswith("bearer "):
api_key = authorization[7:].strip()

# Check if the API key is valid
if not settings.api_keys or api_key not in settings.api_keys:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={
"error": "authentication_error",
"message": "Invalid API key",
"type": "unauthorized",
},
)

return api_key
Loading