Skip to content

fix: make subtitle burn-in diagnosable and multilingual - #120

Open
mvanhorn wants to merge 5 commits into
browser-use:mainfrom
mvanhorn:fix/118-subtitle-burn-in
Open

fix: make subtitle burn-in diagnosable and multilingual#120
mvanhorn wants to merge 5 commits into
browser-use:mainfrom
mvanhorn:fix/118-subtitle-burn-in

Conversation

@mvanhorn

@mvanhorn mvanhorn commented Aug 5, 2026

Copy link
Copy Markdown

Subtitle burn-in currently reaches the final compositing pass before discovering that the selected ffmpeg lacks the libass-backed subtitles filter, so the documented default Homebrew installation wastes the earlier render work and ends in an opaque CalledProcessError. The same path always forces Helvetica, which prevents a project from selecting a font with glyph coverage for CJK and other non-Latin scripts. The EDL and skill documentation expose a subtitle file but no font override, despite describing subtitle styling as customizable. The issue also proposes language-aware cue chunking, but that distinct segmentation behavior is outside this plan's explicitly declared partial scope.

Summary by cubic

Add a production-used ffmpeg capability check in helpers/render.py and run it before segment extraction whenever the requested render will burn an existing EDL subtitle file or build subtitles, while preserving --no-subtitles and subtitle-free renders; on failure, exit cleanly with the missing-libass diagnosis and installation/PATH guidance. Replace the fixed font portion of the force style with an EDL-level subtitle_font override that retains the current Helvetica default and all proven geometry, color, and safe-zone values, then pass the resolved style through the existing final-composite call path. Document the new EDL field and require projects with non-Latin captions to choose an installed, script-compatible font rather than relying on a platform-specific global default.

Test

  • A render using --build-subtitles with an ffmpeg filter listing that lacks an exact subtitles entry exits before segment extraction and reports that a libass-enabled ffmpeg is required, including actionable macOS PATH guidance rather than a traceback.
  • An EDL that points to an existing subtitle file performs the same preflight, while --no-subtitles, an EDL with no subtitle request, and an EDL whose configured subtitle file is absent retain their current skip/warning behavior without requiring libass.
  • A filter listing containing the real subtitles filter passes capability detection without being confused by unrelated text, and a failed ffmpeg capability probe produces the same controlled diagnostic.
  • An EDL without subtitle_font produces the existing Helvetica force style byte-for-byte, preserving FontSize, bolding, colors, alignment, and MarginV=90.
  • An EDL with a spaced non-Latin-capable font name such as Heiti SC changes only FontName in the final subtitles filter and leaves overlay ordering, subtitle path escaping, and all other style fields intact.
  • Documentation examples keep the README quick start, install.md, and the EDL contract in SKILL.md consistent about libass availability, ffmpeg-full PATH precedence, and per-project font selection.

Closes #118


Summary by cubic

Fail‑fast, multilingual subtitle burn‑in. Previously, burn‑in failed late at final compositing with an opaque error and always forced Helvetica; now we preflight ffmpeg for libass and allow an EDL subtitle_font override. Subtitle‑free renders are unchanged.

  • Preflights the selected ffmpeg for an exact subtitles filter before extraction when burn‑in will occur (including --build-subtitles); on failure, exits cleanly with install/PATH guidance for macOS (brew install ffmpeg-full, put it first on PATH, verify with ffmpeg -hide_banner -filters | grep -w subtitles).
  • Keeps skip/warn behavior for --no-subtitles, EDLs without subtitles, and missing subtitle files; no libass required in those modes.
  • Adds EDL subtitle_font; validates only when burn‑in is active and exits cleanly on invalid values (rejects non‑strings and commas, apostrophes, backslashes, or control characters to prevent force_style injection). Default remains Helvetica with existing colors and geometry (MarginV=90); only FontName changes.
  • Passes the resolved style into final compositing; overlay ordering and path escaping are preserved.
  • Updates docs (README.md, SKILL.md, install.md) with the capability check, PATH precedence for ffmpeg-full, and guidance to set subtitle_font for non‑Latin captions.
  • Adds focused tests for capability detection, early exit paths, and style/override propagation.

Closes #118

Written for commit a05bd95. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread helpers/render.py Outdated
A font name containing a comma, apostrophe, backslash, or control
character could terminate the force_style argument or inject extra ASS
style fields. Reject those up front and cover it with a regression test.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread helpers/render.py
Only validate the EDL subtitle_font override when subtitles are actually
burned in, so --no-subtitles or a missing EDL subtitles path no longer
fails on a field that will not be used.

Convert the ValueError into a SystemExit so an invalid font override
prints a message instead of a traceback, matching the existing libass
check.
@mvanhorn

mvanhorn commented Aug 8, 2026

Copy link
Copy Markdown
Author

Both flagged, thanks. Handling them separately since one was already closed out:

The force_style injection (helpers/render.py:61) was fixed in 07a4433 - the override now rejects commas, apostrophes, backslashes, and control characters before interpolation, so a font name can no longer terminate the filter argument or add ASS style fields.

The second one is fair and is fixed in 591beac. Two problems, both real:

  • The validation ran unconditionally, so an EDL carrying a subtitle_font could fail a --no-subtitles render over a field that would never be used. It is now gated on subs_path, which already accounts for --no-subtitles and for an EDL subtitles path that is missing.
  • The ValueError was uncaught and surfaced as a traceback. It is now a SystemExit with the message inline, matching the pattern the libass check already uses.

Existing render tests still pass.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread helpers/render.py Outdated
A bad font config now fails before the expensive render work, gated on
actual burn-in intent so --no-subtitles never trips on it.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread helpers/render.py
Implemented the remaining review fix.
- Non-string `subtitle_font` values now raise a clean validation error before extraction: [helpers/render.py](/Users/mvanhorn/.osc/workspaces/browser-use-video-use-pr120/helpers/render.py:59)
- Added helper and preflight regression coverage: [tests/test_render.py](/Users/mvanhorn/.osc/workspaces/browser-use-video-use-pr120/tests/test_render.py:177)
### CODEX STATUS
- **PASS:** 13 focused tests.
- **PASS:** Scoped Ruff checks and `git diff --check`.
- **PASS:** Black check for the modified tests.
- **BASELINE_BLOCKED:** Full Ruff/Black checks encounter existing unrelated issues in `helpers/render.py`.
@mvanhorn

Copy link
Copy Markdown
Author

Fixed. Non-string subtitle_font values now raise a clean validation error before extraction rather than failing later, with regression coverage for both the helper and the preflight path.

13 focused tests pass, plus scoped Ruff and Black on the touched files.

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.

Subtitle burn-in is broken two ways: crashes on a documented macOS install, and renders tofu for non-Latin scripts

1 participant