Srtx Architecture
Scope
The current Srtx implementation supports one end-to-end workflow: translating one local SRT file through the regular Gemini Developer API.
The implementation deliberately excludes resume state, streaming, audio context, transcription, FFmpeg extraction, multiple API keys, and token reports.
Package layers
Public caller or Typer CLI
|
v
srtx.api / Srtx
|
v
SubtitleTranslator
| | |
v v v
SRT I/O Batcher Prompt builder
|
v
TextGenerationProvider
|
v
GeminiProvider
Public API layer
src/srtx/api.py provides the simple configure() and translate() facade.
src/srtx/app.py provides the explicit object-oriented Srtx facade.
This layer resolves API keys and constructs the Gemini provider. Environment variables are not read by lower-level services.
Translation service
SubtitleTranslator coordinates the workflow:
- Resolve input and output paths.
- Read and validate the source SRT.
- Divide subtitle entries into deterministic batches.
- Build a provider-independent translation prompt.
- Ask the configured provider for JSON.
- Validate response count, indexes, order, schema, HTML tags, line breaks, and empty text.
- Apply translated text without changing timestamps.
- Apply RTL embedding when translated text is predominantly RTL.
- Write the output SRT.
- Return
TranslationResult. - Emit progress events throughout the workflow.
The service does not know about Typer, Rich, Gemini SDK classes, or terminal rendering.
Provider boundary
TextGenerationProvider is a small protocol:
class TextGenerationProvider(Protocol):
def generate_json(self, prompt: TranslationPrompt) -> str: ...
SubtitleTranslator depends on this protocol rather than GeminiProvider.
This allows tests and embedding applications to supply fake or custom
providers.
The Gemini adapter owns:
- Creating
google.genai.Client - Constructing Gemini request configuration
- Requesting structured JSON
- Converting SDK errors into Srtx exceptions
- Releasing Gemini client resources
Gemini SDK objects do not enter domain or service models.
Domain layer
Important immutable domain objects include:
SubtitleLineTranslationItemTranslationBatchProgressEventTranslationResult
External Gemini JSON is validated with Pydantic before it is converted into domain objects.
File I/O
SubtitleFileRepository is responsible for parsing and writing SRT data.
It preserves:
- Subtitle indexes
- Source order
- Start and end timestamps
- Internal line breaks
- Empty subtitle text
- Formatting contained in subtitle text
Path validation and default output naming belong to io/paths.py.
Progress reporting
Core services emit ProgressEvent instances to the ProgressSink protocol.
Available sinks include:
NullProgressSinkMemoryProgressSink- CLI-only
RichProgressSink
Core services never render terminal output directly.
Error boundaries
Expected failures derive from SrtxError.
The library raises typed errors. The CLI catches SrtxError, displays a
user-facing message, and exits with a non-zero status.
Unexpected programming errors are not silently hidden.