Skip to content

feat: Subtitle Editor#50

Merged
LavX merged 9 commits intodevelopmentfrom
feature/subtitle-editor
Apr 6, 2026
Merged

feat: Subtitle Editor#50
LavX merged 9 commits intodevelopmentfrom
feature/subtitle-editor

Conversation

@LavX
Copy link
Copy Markdown
Owner

@LavX LavX commented Apr 2, 2026

Subtitle Editor

A full-featured subtitle editor built directly into Bazarr+. Edit, translate, sync, and preview subtitles without leaving the app.

Keyboard shortcuts AI Translate with reference
Shortcuts Translate

What's New

Core Editor

  • Editable cue table with inline timing fields (scroll-wheel adjust), text editing, CPS/line-length indicators
  • Undo/Redo with full operation history (Ctrl+Z / Ctrl+Y)
  • Multi-select cues with Shift+Click for batch operations
  • Add/Delete/Split/Merge cue operations with keyboard shortcuts
  • Auto-sort cues by start time after any timing change, selection follows by cue id
  • Gap detection (1s minimum) with click-to-create ghost rows
  • QC panel with configurable presets: overlap detection, gap analysis, CPS limits, line length, duration warnings
  • Search & Replace with regex support across all cues
  • Jump to Cue by number
  • Bookmarks with filter toggle (Ctrl+B to bookmark, Ctrl+Shift+B to jump)
  • Quality markers with visible symbols per severity level

Video Preview

  • Direct play for browser-supported codecs (H.264, HEVC, VP9, AV1), automatic remux/transcode fallback
  • Audio track switching via separate cached audio element (no video reload)
  • Seekbar with full-width range slider
  • -5s / +5s seek buttons and Alt+Left/Right keyboard shortcuts
  • Playback speed control (0.25x to 2x)
  • Subtitle overlay on the video synced to playback position
  • Codec detection badge (Direct/Remux/Transcode) with browser capability tooltip

Waveform Timeline

  • Audio waveform visualization with peaks loaded from server
  • Draggable/resizable cue regions directly on the waveform
  • Click-to-seek on waveform
  • Selected cue highlighting with auto-scroll
  • Audio track-aware peaks (reloads waveform on track switch)

AI Translation

  • Source toggle: Auto / Reference / Editor cues
  • Reference subtitle loading from existing files on disk or file import
  • Batch translation of all cues via AI Subtitle Translator (OpenRouter)
  • Creates cues from reference timing when translating into empty subtitle
  • Per-line AI translate button in detail pane with reference context
  • Reference text follows playback position, not just selected cue
  • Use button creates new cue at reference timing if no nearby cue exists

Subtitle Sync (ffsubsync)

  • Integrated ffsubsync with server-side execution via jobs queue
  • VAD selection: Default, subs_then_webrtc, subs_then_auditok, webrtc, auditok
  • Golden-Section Search toggle for framerate ratio optimization
  • No Fix Framerate toggle
  • Max offset configuration (60/120/300/600 seconds)
  • Progress tracking in Jobs Manager with real-time status

Text Editing Tools

  • Style buttons: Italic, Bold, Underline (wrap selection in HTML tags)
  • Symbol insert: Music note, ellipsis, em dash, inverted punctuation
  • Ctrl+I/B/U keyboard shortcuts for tag wrapping
  • CPS and line length strip HTML tags before counting

Timing Tools

  • Shift all cues by offset (positive/negative milliseconds)
  • Linear correction (two-point fit) for drift compensation
  • Set start/end from playback position
  • Nudge timing with Ctrl+Shift+Arrow shortcuts (start/end, +-100ms/500ms)

Persistence & Recovery

  • Auto-save to localStorage on every change (2s debounce)
  • Recovery banner on load if unsaved draft found (< 24 hours old)
  • beforeunload warning for unsaved changes
  • Navigation blocker with save/discard/stay modal

Navigation

  • Subtitle language switcher in breadcrumb (Mantine Menu dropdown)
  • Save/Discard/Cancel prompt when switching with unsaved changes
  • Save As to different language with overwrite confirmation
  • Breadcrumb navigation back to series/movie detail page

