How the Output-Timeline Offset Calculation Keeps Captions Synced After Segment Concatenation in `build_master_srt`

The build_master_srt function maintains caption synchronization by converting segment-local word timestamps to global output timeline coordinates using a running seg_offset that accumulates the duration of each processed segment.

The browser-use/video-use repository handles video editing workflows where multiple source clips are concatenated into a single output. The build_master_srt function in helpers/render.py solves the critical challenge of keeping subtitles synchronized across these concatenated segments through a precise offset calculation that tracks cumulative time across edit decision list (EDL) ranges.

The Segment Offset Mechanism

When processing an edited video, build_master_srt iterates over EDL-defined segments—each specifying a start and end time from a source video. To prevent captions from overlapping or appearing at wrong timestamps in the final concatenated output, the function maintains a segment offset (seg_offset) that represents the total duration of all previously processed segments.

According to the source code in helpers/render.py (lines 15-33), this accumulator starts at zero and updates after each segment is fully processed.

Converting Local Timestamps to Global Output Timeline

The core synchronization logic occurs when converting word-level timestamps from individual segments into the global output timeline. For each caption word, the function performs a three-step transformation:

  1. Calculate the segment-relative time by subtracting the segment's start time
  2. Clamp negative values to zero using max(0.0, ...)
  3. Add the accumulated seg_offset to shift into the global timeline

This calculation appears in helpers/render.py at lines 60-64:

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

Here, local_start and local_end represent the absolute timestamps of words within the source video file, while seg_start marks the beginning of the current EDL range. Subtracting seg_start normalizes these timestamps to segment-relative coordinates (0 seconds to segment duration), and adding seg_offset maps them to the correct position in the concatenated output.

Accumulating the Segment Offset

The critical step that ensures subsequent segments start at the correct global timestamp occurs immediately after processing each segment's captions. At lines 73-74 of helpers/render.py, the function increments the offset by the current segment's duration:

seg_offset += seg_duration

This accumulation ensures that the next segment's words are shifted forward by exactly the sum of all preceding segment durations. For example, if the first segment spans 12 seconds, seg_offset becomes 12.0, causing the second segment's first word (which has a local timestamp of 0 relative to its own start) to appear at 12 seconds in the output SRT file.

Practical Example: Multi-Segment Video

Consider a video project combining two source clips:

  • Clip A: 0 seconds → 12 seconds (duration: 12.0)
  • Clip B: 12 seconds → 20 seconds (duration: 8.0)

The offset calculation processes these as follows:


# Processing Clip A (seg_offset = 0):

out_start = word.start - 0 + 0  # Results in 0-12 second range

# After Clip A, update offset:

seg_offset += 12.0  # seg_offset now equals 12.0

# Processing Clip B:

# word.start is absolute (12-20), seg_start is 12

out_start = max(0.0, word.start - 12) + 12.0  # Results in 12-20 second range

This arithmetic ensures that captions from Clip B appear exactly when Clip B begins playing in the concatenated video, maintaining perfect synchronization regardless of how many segments are combined.

Summary

  • build_master_srt generates a single SRT file synchronized to concatenated video segments defined by EDL ranges.
  • The segment offset (seg_offset) tracks cumulative duration of processed segments, initialized at lines 15-33 in helpers/render.py.
  • Timestamp conversion at lines 60-64 converts local word times to global output coordinates using max(0.0, local_start - seg_start) + seg_offset.
  • Offset accumulation at lines 73-74 updates seg_offset after each segment, ensuring subsequent captions align with the concatenated timeline.
  • This approach guarantees frame-accurate caption placement across any number of concatenated source videos.

Frequently Asked Questions

What happens if seg_offset is not updated after each segment?

If the accumulation step at lines 73-74 were skipped, every subsequent segment's captions would align to the beginning of the output timeline instead of their actual concatenated position. This would cause all captions after the first segment to appear early, potentially overlapping previous captions or appearing before their corresponding video content.

How does max(0.0, ...) handle edge cases in timestamp conversion?

The max(0.0, local_start - seg_start) guard prevents negative timestamps when a word's absolute start time precedes the EDL segment's start time. This ensures captions never begin before the output video starts, effectively clamping any out-of-bounds segment-local times to zero while preserving the offset calculation's integrity.

Can this offset calculation handle overlapping EDL segments?

The current implementation assumes sequential, non-overlapping segments where seg_offset strictly accumulates. If EDL ranges overlap, the simple addition of durations would create incorrect global timestamps, potentially causing caption duplication or temporal misalignment. The function is designed for linear concatenation workflows where segments form a continuous timeline.

Is the offset calculation frame-accurate for professional video workflows?

The calculation uses floating-point arithmetic for seg_offset and timestamp values, providing sufficient precision for standard SRT workflows (which typically use millisecond precision). However, for frame-accurate professional workflows requiring exact frame boundaries, additional rounding to frame-rate boundaries would be necessary, as the current implementation treats time as continuous seconds.

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 →