*arr-compatible · Self-hosted · Open Source · Anime-first scoring
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.
| 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 |
- 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)
- 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
- Filesystem watching — monitors configured folders; automatically adds new video files to the wanted list
- NFO metadata — reads
.nfosidecar 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
- Waveform editor (Aegisub-class) — drag region edges to retime cues, click-set start/end (
S/Dkeys), 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 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 admin — Settings → 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
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.
- *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 —
/pluginspage 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)
# 1. Copy environment file
cp .env.example .env
# 2. Edit .env — set your media path at minimum
nano .env
# 3. Start
docker compose up -dOpen 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.
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-stoppedThe 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"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 .envAll settings use the SUBLARR_ prefix. They can be set via environment variables, .env file, or the Settings UI at runtime (stored in the database).
| 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 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) |
| 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.
| 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 |
If your Sonarr/Radarr runs on a different host and uses different paths than Sublarr:
SUBLARR_PATH_MAPPING=/data/media=/mnt/mediaSee sublarr.de/docs/getting-started/environment-variables for the complete variable reference.
- In Sonarr/Radarr: Settings → Connect → Add → Webhook
- URL:
http://sublarr:5765/api/v1/webhook/sonarr(or/radarr) - Events: ✅ On Import, ✅ On Upgrade
- (Optional) Set
SUBLARR_SONARR_URL+SUBLARR_SONARR_API_KEYfor library refresh
Sublarr will automatically search and download subtitles for every new import. Translation only runs if SUBLARR_WEBHOOK_AUTO_TRANSLATE=true.
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.
- Sublarr → Settings → Connections → Add Media Server
- Enter your server URL and API key
- Sublarr will trigger a library refresh after each subtitle download
⚠️ Translation quality is variable. Only enable if you need it. The customanime-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 GBThen set in your .env:
SUBLARR_OLLAMA_MODEL=qwen2.5:14b-instruct
SUBLARR_WANTED_AUTO_TRANSLATE=trueSet SUBLARR_OLLAMA_URL to your Ollama host. For Docker, use http://host.docker.internal:11434.
| 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)
# 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 --noEmitFull documentation lives at sublarr.de/docs.
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 |
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.
Contributions are welcome — bug reports, feature requests, and pull requests.
- Bug reports → open a GitHub Issue with your log output and config
- Feature requests → open a Discussion so we can talk through the approach first
- Pull requests → see sublarr.de/docs/development/contributing for code style, testing requirements, and commit format
- Discord — discord.gg/WjatsKzHXz — live chat, install help, beta testing
- Reddit — r/Sublarr — announcements, showcases, discussions
- GitHub Issues — bug reports & feature requests
GPL-3.0 — see LICENSE.
Sublarr is not affiliated with the *arr project or any subtitle provider.