Skip to content

Fix subtitle burn-in: Homebrew's ffmpeg formula lacks libass - #133

Open
businessadam wants to merge 1 commit into
browser-use:mainfrom
businessadam:fix/ffmpeg-libass-subtitles
Open

Fix subtitle burn-in: Homebrew's ffmpeg formula lacks libass#133
businessadam wants to merge 1 commit into
browser-use:mainfrom
businessadam:fix/ffmpeg-libass-subtitles

Conversation

@businessadam

@businessadam businessadam commented Aug 18, 2026

Copy link
Copy Markdown

Summary

On macOS, plain brew install ffmpeg (what install.md currently tells every agent to run) ships without libass, so the subtitles filter doesn't exist in that build at all. Since Hard Rule 1 (subtitles burned in last, after every overlay) depends entirely on that filter, any render that burns captions fails — but only when it gets to that step, deep into a render, not at install time where it'd be cheap to catch.

ffmpeg-full (also in homebrew-core) is a superset build that includes libass. This PR:

  • Checks for the subtitles filter first (ffmpeg -h filter=subtitles) before doing anything, so machines that already have a libass-enabled ffmpeg (common on Linux — apt/pacman both build with libass by default) aren't affected.
  • Falls back to brew install ffmpeg-full && brew link --overwrite ffmpeg-full only when the filter is missing.
  • Adds a verification line at the end of install.md's end-to-end check so this surfaces immediately on install rather than during someone's first real render.
  • Updates the manual-install path in README.md to match.

Found this the hard way while rendering vertical clips with burned captions — ffmpeg ran without error but silently had no subtitles filter registered.

Test plan

  • Confirmed plain brew install ffmpeg on macOS (Homebrew core formula) has no libass/subtitles filter (ffmpeg -h filter=subtitlesUnknown filter 'subtitles')
  • Confirmed ffmpeg-full has it (ffmpeg -h filter=subtitlesFilter subtitles / Render text subtitles onto input video using the libass library.)
  • brew link --overwrite ffmpeg-full correctly repoints the global ffmpeg/ffprobe symlinks
  • Burned a real 2-word subtitle onto a rendered clip afterward and confirmed it rendered correctly

Summary by cubic

Fixes subtitle burn-in on macOS by ensuring ffmpeg includes libass. Previously, Homebrew’s default ffmpeg lacked the subtitles filter, so caption burn-in failed late in renders; we now detect this early and install/link ffmpeg-full when needed.

  • macOS install now checks ffmpeg -h filter=subtitles; if missing, runs brew install ffmpeg-full and brew link --overwrite ffmpeg-full.
  • Adds an install verification step that confirms the subtitles filter is present so issues surface at setup, not during a render.
  • Updates manual install in README.md to use brew install ffmpeg-full plus a link step.
  • Notes for Linux distros: default packages usually include libass, but we document how to verify.
  • Side effect: linking ffmpeg-full updates system-wide ffmpeg/ffprobe symlinks; it’s a superset of ffmpeg.
  • Migration: macOS developers with an existing Homebrew ffmpeg should rerun the install step or manually brew install ffmpeg-full && brew link --overwrite ffmpeg-full.

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

Review in cubic

Plain `brew install ffmpeg` on macOS ships without libass, so the
`subtitles` filter doesn't exist at all — Hard Rule 1 (captions burned
in) fails deep into a render instead of at install time, where it's
much cheaper to catch.

`ffmpeg-full` includes libass. install.md and README.md now check for
the `subtitles` filter first and only install/link ffmpeg-full if it's
missing, plus a verification line at the end of install so this shows
up immediately rather than during someone's first real render.

@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.

2 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="README.md">

<violation number="1" location="README.md:63">
P2: The manual-install path unconditionally runs `brew link --overwrite ffmpeg-full`, which replaces the global `ffmpeg`/`ffprobe` symlinks system-wide on every machine, even ones whose existing ffmpeg already has libass. This contradicts the PR's stated design — install.md (in the same PR) guards this with `if ! ffmpeg -h filter=subtitles 2>&1 | grep -q "Filter subtitles"` and only falls back to ffmpeg-full when the filter is missing, and notes the relink is a system-wide change to surface to the user. Make the README path match so a working libass-enabled ffmpeg isn't silently overwritten.</violation>
</file>

