Sublarr

Sublarr

Docker app from Abrechen2's Repository

Overview

Self-hosted subtitle manager for anime and media libraries — a *arr-style companion (and Bazarr alternative) that automatically searches, scores and downloads the best subtitle, then gives you tools to edit, sync and convert it. Runs entirely on your LAN; no cloud required.

What it does:

  • Searches 21 subtitle providers in parallel (AnimeTosho, Jimaku, OpenSubtitles, SubDL, Subscene, Subf2m, Subsource, SubsDump, Addic7ed, BetaSeries, Titlovi, Titrari, TVSubtitles, Gestdown, Kitsunekko, Napisy24, Podnapisi, YIFY, Zimuku, LegendasDivX, TurkceAltyazi) plus embedded subtitle extraction.
  • ASS-first scoring with format, dialect, sync-quality and uploader-trust weighting; smart de-duplication; per-provider circuit breakers.
  • Sonarr/Radarr webhook integration (multi-instance), Jellyfin/Emby/Plex/Kodi library refresh, AniDB absolute-episode-order handling.
  • Standalone mode (no *arr required): watches a folder and reads .nfo metadata.
  • Subtitle toolbox: Aegisub-class waveform editor, ffsubsync/alass sync, format conversion, an 18-step post-processing pipeline, batch OCR and Whisper fallback.
  • Optional LLM translation (Ollama / DeepL / Google / LibreTranslate / OpenAI-compatible) — experimental; quality varies.

Setup:

Sublarr is self-contained — it stores everything in an embedded SQLite database, so no separate database container is required. After the container is healthy, open http://[IP]:[PORT:5765] and the first-run onboarding wizard walks you through language selection, provider keys and automation. Sonarr/Radarr are optional.

Map the Media Path to the same library root your Sonarr/Radarr/Jellyfin see, so subtitle files land next to your videos.

Configuration is UI-first. This template only exposes the handful of boot-level settings (ports, paths, IDs, optional API key / database / log level). Everything else — Sonarr/Radarr connections, provider API keys, language profiles, translation backends, path mapping, automation — is configured in the web UI under Settings and stored in the database. There is no need to set those as environment variables.

Optional backends: PostgreSQL and Redis are supported for larger setups via the SUBLARR_DATABASE_URL / SUBLARR_REDIS_URL variables (advanced) — point them at your own containers. Not needed for normal use.

