| """
|
| Request models for VoiceAuth API.
|
|
|
| Defines Pydantic models for API request validation.
|
| """
|
|
|
| import base64
|
| import re
|
| from typing import Annotated
|
|
|
| from pydantic import BaseModel
|
| from pydantic import ConfigDict
|
| from pydantic import Field
|
| from pydantic import field_validator
|
|
|
| from app.models.enums import AudioFormat
|
| from app.models.enums import SupportedLanguage
|
|
|
|
|
| class VoiceDetectionRequest(BaseModel):
|
| """
|
| Request model for voice detection endpoint.
|
|
|
| Accepts Base64-encoded MP3 audio in one of 5 supported languages.
|
| """
|
|
|
| model_config = ConfigDict(
|
| json_schema_extra={
|
| "example": {
|
| "language": "Tamil",
|
| "audioFormat": "mp3",
|
| "audioBase64": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjM2LjEwMAAAAAAA...",
|
| }
|
| }
|
| )
|
|
|
| language: Annotated[
|
| SupportedLanguage,
|
| Field(
|
| description="Language of the audio content. Must be one of: Tamil, English, Hindi, Malayalam, Telugu"
|
| ),
|
| ]
|
|
|
| audioFormat: Annotated[
|
| AudioFormat,
|
| Field(
|
| default=AudioFormat.MP3,
|
| description="Format of the audio file. Currently only 'mp3' is supported",
|
| ),
|
| ] = AudioFormat.MP3
|
|
|
| audioBase64: Annotated[
|
| str,
|
| Field(
|
| min_length=100,
|
| description="Base64-encoded MP3 audio data. Minimum 100 characters for valid audio",
|
| ),
|
| ]
|
|
|
| @field_validator("audioBase64")
|
| @classmethod
|
| def validate_base64(cls, v: str) -> str:
|
| """
|
| Validate that the string is valid Base64.
|
|
|
| Args:
|
| v: The base64 string to validate
|
|
|
| Returns:
|
| The validated base64 string
|
|
|
| Raises:
|
| ValueError: If the string is not valid base64
|
| """
|
|
|
| v = v.strip()
|
|
|
|
|
| base64_pattern = re.compile(r"^[A-Za-z0-9+/]*={0,2}$")
|
| if not base64_pattern.match(v):
|
| raise ValueError("Invalid Base64 encoding: contains invalid characters")
|
|
|
|
|
| try:
|
|
|
| padding = 4 - len(v) % 4
|
| if padding != 4:
|
| v += "=" * padding
|
|
|
| decoded = base64.b64decode(v)
|
| if len(decoded) < 100:
|
| raise ValueError("Decoded audio data is too small to be a valid MP3 file")
|
|
|
| except Exception as e:
|
| if "Invalid Base64" in str(e) or "too small" in str(e):
|
| raise
|
| raise ValueError(f"Invalid Base64 encoding: {e}") from e
|
|
|
| return v.rstrip("=") + "=" * (4 - len(v.rstrip("=")) % 4) if len(v.rstrip("=")) % 4 else v
|
|
|