Skip to content
Back to skills

082 Claude 2615c082

ASecurity

Speech-to-text (STT) provider implementations for audio transcription.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 31, 2026
developmentpythongoazureapidocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 082-claude_2615c082 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 082 Claude 2615c082?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 082 Claude 2615c082
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-082-claude-2615c082/badge)](https://www.skillsdirectory.com/skills/tools-only-082-claude-2615c082)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Speech-to-Text Providers

Speech-to-text (STT) provider implementations for audio transcription.

## Files

- **`base.py`**: Abstract base class `SpeechToTextModel` defining the interface
- **`openai.py`**: OpenAI Whisper API
- **`groq.py`**: Groq Whisper inference
- **`google.py`**: Google Cloud Speech-to-Text
- **`azure.py`**: Azure Speech Service
- **`elevenlabs.py`**: ElevenLabs speech recognition
- **`openai_compatible.py`**: Generic OpenAI-compatible STT API

## Patterns

### Base Class Contract

All providers inherit from `SpeechToTextModel` (base.py:14) and must:

1. **Implement abstract methods**:
   - `transcribe()`: Synchronous transcription
   - `atranscribe()`: Async transcription
   - `_get_models()`: Return list of available models
   - `_get_default_model()`: Return default model name
   - `provider` property: Return provider name string

2. **Override `__post_init__()`**:
   - Call `super().__post_init__()` first
   - Set `api_key` from parameter or environment variable
   - Set `base_url` (if applicable)
   - Call `self._create_http_clients()` last

3. **Return standardized response**:
   - Use `TranscriptionResponse` from `esperanto.common_types`
   - Contains `text`, optional `language`, `duration`, and provider-specific metadata

### Audio File Handling

`transcribe()` accepts two input types (base.py:53):

1. **File path** (str): Read file from disk
2. **File-like object** (BinaryIO): Read from memory/stream

Handle both cases:

```python
def transcribe(self, audio_file: Union[str, BinaryIO], ...):
    if isinstance(audio_file, str):
        with open(audio_file, "rb") as f:
            audio_data = f.read()
    else:
        audio_data = audio_file.read()
    # Process audio_data...
```

For APIs that expect files, create multipart form data:

```python
files = {
    "file": ("audio.mp3", audio_data, "audio/mpeg")
}
```

### Language Support

Language parameter is optional (base.py:56):

- If provided: Use it to help model (improves accuracy)
- If None: Model auto-detects language
- Format: ISO 639-1 codes (e.g., "en", "es", "fr")

Some providers (Google) use different language codes - map them:

```python
# Google uses BCP-47 (e.g., "en-US")
if language:
    language_code = f"{language}-US"  # or appropriate mapping
```

### Prompt/Context

Optional `prompt` parameter (base.py:57) provides context:

- Helps model understand domain-specific terms
- Improves accuracy for technical/specialized content
- Not all providers support this (check before using)

### HTTP Client Pattern

Same as other providers:

```python
def __post_init__(self):
    super().__post_init__()
    self.api_key = self.api_key or os.getenv("PROVIDER_API_KEY")
    self.base_url = self.base_url or "https://api.provider.com/v1"
    self._create_http_clients()
```

### Response Construction

Build `TranscriptionResponse` from API results:

```python
from esperanto.common_types import TranscriptionResponse

return TranscriptionResponse(
    text=api_response["text"],
    language=api_response.get("language"),  # if available
    duration=audio_duration,  # if available
    segments=segments,  # if available (timestamped segments)
    words=words,  # if available (word-level timestamps)
)
```

## Integration

- Imported by `factory.py` via `AIFactory._provider_modules["speech_to_text"]`
- Uses `TranscriptionResponse` from `esperanto.common_types.stt`
- Inherits mixins from `esperanto.utils.timeout` and `esperanto.utils.ssl`

## Gotchas

- **File format support**: Check provider docs for supported audio formats (WAV, MP3, FLAC, etc.)
- **File size limits**: APIs have max file size (often 25MB) - check and chunk if needed
- **Audio duration limits**: Some providers limit duration (e.g., 30 minutes)
- **Multipart encoding**: When uploading files, use correct MIME type
- **File pointer position**: If using BinaryIO, reset pointer with `seek(0)` if needed
- **Language code formats**: Different providers use different formats (ISO 639-1 vs BCP-47)
- **Model availability**: Not all models support all languages
- **Timeout configuration**: Transcription can be slow - use longer timeouts via mixin
- **Prompt ignored**: Some providers don't support prompt parameter - handle gracefully
- **Deprecation warnings**: Use `_get_models()` internally (not `.models` property)
- **Response formats**: Some APIs support SRT, VTT, JSON with timestamps - handle appropriately

## When Adding a New Provider

1. Create new file `provider_name.py`
2. Import `SpeechToTextModel` from `esperanto.providers.stt.base`
3. Import `TranscriptionResponse` from `esperanto.common_types`
4. Define class inheriting from `SpeechToTextModel`
5. Implement all abstract methods
6. Add `__post_init__()` following the pattern
7. Handle both file path and BinaryIO inputs
8. Map language codes if provider uses different format
9. Add provider to `factory.py` in `_provider_modules["speech_to_text"]` dict
10. Write tests in `tests/providers/stt/test_provider_name.py`
11. Add documentation in `docs/providers/provider_name.md`

## Special Cases

### OpenAI Whisper

- Supports multiple formats: MP3, MP4, MPEG, MPGA, M4A, WAV, WEBM
- Max file size: 25MB
- Returns language, duration, and segments with timestamps
- Supports prompt for context and spelling hints

### Google Speech-to-Text

- Requires Google Cloud credentials (JSON key file or ADC)
- Uses `google-cloud-speech` library (not just HTTP)
- Different language code format (BCP-47: "en-US" not "en")
- Supports long-running transcription for files >1 minute
- Supports speaker diarization, word-level timestamps

### Groq

- Uses Whisper models but with fast inference
- OpenAI-compatible API format
- Same file size/format limits as OpenAI
- Much faster than standard Whisper

### Azure Speech Service

- Uses Speech SDK or REST API
- Different authentication (subscription key + region)
- Supports real-time streaming (beyond file transcription)
- Different response format than others

## Common Implementation Patterns

### Handling File Uploads

```python
def transcribe(self, audio_file: Union[str, BinaryIO], language: Optional[str] = None, prompt: Optional[str] = None):
    # Read file
    if isinstance(audio_file, str):
        with open(audio_file, "rb") as f:
            file_content = f.read()
        filename = Path(audio_file).name
    else:
        file_content = audio_file.read()
        filename = "audio.mp3"

    # Create multipart request
    files = {"file": (filename, file_content, "audio/mpeg")}
    data = {"model": self.get_model_name()}

    if language:
        data["language"] = language
    if prompt:
        data["prompt"] = prompt

    # Make request
    response = self.client.post(f"{self.base_url}/transcriptions", files=files, data=data)
```

### Error Handling

```python
try:
    response = self.client.post(url, files=files, data=data)
    response.raise_for_status()
    result = response.json()
except httpx.HTTPStatusError as e:
    raise RuntimeError(f"Transcription failed: {e.response.text}")
except Exception as e:
    raise RuntimeError(f"Transcription error: {str(e)}")
```

### Async Implementation

```python
async def atranscribe(self, audio_file: Union[str, BinaryIO], language: Optional[str] = None, prompt: Optional[str] = None):
    # Same file handling as sync version
    if isinstance(audio_file, str):
        with open(audio_file, "rb") as f:
            file_content = f.read()
        filename = Path(audio_file).name
    else:
        file_content = audio_file.read()
        filename = "audio.mp3"

    files = {"file": (filename, file_content, "audio/mpeg")}
    data = {"model": self.get_model_name()}

    # Use async_client
    response = await self.async_client.post(f"{self.base_url}/transcriptions", files=files, data=data)
    response.raise_for_status()
    result = response.json()

    return TranscriptionResponse(text=result["text"], ...)
```

Files in this skill

  • README.md810 B
  • skill.md7.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.