All apps · 0 apps
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
Readme
View on GitHubSublarr

Subtitle Manager & Downloader for Anime and Media
*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.
✨ 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
.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
🔧 Subtitle Tools
- 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 & 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 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
🌐 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 —
/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)
🚀 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
- 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.
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
- Sublarr → Settings → Connections → Add Media Server
- Enter your server URL and API key
- 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 |
🤖 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.
- 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
💬 Community
- Discord — discord.gg/WjatsKzHXz — live chat, install help, beta testing
- Reddit — r/Sublarr — announcements, showcases, discussions
- GitHub Issues — bug reports & feature requests
📄 License
GPL-3.0 — see LICENSE.
Sublarr is not affiliated with the *arr project or any subtitle provider.
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.
Download Statistics
Related apps
Explore more like this
Explore allDetails
ghcr.io/abrechen2/sublarr:latestRuntime 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
Host port for the Sublarr web UI and API. Swagger UI is available at /api/docs.
- Target
- 5765
- Default
- 5765
- Value
- 5765
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
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
User ID for file ownership. Unraid default is 99 (nobody).
- Default
- 99
- Value
- 99
Group ID for file ownership. Unraid default is 100 (users).
- Default
- 100
- Value
- 100
Container timezone, e.g. Europe/Berlin or UTC.
- Default
- Europe/Berlin
- Value
- Europe/Berlin
Optional API key (X-Api-Key header) protecting the API. Strongly recommended if the port is exposed beyond your LAN.
- Target
- SUBLARR_API_KEY
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
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
Advanced: log verbosity — DEBUG, INFO, WARNING or ERROR.
- Target
- SUBLARR_LOG_LEVEL
- Default
- INFO
- Value
- INFO