File Format Support

Parsers and serializers for: SRT, VTT, ASS/SSA, SUB (MicroDVD), SMI, MPL, TXT

Backend (API)

  • /api/editor/info — video metadata, codec info, audio tracks, available subtitles
  • /api/editor/video — direct play, remux, or transcode video streaming with seek support
  • /api/editor/audio — cached AAC audio extraction per track
  • /api/editor/peaks — waveform peak data generation
  • /api/editor/sync — ffsubsync integration via jobs queue
  • /api/editor/subtitles — list available subtitle files for media
  • /api/subtitles/content — read/write/create subtitle files with ETag support

Keyboard Shortcuts (40+)

Full shortcut sheet accessible via ? key. Includes: file ops, cue editing, timing nudge, navigation, playback, bookmarks, panels.


Quality

Check Status
TypeScript 0 errors
ESLint 0 errors, 21 warnings (pre-existing)
npm run check Pass
npm run build Pass
Frontend tests 424 passing
Backend tests 50 passing
Total tests 474

Test Breakdown

Suite Tests Coverage
document.ts (reducer) 77 Operations, undo/redo, auto-sort, QC validation, gap detection
Parsers (7 formats) 100 SRT, VTT, ASS, SUB, SMI, MPL, TXT with edge cases
Serializers (8 formats) 62 Round-trip, format-specific output, special characters
Media utils 40 formatTime, renderSubtitleHtml, codec detection, cueColor
DetailPane 27 CPS tag stripping, style buttons, wrap/insert, timing
Translate flow 19 Source toggle, reference/editor paths, MARK_DIRTY
StatusBar 19 CPS computation, display states, dirty indicator
Backend API (Python) 50 All endpoints, parameter validation, sync worker, error handling
Existing tests 80 Parsers (original), other project tests

Stats

  • 14,819 lines added across 57 files
  • 22 new frontend components/modules
  • 1 new backend API module (811 lines)
  • 8 subtitle format parsers + 8 serializers
  • 8 new test files with 474 test cases
  • 40+ keyboard shortcuts

Manual Test Plan

  • TypeScript: 0 errors (npx tsc --noEmit)
  • ESLint: 0 errors (npm run check)
  • Frontend tests: 424 passing (npx vitest run)
  • Build: clean (npm run build)
  • Open editor from series/movie subtitle action menu
  • Edit cue text, verify CPS and line length strip HTML tags
  • Add/delete/split/merge cues
  • Drag/resize cues on waveform, verify table updates and auto-sort
  • Play video, verify subtitle overlay sync
  • Switch audio tracks while playing, verify audio switches without video reload
  • Seek with seekbar, -5s/+5s buttons, Alt+Left/Right
  • Load reference subtitle, verify it follows playback position
  • AI translate from reference, verify all cues created with timing
  • AI translate from editor cues (source toggle)
  • Run ffsubsync with different VAD/GSS options
  • Switch subtitle language via breadcrumb dropdown
  • Save, Save As, verify no double modal on navigation
  • Close tab with unsaved changes, verify beforeunload warning
  • Recover from localStorage draft after page reload
  • Undo/redo timing changes, verify cue sort order maintained

LavX added 5 commits April 1, 2026 15:14
… editing tools

Phase 1 subtitle editor with inline text/timing editing, undo/redo (50-level),
search/replace with regex, and 8-format parser/serializer support (SRT, ASS/SSA,
VTT, SUB, SMI, TXT, MPL).

New features in this commit:
- Video preview with native seeking for browser-compatible codecs, remux mode
  for unsupported audio (separate audio element), and full transcode fallback
- Waveform timeline (wavesurfer.js) with draggable cue regions, zoom, and
  time-synced cursor
- Backend /api/editor/ endpoints: video streaming with FFmpeg remux/transcode,
  audio extraction with disk caching, waveform peak generation
- AI translate integration: in-editor translation via translator service API
  with progress tracking and batch apply
- QC panel with Netflix/Amazon/BBC presets and 7 batch fix tools
- Timing tools: bulk shift, linear correction (two-point fit), auto-sync
- Reference subtitle loading from existing languages or file import, with
  time-aligned matching to current cues
