How video-use Ensures Subtitles Stay Visible During Video Rendering

Video-use guarantees subtitles are never hidden by adding them as the final filter in the FFmpeg filter-complex, forcing them to render on top of all video layers and overlays.

The browser-use/video-use repository is an open-source tool for automated video editing and composition. When rendering complex videos with multiple layers—base footage, graphics, transitions, and text overlays—subtitles risk being obscured. The codebase implements a strict architectural rule to prevent this: subtitles are always the last element composited onto the final frame.

The Two-Stage Rendering Architecture

Video-use builds videos through a deliberate two-stage process implemented in helpers/render.py. Understanding this flow explains why subtitle visibility is architecturally guaranteed.

Stage 1: Base Clip Assembly

Raw video segments are first concatenated into a continuous base timeline. This creates the foundational video stream without any overlays or text elements.

Stage 2: Sequential Filter Composition

The build_final_composite function constructs an FFmpeg filter_complex expression. Filters execute in written order, meaning each subsequent filter receives and transforms the output of the previous one. Video-use exploits this sequencing behavior strategically.

The "Subtitles LAST" Rule in build_final_composite

The critical implementation resides in helpers/render.py. The code enforces what the developers explicitly label as Rule 1: subtitles must be the final filter operation.

Step 1: Detect Subtitle Presence

has_subs = subtitles_path is not None and subtitles_path.exists()

This boolean ensures subtitles are only processed when a valid file exists, preventing FFmpeg errors from missing inputs.

Step 2: Build Overlay Filters First

Any graphical overlays, picture-in-picture elements, or additional video tracks are appended to filter_parts before subtitles are considered.

Step 3: Append Subtitles as Final Filter

filter_parts.append(
    f"{current}subtitles='{subs_abs}':force_style='{SUB_FORCE_STYLE}'[outv]"
)

The comment preceding this line reads # Subtitles LAST — Rule 1. This positioning means:

  • All prior visual elements are already baked into the frame buffer
  • The subtitles filter burns text directly onto this composite
  • No subsequent operation can obscure the rendered text

Step 4: Map Final Output

The [outv] label—output from the subtitles filter—becomes the sole video stream mapped to the final container. This completes the chain with subtitle visibility guaranteed.

Styling Subtitles for Maximum Legibility

Beyond positioning, video-use applies forced styling through SUB_FORCE_STYLE. This constant defines font family, size, outline thickness, and background properties that maintain readability across varied scene content.

Without forced styling, default subtitle renderers might choose colors that blend into the underlying video. The explicit style override ensures contrast regardless of the base footage's visual characteristics.

Command-Line Workflows for Subtitle Control

Generate and Embed Subtitles Automatically

python helpers/render.py edl.json -o final.mp4 --build-subtitles

The --build-subtitles flag triggers helpers/transcribe.py to create .srt files from transcript data, then embeds them using the LAST-rule positioning.

Render With Existing External Subtitle File

python helpers/render.py edl.json -o final.mp4

When the EDL references a subtitle path that exists on disk, the script auto-detects and applies it without additional flags.

Force Subtitle Exclusion

python helpers/render.py edl.json -o final.mp4 --no-subtitles

The --no-subtitles flag overrides EDL references, useful when producing alternate versions or when burned-in captions from the source footage are preferred.

Supporting Files in the Subtitle Pipeline

File Responsibility
helpers/render.py Orchestrates FFmpeg execution and enforces the subtitles-last filter ordering
helpers/transcribe.py Converts transcript JSON into timestamped .srt format
helpers/pack_transcripts.py Normalizes raw transcript structures for subtitle generation

These modules operate independently but converge in build_final_composite, where the architectural rule protecting subtitle visibility is ultimately enforced.

Summary

  • Subtitles are appended last in the FFmpeg filter-complex chain, preventing any overlay from obscuring them
  • The build_final_composite function in helpers/render.py implements this as an explicit architectural rule with code comments
  • force_style parameters guarantee legibility through consistent font rendering
  • CLI flags provide flexible control: auto-generation, external file use, or complete exclusion
  • The filter-complex's sequential execution model makes this protection deterministic rather than conditional

Frequently Asked Questions

What happens if I add overlays after the subtitles filter?

The code architecture prevents this. The build_final_composite function structure ensures no filters are appended after the subtitles filter. Even manual modification would violate the explicit # Subtitles LAST — Rule 1 comment that documents this invariant.

Can subtitles still be hidden by very bright video content?

The SUB_FORCE_STYLE constant includes border and shadow parameters that create contrast against any background. This styling is applied via FFmpeg's force_style option, making subtitle visibility robust against scene variations.

Does this approach work with animated or moving overlays?

Yes. The subtitles-last rule is independent of overlay motion characteristics. Whether overlays are static images or dynamic video tracks, they are processed in the filter chain before subtitle burning occurs.

Why not use separate subtitle tracks instead of burning them in?

Burned-in subtitles guarantee universal player compatibility and precise visual positioning. Video-use targets automated video production workflows where consistent presentation across platforms outweighs the flexibility of selectable text tracks.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →