How Output-Timeline Subtitle Offsets Are Calculated in the video-use Master SRT Builder

In the browser-use/video-use repository, subtitle offsets are calculated by mapping segment-relative word timings to global output positions using the formula max(0.0, local_start - seg_start) + seg_offset, where seg_offset accumulates the total duration of all previously processed segments.

The master SRT builder transforms per-source transcript timings into a seamless timeline that matches the final edited video. Understanding how output-timeline subtitle offsets are calculated is critical for debugging synchronization issues or extending the caption generation pipeline.

The Core Offset Formula

The build_master_srt function in helpers/render.py implements a precise mathematical transformation that translates local word timestamps into global cue positions.

Segment-Relative to Global Timeline

For each caption chunk, the code computes output timestamps as follows:

out_start = max(0.0, local_start - seg_start) + seg_offset
out_end   = max(0.0, local_end   - seg_start) + seg_offset

Variable definitions:

  • local_start and local_end: The absolute start and end times of the word chunk within the original source file, clamped to the segment's bounds (lines 60-64).
  • seg_start: The start time of the current segment in the source timeline as specified by the EDL (Edit Decision List) entry.
  • seg_offset: A running total representing the cumulative duration of all previously processed segments, initialized at 0.0 and incremented by seg_duration after each segment (lines 26-27, 73).

The subtraction local_start - seg_start calculates the relative position of the word within its segment. Adding seg_offset shifts this value into the global output timeline, ensuring that earlier segments contribute their full duration to subsequent cue positions.

The Processing Pipeline

The offset calculation occurs within a six-stage pipeline that transforms source transcripts into the final SRT file.

1. Source Transcript Loading

For every cut segment defined in the EDL, the system loads the corresponding transcript JSON from transcripts_dir / f"{src_name}.json".

2. Word Range Selection

The _words_in_range helper function (lines 300-311) filters the transcript to include only words that fall within the segment's time boundaries.

3. Word Chunking

Selected words are grouped into 2-word chunks (or smaller units if punctuation appears), creating the caption text blocks that will appear in the output (lines 444-457).

4. Cue Duration Enforcement

The code ensures a minimal cue length of 0.4 seconds. If out_end <= out_start, the end timestamp is automatically extended forward to maintain readability (lines 65-66).

5. Timestamp Formatting

The _srt_timestamp function (lines 92-98) converts floating-point second counts into standard SRT format (HH:MM:SS,mmm).

6. Final Assembly

The resulting list of (out_start, out_end, text) tuples is sorted by start time (line 76) and written to disk in standard SRT format (lines 78-84).

Practical Implementation Examples

Generating a Master SRT for an Edited Timeline

from pathlib import Path
import json
from helpers.render import build_master_srt

# Assume `edl` is the Edit Decision List produced by the LLM

# and `edit_dir` points at the directory where segment files live.

edl_path = Path("edit/edl.json")
edit_dir = Path("edit")
out_srt = Path("edit/master.srt")

with edl_path.open() as f:
    edl = json.load(f)

build_master_srt(edl, edit_dir, out_srt)
print(f"✅ Master subtitles written to {out_srt}")

Manual Offset Calculation

def cue_offset(seg_start, seg_offset, chunk_start, chunk_end):
    # chunk_* are absolute timestamps from the source transcript

    out_start = max(0.0, chunk_start - seg_start) + seg_offset
    out_end   = max(0.0, chunk_end   - seg_start) + seg_offset
    return out_start, out_end

# Segment starts at 30.0 s in the source, has already contributed 45.2 s to the output.

seg_start  = 30.0
seg_offset = 45.2
chunk_start = 31.4   # word begins at 31.4 s in the source

chunk_end   = 31.9   # word ends at 31.9 s in the source

print(cue_offset(seg_start, seg_offset, chunk_start, chunk_end))

# → (46.6, 47.1) seconds in the final video timeline

Converting Seconds to SRT Format

from helpers.render import _srt_timestamp

# Example: first cue after processing

start_sec = 12.345   # seconds in the final video

end_sec   = 12.845
print(_srt_timestamp(start_sec), "-->", _srt_timestamp(end_sec))

# → 00:00:12,345 --> 00:00:12,845

Summary

  • Offset calculation: Output timestamps derive from max(0.0, local_time - seg_start) + seg_offset, combining segment-relative positioning with cumulative duration tracking.
  • Core implementation: The logic resides in helpers/render.py, specifically within build_master_srt, _words_in_range, and _srt_timestamp.
  • Cumulative tracking: The seg_offset variable accumulates the total duration of processed segments, ensuring seamless timeline continuity across cuts.
  • Chunk processing: Words are grouped into 2-word captions before offset calculation, with automatic extension for cues shorter than 0.4 seconds.
  • Code references: Critical calculations occur at lines 26-27, 60-66, 73, 76, 78-84, 92-98, 300-311, and 444-457 in helpers/render.py.

Frequently Asked Questions

What prevents negative timestamps when a word appears slightly before the segment start?

The max(0.0, local_start - seg_start) expression ensures that even if boundary clamping places a word near the segment edge, the calculation never produces negative values. This safeguard maintains valid SRT formatting while preserving the intended synchronization (lines 60-64).

How does the system handle time gaps between non-consecutive segments?

The seg_offset variable maintains a running total of all previous segment durations. When processing transitions to a new segment, this offset increments by the previous segment's duration (lines 26-27, 73), effectively compressing the source timeline and eliminating gaps so the output matches the edited video flow.

Can the default 2-word chunking strategy be modified?

The current implementation in helpers/render.py (lines 444-457) groups words into 2-word chunks with punctuation-based early breaks. While the code does not expose a configuration parameter for chunk size, developers can modify the grouping logic within build_master_srt to adjust caption density or maximum character limits.

Why is a minimum cue length of 0.4 seconds enforced?

The 0.4-second minimum ensures that subtitle cues remain readable and valid according to standard SRT specifications. When word boundaries produce out_end <= out_start, the code automatically extends the end timestamp by 0.4 seconds to prevent zero-duration or invalid cues (lines 65-66).

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 →