Optional translation (experimental): install the Ollama Community App and pull a general model (e.g. qwen2.5:14b-instruct), then point Sublarr at it under Settings → Translation in the web UI (e.g. http://host.docker.internal:11434). Disabled by default.

Full documentation: https://sublarr.de/docs/ · Source: https://github.com/Abrechen2/sublarr

Sublarr

Sublarr Logo

Subtitle Manager & Downloader for Anime and Media

*arr-compatible · Self-hosted · Open Source · Anime-first scoring

Version License: GPL-3.0 Python 3.12+ React 19 Docker


Quick Start · Configuration · Integrations · Website · Docs

Community: Discord · Reddit r/Sublarr · GitHub Issues


Sublarr is a self-hosted subtitle manager for anime and media libraries. It automatically searches subtitle providers, scores and downloads the best match (ASS-first), and gives you tools to edit, sync and convert subtitles — all on your LAN, no cloud required.

It follows the *arr-suite design philosophy: connect it to Sonarr/Radarr, set up your language profiles, and let it handle everything automatically via webhooks. Or run it standalone — no *arr setup required.

[!NOTE] V1.0 — stable core. The subtitle search, scoring, download and *arr-integration paths are stable. LLM translation remains experimental (see below). Always keep backups of your subtitle files before enabling automation, and read the CHANGELOG before upgrading. Solo-maintained project — bug reports and contributions welcome.


✨ Features

What's core vs. what's beta

Feature Status
Subtitle search & download (21 providers + embedded extraction) Core — most-tested path
ASS-first scoring, deduplication, trust scoring Core — most-tested path
Sonarr/Radarr webhook integration Core — most-tested path
Standalone mode (no *arr required) Core — filesystem watching + NFO metadata
Language profiles (mustContain, cutoff, audioExclude) Core — functional
Subtitle editor, waveform sync, format conversion Core — functional, rough edges possible
Post-download processing pipeline Core — functional
LLM translation via Ollama / DeepL / Google ⚠️ Beta — experimental, quality varies

🔍 Subtitle Search & Download

  • 21 providers — AnimeTosho, Jimaku, OpenSubtitles, SubDL, Subscene, Subf2m, Subsource, SubsDump, Addic7ed, BetaSeries, Titlovi, Titrari, TVSubtitles, Gestdown, Kitsunekko, Napisy24, Podnapisi, YIFY, Zimuku, LegendasDivX, TurkceAltyazi — plus embedded subtitle extraction
  • ASS-first scoring — ASS/SSA gets +50 bonus over SRT; format, dialect, sync quality, and uploader reputation scored
  • Smart deduplication — avoids re-downloading identical files via SHA-256 hashing
  • Machine translation detection — flags OpenSubtitles mt/ai-tagged uploads with an orange badge
  • Uploader trust scoring — 0–20 bonus based on provider rank (emerald badge for top uploaders)
  • Score breakdown — hover tooltip on score badges shows per-component point breakdown
  • Parallel provider search — all providers queried concurrently via ThreadPoolExecutor
  • Circuit breakers — per-provider CLOSED/OPEN/HALF_OPEN state prevents cascading failures; state persisted across restarts
  • Language profiles — per-series/film target language rules; mustContain / mustNotContain filters, cutoff (stop searching once found), audioExclude (skip if audio already matches target)

📺 *arr & Media Server Integration

  • Sonarr & Radarr webhooks — automatically processes new episodes and movies on import
  • Multi-instance support — connect multiple Sonarr/Radarr/Jellyfin/Emby instances
  • Jellyfin / Emby / Plex / Kodi — triggers library refresh after subtitle completion
  • Tag-based profile assignment — Sonarr/Radarr tags automatically assign language profiles
  • AniDB absolute episode order — correct episode numbering for anime with alternate orders (e.g. Haruhi)
  • Anime multi-season fallback — OpenSubtitles season-1 collapse for anime indexed without season split
  • Path mapping — supports remote *arr setups where file paths differ between hosts

🗂️ Standalone Mode (no *arr required)

  • Filesystem watching — monitors configured folders; automatically adds new video files to the wanted list
  • NFO metadata — reads .nfo sidecar files to resolve series/movie title, TVDB/TMDB IDs without API calls
  • Auto-mode — when no *arr is configured, Sublarr activates standalone mode automatically on startup
  • Extras skipping — trailers, samples, featurettes excluded from subtitle discovery
  • Symlink support — follows symlinked directories during scan

🔧 Subtitle Tools

  • Waveform editor (Aegisub-class) — drag region edges to retime cues, click-set start/end (S / D keys), snap to keyframes / scene cuts / neighbour cues with priority-tied tie-breaking, gap & overlap quality markers, vertical amplitude zoom (1×–5×), pitch-preserving playback rate (0.5×–2×), sticky time-axis ruler, optional spectrogram overlay, optional audio-scrub-while-dragging, multi-audio-track picker, ASS karaoke syllable overlay
  • CodeMirror editor — syntax-highlighted ASS/SRT editing with diff view
  • Video sync — ffsubsync & alass integration for automatic timing correction (install directly from the UI)
  • Format conversion — convert between ASS, SRT, VTT, SSA via pysubs2
  • Post-processing pipeline — 18 fix functions (HI removal, OCR artifact cleanup, formatting corrections); configurable per-series
  • Quality fixes — one-click overlap fix, timing normalization, line merge/split, spell-check
  • Batch OCR — extract text from PGS/VobSub image tracks via Tesseract
  • Whisper fallback — generate subtitles from audio when no text subs exist
  • Stream removal — safely remove embedded subtitle streams from video containers without re-encoding

🖥️ Wanted & Automation

  • Wanted scanner — detects all episodes/movies missing subtitles in your library
  • Event-driven by default — webhooks, manual triggers, and the file-watcher kick scans; periodic fallback only when SUBLARR_WANTED_SCAN_INTERVAL_HOURS > 0
  • Scheduler adminSettings → System → Scheduler lists every background job (wanted scanner, search, cleanup, upgrade scan, AniDB sync, history pruning) with run-now / pause / resume / edit-trigger controls. Backed by APScheduler with SQLAlchemyJobStore — jobs persist across restarts with next-fire-time intact.
  • Failure details — failed items show inline error reason, attempt count, and next retry countdown
  • Subtitle upgrade system — automatically replaces low-quality subs when a better version appears
  • Batch search — run searches across all wanted items with live progress bar
  • Anime-only mode — optionally limit wanted scanning to anime series

🌐 LLM Translation (optional · experimental · off by default)

Sublarr can optionally translate subtitles with a local or cloud LLM (Ollama, DeepL, Google, LibreTranslate, or any OpenAI-compatible endpoint). It is disabled by default and not a headline feature — quality varies a lot by model and language pair, so treat it as a bonus, not a reason to use Sublarr. EN→DE anime is the best-tested path.

If you want to try it, see the translation docs.

🎨 UI

  • *arr-style dark theme with teal accent — feels at home next to Sonarr, Radarr, Prowlarr
  • Fully redesigned Settings UI — grouped cards, advanced toggles, inline field descriptions, unsaved-changes guard
  • Customizable dashboard with draggable widgets and automation status widget
  • Plugin marketplace/plugins page lets you install community subtitle providers from a Git URL allowlist; ships with circuit breakers + rate-limit wiring identical to first-party providers
  • Global search (Ctrl+K) across all pages
  • Real-time updates via WebSocket (activity feed, job progress)
  • Onboarding wizard for first-time setup (language, automation, connections)
  • Keyboard shortcuts throughout (? to view all)

🚀 Quick Start

# 1. Copy environment file
cp .env.example .env

# 2. Edit .env — set your media path at minimum
nano .env

# 3. Start
docker compose up -d

Open http://localhost:5765 — that's it.

First-time setup: The onboarding wizard will guide you through language selection, provider API keys, and automation settings. Sonarr/Radarr are optional — Sublarr can run standalone.


🐳 Docker

Minimal docker-compose.yml

services:
  sublarr:
    image: ghcr.io/abrechen2/sublarr:latest
    container_name: sublarr
    ports:
      - "5765:5765"
    volumes:
      - ./config:/config        # database, backups, logs
      - /path/to/media:/media   # your media library (same path as Jellyfin/Emby sees)
    environment:
      - PUID=1000
      - PGID=1000
      - SUBLARR_MEDIA_PATH=/media
    restart: unless-stopped

Production Hardening

The image runs as a non-root user with cap_drop: ALL and no new privileges. A full production example with resource limits:

services:
  sublarr:
    image: ghcr.io/abrechen2/sublarr:latest
    container_name: sublarr
    ports:
      - "5765:5765"
    volumes:
      - ./config:/config
      - /mnt/media:/media:rw
    env_file: .env
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 4G
        reservations:
          cpus: '0.5'
          memory: 512M
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - SETGID
      - SETUID
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5765/api/v1/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

User / Group IDs

Sublarr runs as a non-root user inside the container. Set PUID and PGID to match your host user so volume file permissions work correctly:

id $USER          # → uid=1000(you) gid=1000(you)
# then set PUID=1000 PGID=1000 in .env

⚙️ Configuration

All settings use the SUBLARR_ prefix. They can be set via environment variables, .env file, or the Settings UI at runtime (stored in the database).

Core

Variable Default Description
SUBLARR_MEDIA_PATH /media Root path of your media library
SUBLARR_DB_PATH /config/sublarr.db SQLite database location
SUBLARR_PORT 5765 HTTP port
SUBLARR_API_KEY (empty) Optional API key for auth (X-Api-Key header)
SUBLARR_LOG_LEVEL INFO Log level (DEBUG, INFO, WARNING, ERROR)
PUID / PGID 1000 Container user/group IDs

Translation (beta)

Translation is disabled by default (SUBLARR_WANTED_AUTO_TRANSLATE=false). When disabled, only subtitle download runs — no LLM calls are made. Enable only if you have a working Ollama instance and accept variable quality.

Variable Default Description
SUBLARR_WANTED_AUTO_TRANSLATE false Auto-translate after subtitle download in wanted scanner
SUBLARR_WEBHOOK_AUTO_TRANSLATE true Auto-translate after webhook-triggered download (gated by master translation_enabled)
SUBLARR_OLLAMA_URL http://localhost:11434 Ollama base URL
SUBLARR_OLLAMA_MODEL qwen2.5:14b-instruct Model for translation
SUBLARR_SOURCE_LANGUAGE en Source subtitle language
SUBLARR_TARGET_LANGUAGE de Default target language
SUBLARR_BATCH_SIZE 15 Subtitle cues per LLM call
SUBLARR_TEMPERATURE 0.3 LLM temperature (lower = more consistent)

Provider API Keys

Variable Provider
SUBLARR_OPENSUBTITLES_API_KEY OpenSubtitles
SUBLARR_JIMAKU_API_KEY Jimaku
SUBLARR_SUBDL_API_KEY SubDL

AnimeTosho, Subscene, Subf2m, Subsource, Kitsunekko, and most other providers work without an API key.

Automation

Variable Default Description
SUBLARR_WANTED_SCAN_INTERVAL_HOURS 0 Periodic scan interval. 0 = disabled — scan is event-driven (webhook / manual / file-watcher). Set > 0 for a periodic fallback.
SUBLARR_WANTED_SEARCH_INTERVAL_HOURS 24 How often the search loop revisits unresolved wanted items
SUBLARR_WANTED_SCAN_ON_STARTUP false Run a full scan when the container starts
SUBLARR_WANTED_ANIME_ONLY true Only scan anime series
SUBLARR_UPGRADE_ENABLED true Replace low-quality subs with better versions

Path Mapping (remote *arr hosts)

If your Sonarr/Radarr runs on a different host and uses different paths than Sublarr:

SUBLARR_PATH_MAPPING=/data/media=/mnt/media

See sublarr.de/docs/getting-started/environment-variables for the complete variable reference.


🔌 Integrations

Sonarr & Radarr

  1. In Sonarr/Radarr: Settings → Connect → Add → Webhook
  2. URL: http://sublarr:5765/api/v1/webhook/sonarr (or /radarr)
  3. Events: ✅ On Import, ✅ On Upgrade
  4. (Optional) Set SUBLARR_SONARR_URL + SUBLARR_SONARR_API_KEY for library refresh

Sublarr will automatically search and download subtitles for every new import. Translation only runs if SUBLARR_WEBHOOK_AUTO_TRANSLATE=true.

Standalone (no *arr required)

Point Sublarr at your media folder in Settings → Library Sources. It will watch for new files and add them to the wanted list automatically. Metadata is read from .nfo sidecars or parsed from filenames.

Jellyfin / Emby

  1. Sublarr → Settings → Connections → Add Media Server
  2. Enter your server URL and API key
  3. Sublarr will trigger a library refresh after each subtitle download

Ollama (Local LLM — translation beta)

⚠️ Translation quality is variable. Only enable if you need it. The custom anime-translator-* GGUFs we previously published are currently broken; do not use them. If a stable replacement ships, this section will name it explicitly.

Use a general-purpose instruction-tuned model:

ollama pull qwen2.5:14b-instruct   # good all-rounder, ~9 GB
ollama pull llama3.1:8b-instruct   # lighter, ~5 GB

Then set in your .env:

SUBLARR_OLLAMA_MODEL=qwen2.5:14b-instruct
SUBLARR_WANTED_AUTO_TRANSLATE=true

Set SUBLARR_OLLAMA_URL to your Ollama host. For Docker, use http://host.docker.internal:11434.


🖥️ UI Overview

Page Description
Dashboard Customizable widget grid — status, queue, recent activity, automation status
Library All series/movies with subtitle progress and bulk actions
Wanted Missing subtitle queue with one-click search, failure details, retry countdown
Queue Live job progress (downloading, translating, syncing)
Activity Real-time event feed
History Past operations with timestamps and results
Statistics Charts — provider success rates, language distribution, quality trends
Plugins Community plugin marketplace — install custom subtitle providers from an allowlisted Git URL
Settings Grouped cards — Connections, Languages & Subtitles, Providers, Automation, System
Settings → System → Scheduler APScheduler admin — list, run-now, pause/resume, edit-trigger, view history per background job

The subtitle editor (accessible from Library/Series Detail) includes:

  • Preview — formatted subtitle preview with cue navigation
  • Editor — CodeMirror syntax-highlighted ASS/SRT editing
  • Diff — side-by-side comparison with the saved version
  • Waveform — Aegisub-class timing surface (drag to retime, snap to keyframes / scenes / neighbours, gap & overlap markers, amplitude + pitch-preserving rate, S/D hotkeys, optional spectrogram + scrub-on-drag)

💻 Development

# First-time setup (installs Python + Node dependencies, optional pre-commit hooks)
npm run setup:sh      # Linux/Mac
npm run setup:ps1     # Windows PowerShell

# Start backend (:5765) + frontend (:5173) in parallel
npm run dev

# Tests
cd backend && python -m pytest
cd frontend && npm test

# Lint & type check
cd backend && ruff check . && ruff format --check .
cd frontend && npm run lint && npx tsc --noEmit

📚 Documentation

Full documentation lives at sublarr.de/docs.

Live API discovery

Every Sublarr instance ships its own interactive API reference:

Endpoint Purpose
GET /api/docs Swagger UI — browse + try-it-out (anonymous-readable; click "Authorize" to inject your X-Api-Key for authenticated endpoints)
GET /api/v1/openapi.json Raw OpenAPI 3.0.3 spec — feed into Postman / Insomnia / Bruno or generate a TypeScript client via openapi-typescript / orval
Topic Doc Page
Installation Getting Started → Installation
Configuration reference Getting Started → Environment Variables
Upgrade guide Getting Started → Upgrade Guide
FAQ Getting Started → FAQ
Sonarr/Radarr/Jellyfin setup User Guide → Integrations
Language profiles User Guide → Language Profiles
LLM translation (beta) User Guide → Translation & LLM
Standalone mode Getting Started → Installation (Scenario 2)
Subtitle scoring algorithm User Guide → Settings → Providers (Scoring)
Provider system User Guide → Settings → Providers
REST API reference Development → API Reference
Architecture & data flow Development → Architecture
Plugin development Development → Plugin Development
Contributing & PR workflow Development → Contributing
Database schema Development → Database Schema
Reverse proxy setup Troubleshooting → Reverse Proxy
Performance tuning Troubleshooting → Performance Tuning
Troubleshooting Troubleshooting → General
ROADMAP.md Feature roadmap and version planning
CHANGELOG.md Release notes
.env.example Minimal deployment template

🤖 How AI was used in this project

Honest answer, since it comes up: yes, AI was used as a coding assistant throughout Sublarr's development. I think the fair thing is to be specific about where it helped and where it didn't, so you can judge for yourself.

Where AI helped:

  • Boilerplate and scaffolding — route handlers, repository classes, TypeScript types, config plumbing
  • Test generation — the bulk of the ~5000-test suite was AI-drafted, then reviewed and corrected by hand
  • Refactoring at scale — the route/service file splits, inline-style → Tailwind migration, and the i18n pass were AI-assisted sweeps
  • Documentation — README, changelog prose, and the docs site started as AI drafts
  • Rubber-ducking — second opinions on tricky bugs and design trade-offs

Where AI did not decide things:

  • The architecture, the data model, and how the pieces fit together
  • The subtitle scoring system (ASS-first weighting, dialect/sync/trust scoring) — the part that actually makes Sublarr useful
  • Provider integrations and their quirks (AniDB absolute order, anime season collapse, format fidelity) — all hand-debugged against real data
  • The waveform editor's interaction model
  • Every production deploy decision, security fix, and what ships vs. doesn't

AI is a tool I used to move faster on the parts that are tedious. The product decisions, the hard debugging, and the year+ of iteration are mine. If a generated chunk was wrong, it got fixed by hand — which is most of what "using AI a lot" actually looks like in practice.

If that's a dealbreaker for you, fair enough. If you try it and find a bug, a report with logs is worth more to me than any opinion about the tooling.


🤝 Contributing

Contributions are welcome — bug reports, feature requests, and pull requests.

  1. Bug reports → open a GitHub Issue with your log output and config
  2. Feature requests → open a Discussion so we can talk through the approach first
  3. Pull requests → see sublarr.de/docs/development/contributing for code style, testing requirements, and commit format

💬 Community


📄 License

GPL-3.0 — see LICENSE.

Sublarr is not affiliated with the *arr project or any subtitle provider.


Made with ☕ for the self-hosting community

Donate via PayPal

Install Sublarr on Unraid in a few clicks.

Find Sublarr in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for Sublarr Review the template variables and paths Click Install

Download Statistics

65
Total Downloads

Related apps

Details

Repository
ghcr.io/abrechen2/sublarr:latest
Last Updated2026-06-14
First Seen2026-06-13

Runtime arguments

Web UI
http://[IP]:[PORT:5765]/
Network
bridge
Shell
sh
Privileged
false
Extra Params
--restart=unless-stopped --add-host=host.docker.internal:host-gateway

Template configuration

WebUI PortPorttcp

Host port for the Sublarr web UI and API. Swagger UI is available at /api/docs.

Target
5765
Default
5765
Value
5765
Config PathPathrw

Persistent application data — SQLite database, plugins, backups and logs. Single volume; nothing else needs to be mounted for normal use.

Target
/config
Default
/mnt/user/appdata/sublarr
Value
/mnt/user/appdata/sublarr
Media PathPathrw

Root of your media library. Must be the same path your Sonarr/Radarr/Jellyfin use so subtitles are written next to the video files.

Target
/media
Default
/mnt/user/media
Value
/mnt/user/media
PUIDVariable

User ID for file ownership. Unraid default is 99 (nobody).

Default
99
Value
99
PGIDVariable

Group ID for file ownership. Unraid default is 100 (users).

Default
100
Value
100
TZVariable

Container timezone, e.g. Europe/Berlin or UTC.

Default
Europe/Berlin
Value
Europe/Berlin
API KeyVariable

Optional API key (X-Api-Key header) protecting the API. Strongly recommended if the port is exposed beyond your LAN.

Target
SUBLARR_API_KEY
Database URLVariable

Advanced: PostgreSQL DSN to use Postgres instead of the built-in SQLite, e.g. postgresql://sublarr:PASSWORD@host.docker.internal:5432/sublarr. Leave empty for SQLite (recommended).

Target
SUBLARR_DATABASE_URL
Redis URLVariable

Advanced: Redis connection string for the job queue, e.g. redis://host.docker.internal:6379/0. Leave empty to use the in-process queue (recommended).

Target
SUBLARR_REDIS_URL
Log LevelVariable

Advanced: log verbosity — DEBUG, INFO, WARNING or ERROR.

Target
SUBLARR_LOG_LEVEL
Default
INFO
Value
INFO