- Keyboard shortcut sheet, jump-to-cue, cue bookmarking, live CPS display
- Playback speed control, auto-play after seek, Ctrl+Shift+Space play/pause
- Browser codec detection with Direct/Remux/Transcode mode indicator
- ETag conflict auto-retry on save, suppressed global 412/409 notifications
- Add ffsubsync integration with VAD/GSS/framerate options in timing panel
- Fix AI translate to use loaded reference subtitles as source text
- Create cues from reference timing when translating from reference
- Add subtitle language switcher dropdown in breadcrumb navigation
- Audio track switching via separate audio element (no video reload)
- Fix waveform region event handlers after track switch re-initialization
- Action-based auto-save to localStorage (2s debounce, not 30s timer)
- Add MARK_DIRTY action for translation-created cues
- Detail pane shows empty cue form with reference when no cue selected
- Ctrl+Shift+Enter inserts cue at current playback position
- Reference text follows playback position, not selected cue
- QC markers with visible symbols instead of thin color bars
- Bookmark filter hides gap rows, button disabled when no bookmarks
- Waveform loading spinner with visible please-wait message
- Clean up status bar and toolbar badge duplication
… sort fixes

- Add seekbar, -5s/+5s buttons, Alt+Left/Right seek shortcuts
- Add text style buttons (I/B/U) and symbol insert (music, ellipsis, em dash)
- Ctrl+I/B/U keyboard shortcuts for tag wrapping in cue textarea
- CPS and line length now strip HTML tags before counting
- Translate panel: source toggle (Auto/Reference/Editor cues)
- Change Alt+T shortcut for translate panel (Ctrl+Shift+T is browser-reserved)
- Cues auto-sort by start time after timing changes
- Selected cue follows by id after re-sort
- Save As no longer triggers unsaved changes modal on navigate
- Subtitle language switcher in breadcrumb using Mantine Menu
- Gap detection minimum raised to 1 second
- Remove hero image from README
@LavX LavX changed the title feat: Subtitle Editor (LiveWire) feat: Subtitle Editor Apr 2, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dae4388d50

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Tests (424 passing, 0 failures):
- document.ts: 77 tests (operations, undo/redo, sort, QC, gaps)
- parsers: 100 tests (SRT, VTT, ASS, SUB, SMI, MPL, TXT)
- serializers: 62 tests (round-trip, format-specific output)
- DetailPane: 27 tests (CPS, tag stripping, style buttons)
- StatusBar: 19 tests (CPS computation, display states)
- translate flow: 19 tests (source toggle, cue creation)
- media utils: 40 tests (formatTime, renderSubtitleHtml, codec detection)
- backend API: 50 tests (editor endpoints, parameter validation)

Type fixes:
- Add MARK_DIRTY to DocumentAction union
- Fix useRefCues forward reference in TranslatePanel
- Fix SubtitleEditor/index.tsx data destructuring

ESLint cleanup:
- Fix import sorting across all files
- Add missing useCallback/useEffect dependencies
- Remove unused parameters and variables
- Add eslint-disable for intentional dep omissions

Code fixes from PR review:
- Save & Switch now waits for save completion instead of fixed 1s delay
@LavX LavX changed the title feat: Subtitle Editor feat: Subtitle Editor — Codename: LiveWire Apr 2, 2026
@LavX LavX changed the title feat: Subtitle Editor — Codename: LiveWire feat: Subtitle Editor Apr 2, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13d7340da4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- Mark recovered drafts as dirty (MARK_DIRTY after LOAD) so unsaved
  changes prompt appears when navigating away after recovery
- Re-throw 409/412 errors in shared HTTP client instead of silently
  swallowing them, so non-editor callers still get error notifications
- Make audio stream mapping optional in ffmpeg transcode command,
  falling back to -an for videos without audio or invalid track index
@LavX LavX merged commit d099660 into development Apr 6, 2026
4 checks passed
@LavX LavX deleted the feature/subtitle-editor branch April 6, 2026 19:09
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b38ea761db

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant