# How to Generate SRT Subtitles with Offset Timelines After Segment Concatenation in Video-Use

> Learn how video-use generates SRT subtitles with offset timelines after segment concatenation. Discover the seg_offset variable and build_master_srt function for accurate timestamp shifting.

- Repository: [Browser Use/video-use](https://github.com/browser-use/video-use)
- Tags: how-to-guide
- Published: 2026-07-05

---

**Video-use accumulates segment durations into a running `seg_offset` variable to shift transcript timestamps onto the final concatenated timeline, outputting a master SRT file via the `build_master_srt` function in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py).**

The `browser-use/video-use` repository provides a complete pipeline for extracting video segments, concatenating them, and generating accurate SRT subtitles that reflect the final output timeline. When multiple clips are stitched together, the subtitles must account for the cumulative duration of preceding segments to maintain synchronization. This article explains the exact mechanism used to calculate these offsets and produce the master subtitle file.

## The Subtitle Generation Pipeline

The entire process is orchestrated by the **`build_master_srt`** function located in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) at line 315. This routine is invoked automatically when you pass the `--build-subtitles` flag to the render script. It processes an Edit Decision List (EDL) to determine which segments appear in the final video and adjusts all subtitle timestamps accordingly.

### Parsing the Edit Decision List (EDL)

The function iterates over the `ranges` array in the EDL JSON file. Each range represents one extracted clip with a specific start and end time from a source video:

```python
for r in edl["ranges"]:
    src_name = r["source"]
    seg_start = float(r["start"])
    seg_end   = float(r["end"])
    seg_duration = seg_end - seg_start

```

During this iteration, the code maintains a **`seg_offset`** variable initialized to `0.0` at line 326. This accumulator tracks the total duration of all previously processed segments.

### Accumulating Segment Offsets

The offset accumulation happens immediately after processing each range. Even if a segment lacks a transcript, the offset increases to ensure subsequent subtitles align correctly with the concatenated timeline. As implemented in the source code at line 326, the offset preserves the exact position of each clip within the final output.

### Loading and Filtering Transcripts

For each EDL range, the system attempts to load a transcript JSON file from `edit_dir/transcripts/<source>.json`. If the file is missing, the range is skipped, but `seg_offset` is still incremented to maintain timeline integrity (line 335).

When a transcript exists, the helper function **`_words_in_range`** (line 300) scans the word-level timing data to select only those utterances that fall within the current segment's boundaries:

```python
words = _words_in_range(transcript, seg_start, seg_end)

```

### Chunking and Timestamp Shifting

Selected words are grouped into caption chunks of at most two words, breaking early on punctuation marks defined by `PUNCT_BREAK` (line 443). This creates readable captions that align with natural speech pauses.

The critical offset calculation occurs at line 562. For each word chunk, the code first determines the local time relative to the source segment, then shifts it by the cumulative `seg_offset`:

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

```

This math ensures that `out_start` and `out_end` represent absolute positions on the final concatenated video timeline, not the original source timestamps.

### Formatting and Writing the SRT File

The helper **`_srt_timestamp`** (line 292) converts floating-point second counts into the standard `HH:MM:SS,mmm` format required by the SRT specification. After processing all EDL ranges, the complete subtitle entries are sorted by start time and written to `edit_dir/master.srt` (line 776).

## Code Implementation Details

The offset logic relies on precise arithmetic to handle edge cases such as segments starting mid-sentence. The `max(0.0, ...)` guard prevents negative timestamps while the `seg_offset` accumulator ensures continuity across clip boundaries.

Here is the core timestamp transformation as implemented in the source:

```python

# seg_offset accumulates the duration of all previous segments

seg_offset = 0.0

for r in edl["ranges"]:
    # ... load transcript and get words ...

    
    for chunk in word_chunks:
        local_start = chunk[0]["start"]
        local_end   = chunk[-1]["end"]
        
        # Shift from source-relative to output-relative time

        out_start = max(0.0, local_start - seg_start) + seg_offset
        out_end   = max(0.0, local_end   - seg_start) + seg_offset
        
        # Convert to SRT format

        start_ts = _srt_timestamp(out_start)
        end_ts   = _srt_timestamp(out_end)

```

The `SUB_FORCE_STYLE` constant defined at line 41 in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) specifies the default subtitle appearance (font, size, margins) when the SRT is later burned into the video using ffmpeg.

## Command-Line Usage

To generate the offset-adjusted subtitle file during rendering, invoke the script with the `--build-subtitles` flag:

```bash

# Render video and generate master.srt with corrected timelines

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

```

This command processes the EDL, calculates all offsets, and deposits `master.srt` in the `edit_dir` directory.

To inspect the generated file:

```srt
1
00:00:00,000 --> 00:00:02,400
THIS IS

2
00:00:02,400 --> 00:00:04,800
AN EXAMPLE

3
00:00:04,800 --> 00:00:05,600
OF CAPTION

```

Notice that the timestamps reflect the concatenated timeline—the second cue starts at 00:00:02,400 because the first segment had a duration of 2.4 seconds.

To burn these subtitles into the final video with the forced style:

```bash
ffmpeg -i base.mp4 \
  -vf "subtitles='edit/master.srt':force_style='FontName=Helvetica,FontSize=18,Bold=1,MarginV=90'" \
  -c:a copy final_with_subs.mp4

```

## Summary

- **Offset Accumulation**: The `seg_offset` variable tracks cumulative segment duration to align subtitles with the concatenated output timeline.
- **Core Function**: `build_master_srt` in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) (line 315) orchestrates the entire pipeline.
- **Timestamp Math**: Each cue's start and end times are shifted by `seg_offset` after being normalized to the segment start (line 562).
- **Input Data**: Per-source transcripts are loaded from `edit_dir/transcripts/<source>.json` and filtered by the `_words_in_range` helper.
- **Output**: A single `master.srt` file containing chronologically sorted, offset-corrected captions ready for ffmpeg overlay.

## Frequently Asked Questions

### What happens if a video segment has no transcript file?

If the expected JSON transcript is missing from `edit_dir/transcripts/`, the range is skipped without generating subtitles, but `seg_offset` is still increased by the segment duration (line 335). This ensures that subsequent subtitles remain synchronized with the video timeline even when gaps exist in the transcript coverage.

### How does the system handle words that span across segment boundaries?

The `_words_in_range` function (line 300) selects words whose temporal intervals overlap the segment's start and end times. When a word is split across segments, it appears only in the segment where its start time falls, ensuring no duplicate captions while maintaining the offset continuity through the `seg_offset` accumulator.

### Can I adjust the number of words per caption line?

Yes, the chunking logic in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) groups words into captions of at most two words by default (line 443). You can modify the chunking parameters or the `PUNCT_BREAK` logic in the source to allow longer lines, though this requires editing the `_chunk_words` implementation directly.

### Why are my subtitles appearing at the wrong time in the final video?

Incorrect timing usually indicates that `seg_offset` was not properly accumulated, which happens if the EDL ranges are processed out of order or if segment durations are miscalculated. Ensure that your [`edl.json`](https://github.com/browser-use/video-use/blob/main/edl.json) contains correct `start` and `end` values for each range, and verify that `--build-subtitles` was used during rendering to trigger the offset calculation logic.