<file name="install.md">

<violation number="1" location="install.md:142">
P2: When the `subtitles` filter is missing, `grep -q` finds no match and the `&& echo` is skipped, so this final verify line prints nothing on failure. The agent sees the two preceding `` OK`` lines and no error, so the missing-libass install failure stays silent — the exact outcome this PR sets out to prevent. Make the failure explicit with a `||` branch that prints a clear message and, ideally, exits non-zero.</violation>
</file>

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

Fix all with cubic | Re-trigger cubic

Comment thread README.md
cd ~/Developer/video-use
uv sync # or: pip install -e .
brew install ffmpeg # required
brew install ffmpeg-full # required — plain `ffmpeg` lacks libass, so

@cubic-dev-ai cubic-dev-ai Bot Aug 18, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The manual-install path unconditionally runs brew link --overwrite ffmpeg-full, which replaces the global ffmpeg/ffprobe symlinks system-wide on every machine, even ones whose existing ffmpeg already has libass. This contradicts the PR's stated design — install.md (in the same PR) guards this with if ! ffmpeg -h filter=subtitles 2>&1 | grep -q "Filter subtitles" and only falls back to ffmpeg-full when the filter is missing, and notes the relink is a system-wide change to surface to the user. Make the README path match so a working libass-enabled ffmpeg isn't silently overwritten.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 63:

<comment>The manual-install path unconditionally runs `brew link --overwrite ffmpeg-full`, which replaces the global `ffmpeg`/`ffprobe` symlinks system-wide on every machine, even ones whose existing ffmpeg already has libass. This contradicts the PR's stated design — install.md (in the same PR) guards this with `if ! ffmpeg -h filter=subtitles 2>&1 | grep -q "Filter subtitles"` and only falls back to ffmpeg-full when the filter is missing, and notes the relink is a system-wide change to surface to the user. Make the README path match so a working libass-enabled ffmpeg isn't silently overwritten.</comment>

<file context>
@@ -60,7 +60,8 @@ ln -sfn ~/Developer/video-use ~/.claude/skills/video-use        # Claude Code
 cd ~/Developer/video-use
 uv sync                         # or: pip install -e .
-brew install ffmpeg             # required
+brew install ffmpeg-full        # required — plain `ffmpeg` lacks libass, so
+brew link --overwrite ffmpeg-full   # subtitle burn-in (Hard Rule 1) silently breaks
 brew install yt-dlp             # optional, for downloading online sources
</file context>
Fix with cubic

Comment thread install.md
```bash
python ~/Developer/video-use/helpers/timeline_view.py --help >/dev/null && echo "helpers OK"
ffprobe -version | head -1
ffmpeg -h filter=subtitles 2>&1 | grep -q "Filter subtitles" && echo "libass OK (subtitles filter present)"

@cubic-dev-ai cubic-dev-ai Bot Aug 18, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: When the subtitles filter is missing, grep -q finds no match and the && echo is skipped, so this final verify line prints nothing on failure. The agent sees the two preceding OK lines and no error, so the missing-libass install failure stays silent — the exact outcome this PR sets out to prevent. Make the failure explicit with a || branch that prints a clear message and, ideally, exits non-zero.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At install.md, line 142:

<comment>When the `subtitles` filter is missing, `grep -q` finds no match and the `&& echo` is skipped, so this final verify line prints nothing on failure. The agent sees the two preceding `` OK`` lines and no error, so the missing-libass install failure stays silent — the exact outcome this PR sets out to prevent. Make the failure explicit with a `||` branch that prints a clear message and, ideally, exits non-zero.</comment>

<file context>
@@ -132,6 +139,7 @@ Run one real thing. Prefer the lightest verification that still proves the pipel
 ```bash
 python ~/Developer/video-use/helpers/timeline_view.py --help >/dev/null && echo "helpers OK"
 ffprobe -version | head -1
+ffmpeg -h filter=subtitles 2>&1 | grep -q "Filter subtitles" && echo "libass OK (subtitles filter present)"

</file context>


</details>

```suggestion
ffmpeg -h filter=subtitles 2>&1 | grep -q "Filter subtitles" && echo "libass OK (subtitles filter present)" || { echo "ERROR: ffmpeg lacks the subtitles filter (no libass). Install ffmpeg-full."; exit 1; }
Fix with cubic

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