GitHub - th3sull1van/srt-translator-ai: SRT subtitle translator with AI — deterministic pipeline, Next.js 16, OpenAI-compatible providers · GitHub
Skip to content

About

SRT subtitle translator with AI — deterministic pipeline, Next.js 16, OpenAI-compatible providers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

🎬 SRT Translator AI — Deterministic Subtitle Translation for OpenAI-Compatible LLMs

A production-grade Next.js app that translates .srt subtitle files through any OpenAI-compatible provider — with a fully deterministic pipeline where the LLM never rebuilds the SRT.

English • Português (Brasil)


🌟 Key Architecture & Capabilities

  • ⚙️ Deterministic SRT Pipeline — The LLM Never Rebuilds the File:

    • Structural control is always deterministic: parse → internal model → batch → context → LLM → validate → persist → serialize.
    • Every structural element (timestamps, indices, tags, line breaks, music/SDH markers, technical placeholders) is preserved by code, not by the model.
    • Original subtitle file is immutable — export always writes a new file and never overwrites the import.
  • 🛡️ Zero-Trust Response Validation:

    • The LLM must answer strict structured JSON { translations: [{id, text}] }, validated by TranslationResponseValidator (schema, IDs present, no duplicates, no empty text).
    • HTTP 200 is not trusted. Missing IDs are repaired by re-requesting only those entries (maxRepairAttempts = 2), then the batch is marked FAILED.
  • 🧠 Layered Architecture (Presentation → Application → Domain → Infrastructure):

    • Clean separation enforced by convention: src/app (Next.js routes), src/application (translation runner), src/domain (batching/context/window), src/infrastructure (LLM provider, retry, rate limiting), src/lib (SRT parsing, serialization, tokens, validation).
    • Domain never imports Drizzle directly; all DB access is isolated behind src/db/ to keep the SQLite→Postgres swap possible.
  • 🔀 Token-Based Batching + Context Window Management:

    • BatchManager groups subtitles by token budget (default target 1800), not by count, with min/max subtitle guards.
    • ContextManager builds before/after reference context (default 10 before / 5 after), and ContextWindowManager shrinks it if it exceeds the model window.
  • ⏱️ Resilient Execution — Concurrency, Retry, Checkpoint:

    • Configurable concurrency (1–16, default conservative), RateLimiter per-minute and ConcurrencyLimiter.
    • Exponential backoff with jitter on retryable statuses (408/409/425/429/500/502/503/504/timeout); never retries permanent errors (401/403/invalid key/model/malformed).
    • Idempotent checkpoint after each batch: pause/cancel/resume never destroys translated content.
  • 🔒 Server-Only Credentials:

    • API keys are always server-side, masked in the UI (sk-••••…1234), never in logs, client components, or the exported SRT. The LLM flow is Browser → Next Server → LLM Provider, never direct.

🚀 Quick Start

1. Install

bun install   # bun.lock is the source of truth (versioned)

2. Run

bun run dev        # http://localhost:3000 (Next 16 Turbopack)

Runtime note: next dev/next build still run on the Node runtime (Next.js 16 has no stable Bun runtime). Bun is the package manager and runs every script that is not Next itself (vitest, tsx, drizzle-kit, the smoke script).

3. Configure & Translate

  1. Open Settings, register a provider (Base URL, API Key, Default Model) → Test Connection → List Models.
  2. On the project page use Start Translation (provider, model, style, priority, concurrency, glossary).
  3. Edit side-by-side, then Export as .srt (UTF-8 / UTF-8 BOM).

⚙️ Configuration Reference

Project targets (defaults)

Setting Default Description
targetTokens 1800 Token budget per batch sent to the LLM.
minSubtitles / maxSubtitles 6 / 24 Guardrails for batch size.
contextBefore / contextAfter 10 / 5 Reference subtitles around the batch (not translated).
concurrency 4 Parallel batches (1–16).
promptVersion "v1" Versioned system prompt.

Provider config ({ id, name, baseUrl, apiKey, defaultModel, enabled, createdAt, updatedAt })

Credentials are server-only and masked in the UI.


📁 Repository Structure

srt-translator-ai/
├── AGENTS.md                       # Agent law (English; canonical requirements source)
├── README.md                       # Master English documentation
├── README.pt-BR.md                 # Brazilian Portuguese documentation (secondary)
├── SPECIFICATION.md                # Formal technical specification
├── LICENSE                         # MIT
├── package.json                    # Next.js 16 scripts & dependencies (Bun is the package manager)
├── bun.lock                        # Bun lockfile (source of truth, versioned)
├── drizzle.config.ts               # Drizzle config
├── src/
│   ├── app/                        # Next.js App Router — pages and API routes
│   │   ├── layout.tsx  page.tsx
│   │   ├── projects/[id]/          # Project detail + editor
│   │   ├── settings/               # Provider configuration
│   │   └── api/                    # parse, projects, providers, translations
│   ├── application/
│   │   └── translation/runner.ts   # Translation orchestration (concurrency pool)
│   ├── components/
│   │   ├── ui/                     # shadcn primitives (Button, Card, Badge, Select, Tooltip…)
│   │   ├── ds/                     # Design-system layout primitives (Stack, Cluster, Grid, Box, Container)
│   │   ├── layout/  projects/  subtitles/  translation/
│   ├── config/                     # languages.ts, profiles.ts
│   ├── db/                         # Drizzle schema + node:sqlite access (isolated)
│   │   └── schema.ts  index.ts  migrate.ts
│   ├── domain/translation/         # batch-manager, context-manager, window-manager
│   ├── infrastructure/llm/         # provider, factory, prompt, validator, retry, rate-limiter
│   ├── i18n/                       # dictionaries.ts (pt-BR/en), context.tsx
│   ├── lib/                        # srt/, tokens/, cost/, validation/, format, status, notify
│   ├── types/                      # shared domain types
│   └── globals.css                 # design tokens + dark mode
├── tests/                          # Vitest unit + integration suite
│   ├── domain/  llm/  srt/  tokens/
└── scripts/smoke-i18n.cjs          # i18n dictionary smoke check

📖 Extended Documentation


🧪 Tests

bun test              # vitest run (parser, serializer, markup, validator, batch, estimate)
bun run lint          # eslint
bun run build         # production build (Next, on Node runtime)

📄 License

This project is open-source and licensed under the MIT License.

About

SRT subtitle translator with AI — deterministic pipeline, Next.js 16, OpenAI-compatible providers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages