Skip to content

Bazarr+ v2.1.0 (LiveWire)

Choose a tag to compare

@LavX LavX released this 19 Apr 20:35
f291e73

Bazarr+ v2.1.0 - LiveWire

Bazarr+ v2.1.0 (LiveWire)

A full subtitle editor now lives inside Bazarr+: video preview with audio track selection, waveform timeline, inline cue editing, ffsubsync auto-sync, AI translation per cue, bold/italic authoring with live ASS tag rendering. Plus supervisor-backed startup with SSE progress, request-a-stop on running jobs, a landing site at lavx.github.io/bazarr, opt-in subdl anime/pack support, and three upstream fixes that prevent silent failure modes in long-running instances.

54 non-merge commits since v2.0.0 (Eclipse). 243 files changed, +22,423 / -3,237 lines.


Headline: Full Subtitle Editor

Built into the Subtitles page. Click any subtitle row to open.

  • Video preview pane with native HTML5 player, audio track selection, external audio streams, remux mode, and playback rate control.
  • Waveform timeline rendered from the source file via ffmpeg, click-to-seek, zoomable 10-500px/s.
  • Cue table with inline time/text editing, split, merge, bulk shift, and id-keyed row tracking that survives auto-sort.
  • 7 formats (8 parser entry points counting SSA as an alias of ASS): SRT, VTT, ASS/SSA, SUB, SMI, MPL, TXT with round-trip fidelity.
  • ffsubsync whole-file auto-sync plus manual bulk shift and linear stretch for finer adjustments.
  • AI translation per cue or selection reusing the v2.0 OpenRouter integration.
  • Inline styling: bold/italic keyboard shortcuts (Ctrl+B / Ctrl+I) for ASS authoring, and live preview rendering of italic/bold/colour tags in the cue table. Translate-source toggle (auto / reference / editor).
  • Undo/redo keyed by cue id, not index, so history survives auto-sort and re-indexing.
  • ETag-backed save with 412/409 conflict detection when the file changed on disk since open.
  • 30+ keyboard shortcuts covering playback, editing, navigation, selection, save.

What's New

Supervisor Process Manager with SSE Startup Screen

Bazarr+ now boots under a lightweight supervisor (docker/supervisor.py) that streams startup progress over Server-Sent Events. The UI shows a live startup screen instead of blank-screen-until-ready, and the supervisor restarts Bazarr with backoff if the main process crashes.

Request-a-Stop on Running Jobs

Ask any in-progress job (mass sync, translate, scan, upgrade) to stop from the Jobs Manager. Cancellation is cooperative: the job aborts at its next progress checkpoint. Previously you had to wait or restart the container.

Scan All Button on Missing Pages

One click to re-index on-disk subtitles for every missing item directly from Wanted > Missing, for both Movies and Series.

Health Re-check Button on Status Page

Force a re-check of Sonarr and Radarr root folders plus language-profile issues from the Status page without restarting Bazarr.

GitHub Pages Landing Site

lavx.github.io/bazarr with hero, feature tour, guides (getting started, AI translation, migration from upstream), and an interactive installer script that provisions Docker and optional companion services.

subdl Anime and Pack Support (Opt-in)

New subdl.anime_mode setting (default off). When enabled:

  • Extra absolute-episode search for anime with non-sequential numbering.
  • Season-only fallback search for cour-split / arc-based seasons (e.g. Fire Force S3).
  • Title-only last-resort search on Episode videos when all prior searches return empty.
  • Subtitle pack acceptance when the pack's episode range covers the target episode; archive extraction then picks the matching episode file.

Non-anime users pay no extra API cost (no fanout). One small behaviour change applies to everyone: single-episode archive extraction now prefers .srt/.sub/.ssa/.ass entries and only falls back to the first file if none are present.


UX Overhaul

A usability and accessibility sweep across the app (commits 2c9868448, 5b56339ac, 5a459cdc2, ~29 items in aggregate):

  • Confirmation dialogs for Restart and Shutdown.
  • Gear icon replaced with vertical ellipsis where it was ambiguous.
  • Tooltip delays reduced from 2s to 500ms for snappier hover cues.
  • Context-menu tools grouped into labeled sections; breadcrumbs added with nav landmark.
  • Wanted and Blacklist renamed to Missing and Excluded to match Sonarr/Radarr vocabulary; nav entry shortened from "Missing Subtitles" to "Missing".
  • Settings navigation gained sub-group labels for Connections / Subtitles / Application.
  • Mass Translate warning moved above action buttons.
  • Progressive disclosure (More dropdown) on batch-action toolbars.
  • Badge tooltips explaining subtitle status colours.
  • Page-size dropdown replaced with a searchable Select; window.confirm replaced with Mantine modals; editor panel overlays repositioned.
  • Notification toast z-index raised above navbar and grain overlay.
  • Subtitle badges click again (regression fix: Menu.Target wrapping was swallowing clicks; Tooltip.Floating removed from interactive rows).
  • Navbar inner panel no longer stretches to full height when content is short.
  • Lazy-loaded route pages reverted (lost too many interaction edges); modal registry rebuilt to stay compatible.

Accessibility-specific items in the sweep: WCAG contrast fix on tertiary/disabled text, UnstyledButton wrappers for keyboard/SR support on clickable badges, role="group" + aria-labelledby on semantic groups, faClosedCaptioning replacing faDeaf, breadcrumbs nav landmark.


Upstream Sync (April 2026)

Cherry-picked from morpheus65535/bazarr through 950a0fcb0:

  • Adaptive-search backoff fix (e3340f72d). Provider outages used to stamp failedAttempts and poison the retry schedule, silently stalling fetches for items that are actually findable. Stamps now fire only when every provider returned empty.
  • SignalR WebSocket FD leak fix (950a0fcb0). signalrcore.stop() closed the socket only when state was connected, so handshake and reconnect failures leaked file descriptors until the process hit EMFILE. Ships with a 10-method regression suite (pytest: 10 passed, 4 subtests) and promotes signalrcore from libs/ to custom_libs/ per the fork-convention registry.
  • Optional no-missing-subs notification (6c2982f4c) on Sonarr/Radarr live sync events (opt-in, default off). Fork-local copy softened to drop upstream's internal "LIVE event" / "signalr" jargon.

The subdl anime/pack commit 71fc948ea is also in this upstream window but is covered separately above since it ships gated behind subdl.anime_mode.


Security & Hardening

  • Frontend dependency remediation (#55). Lockfile upgraded: axios 1.15.0, vite 7.3.2, lodash 4.18.1, socket.io-parser 4.2.6, defu 6.1.7, picomatch 4.0.4 (2.3.2 also resolved transitively), serialize-javascript 7.0.5. npm audit reports zero high/critical and one unrelated moderate (follow-redirects, transitive, tracked). GitHub still shows ten legacy Dependabot alerts in "open" state pending auto-close; the underlying vulnerabilities are no longer resolved in the build.
  • Code-scanning remediation (#56). _is_safe_path() validation for subtitle content endpoints, path-confinement for PWA asset serving, API key values no longer logged, SMI tag stripping hardened against nested payloads, permissions: contents: read pinned on CI. Follow-up 1074a047b adds raw .. rejection before normalisation and an os.sep suffix to block sibling-prefix bypass (/build-evil vs /build).
  • Subtitle editor works on HTTP LAN deployments. crypto.randomUUID() is only defined in secure contexts, so self-hosted users on http://192.168.x.x hit a TypeError that broke every parser. New uuid.ts helper gates on window.isSecureContext (plus localhost/127.0.0.1) and falls back to a deterministic cue-<timestamp>-<counter> id.

Bug Fixes

  • Base URL-aware proxy routes and auth-redirect deadlock (10caaa72c): reverse-proxy users on /bazarr/ subpaths are unblocked.
  • ETag 409/412 save conflict handling + undo/redo sort consistency (4c1fb91b4).
  • Optional chaining on settings.data.general (1f52655b6): avoids crash when config is partially loaded during startup.
  • Navigation blocker discard crash (8d5b5a9a3): fixes "Invalid blocker state transition" when aborting an edit mid-dirty-state.
  • History test updated to match the Blacklist → Excluded rename (3995abd99).
  • Lint status: ESLint 0 errors, 19 pre-existing warnings (mostly unused error in catch clauses and unused Settings imports); Prettier clean. All warnings are non-blocking and tracked for cleanup.

Dependency Bumps

  • Mantine major bump: 8.x → 9.0.2 across six packages (@mantine/core, dropzone, form, hooks, modals, notifications). Review any fork-specific component overrides.
  • Runtime: React 19.2, Vite 7.3.1, Mantine 9.0.2, TypeScript 5.9.3, ESLint 10.0.3 (flat config), typescript-eslint 8.57, react-router 7.13 (v7 major), Vitest 4.0 (v4 major).
  • CI actions: softprops/action-gh-release 2 → 3, actions/upload-artifact 4 → 7, docker/setup-buildx-action 3 → 4.

Runtime

  • Python 3.14 target (backend matrix-tested on 3.12 / 3.13 / 3.14)
  • Node 22.13.0 (pinned via frontend/.nvmrc)
  • React 19.2, Vite 7.3, Mantine 9.0, TypeScript 5.9, ESLint 10 flat config

Migration from v2.0.0

Drop-in replacement. Pull the new image, restart.

docker pull ghcr.io/lavx/bazarr:v2.1.0
# or :latest for rolling

No config migration required. Existing translator profiles, language profiles, provider settings, and encrypted API keys all carry over. If you used v2.1.0-rc1, you are already on this path.


Docker

docker pull ghcr.io/lavx/bazarr:v2.1.0
docker pull ghcr.io/lavx/bazarr:latest

Docker Compose:

git clone --recursive https://github.com/LavX/bazarr.git
cd bazarr
docker compose up -d

Full Changelog: v2.0.0...v2.1.0