# Optimizing render.py for Large-Scale Video Projects in video-use

> Optimize render.py for large video projects. Learn strategies like parallel extraction, ffprobe caching, RAM disk usage, and quick loudness normalization for efficient video rendering.

- Repository: [Browser Use/video-use](https://github.com/browser-use/video-use)
- Tags: performance
- Published: 2026-07-08

---

**To optimize [`render.py`](https://github.com/browser-use/video-use/blob/main/render.py) for large-scale video projects, parallelize segment extraction using `ThreadPoolExecutor`, cache `ffprobe` calls with `lru_cache`, utilize RAM disks for temporary files, and optionally bypass the two-pass loudness normalization with a `--quick-loudnorm` flag.**

The [`render.py`](https://github.com/browser-use/video-use/blob/main/render.py) script in the `browser-use/video-use` repository implements a deterministic **HEURISTICS** pipeline that transforms edit-decision lists (EDL) into finished videos. As projects scale from a handful of clips to hundreds or thousands of segments, the script's sequential, I/O-heavy architecture—spawning at least `N+3` FFmpeg processes for `N` segments—creates severe bottlenecks. Below are proven optimization strategies that maintain the tool's public behavior while dramatically improving throughput.

## Understanding the render.py Architecture

Before applying optimizations, it is essential to understand the five-stage pipeline defined in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py):

1. **`extract_all_segments`** → **`extract_segment`**: Cuts each range, applies colour-grading (auto or preset), HDR-to-SDR tone-mapping, 30ms audio fades, and rescales to target resolution.
2. **`concat_segments`**: Performs lossless concatenation via the FFmpeg *concat demuxer* (`-c copy`).
3. **`build_master_srt`** (optional): Builds subtitle overlays.
4. **`build_final_composite`**: Applies picture-shifted overlays and burns subtitles.
5. **`apply_loudnorm_two_pass`**: Runs two-pass loudness normalization (unless `--no-loudnorm` is passed).

For a project with 1,000 segments, this workflow spawns over 1,003 subprocesses sequentially. The following strategies address this linear execution penalty.

## Parallelize Per-Segment Extraction

The `extract_all_segments` function processes segments one after another, making it the primary bottleneck. Since each segment operates on an independent source file and writes to its own temporary MP4, this step is *embarrassingly parallel*.

Replace the sequential loop with a `ThreadPoolExecutor` to saturate multi-core CPUs:

```python
from concurrent.futures import ThreadPoolExecutor, as_completed
import os

def _extract_one(i, r, sources, edit_dir, preview, draft):
    src_name = r["source"]
    src_path = resolve_path(sources[src_name], edit_dir)
    start = float(r["start"])
    end = float(r["end"])
    duration = end - start
    out_path = edit_dir / f"clips_{'draft' if draft else ('preview' if preview else 'graded')}"
    out_path = out_path / f"seg_{i:02d}_{src_name}.mp4"

    # Auto-grade handling (identical to original implementation)

    seg_filter = (
        auto_grade_for_clip(src_path, start=start, duration=duration, verbose=False)[0]
        if is_auto else resolved
    )
    extract_segment(src_path, start, duration, seg_filter,
                    out_path, preview=preview, draft=draft)
    return out_path

def extract_all_segments(edl, edit_dir, preview, draft=False):
    resolved = resolve_grade_filter(edl.get("grade"))
    is_auto = resolved == "__AUTO__"
    clips_dir = edit_dir / (
        "clips_draft" if draft else ("clips_preview" if preview else "clips_graded")
    )
    clips_dir.mkdir(parents=True, exist_ok=True)

    ranges = edl["ranges"]
    sources = edl["sources"]
    seg_paths = []

    with ThreadPoolExecutor(max_workers=os.cpu_count()) as ex:
        futures = {
            ex.submit(_extract_one, i, r, sources, edit_dir, preview, draft): i
            for i, r in enumerate(ranges)
        }
        for fut in as_completed(futures):
            seg_paths.append(fut.result())

    # Preserve original order (optional)

    seg_paths.sort(key=lambda p: int(p.stem.split('_')[1]))
    return seg_paths

```

**Why this works:** FFmpeg handles the heavy lifting (decoding, filtering, re-encoding) in multi-threaded C code. Running multiple FFmpeg processes in parallel via Python threads fully utilizes CPU resources and eliminates the linear wait time of the original loop.

## Cache Repeated FFprobe Calls

The pipeline invokes `ffprobe` twice per unique source: once for HDR detection (`is_hdr_source`) and once for loudness measurement (`measure_loudness`). In projects reusing the same source files across multiple segments, these calls duplicate identical work.

Apply `functools.lru_cache` to reduce subprocess overhead from **O(N)** to **O(unique-sources)**:

```python
from functools import lru_cache
from pathlib import Path

@lru_cache(maxsize=256)
def is_hdr_source(video: Path) -> bool:
    # Existing ffprobe logic preserved

    ...

@lru_cache(maxsize=256)
def measure_loudness(video_path: Path) -> dict[str, str] | None:
    # Existing loudness measurement logic preserved

    ...

```

The cache keys results by the absolute file path, ensuring that subsequent segments referencing the same source file reuse the previous probe result without spawning new subprocesses.

## Minimize Disk I/O with RAM Disks

Intermediate segment files (`*.mp4`) dominate the temporary storage footprint and create significant read/write latency. On Linux systems with ample RAM, mount a RAM disk (e.g., `/dev/shm`) and point the `edit_dir` there to eliminate physical disk thrashing.

```bash
export TMPDIR=/dev/shm/video-use
python helpers/render.py my_project.edl.json -o final.mp4

```

[`render.py`](https://github.com/browser-use/video-use/blob/main/render.py) respects the working directory derived from the EDL location, so no code modification is required. The environment variable simply redirects temporary directories to high-speed memory.

## Optimize the Concatenation Strategy

By default, `concat_segments` uses the FFmpeg *concat demuxer* with `-c copy` to create an intermediate `base.mp4`. If **all segments share identical resolution, pixel format, and codec**, you can bypass this separate step and concatenate directly within a single FFmpeg filter graph, eliminating one full encode/decode cycle and the temporary `base.mp4` file.

```bash
ffmpeg -y \
  -i seg_00.mp4 -i seg_01.mp4 -i seg_02.mp4 \
  -filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" -c:v libx264 -preset fast -crf 20 final.mp4

```

**Note:** When the EDL contains mixed codecs or resolutions, retain the lossless concat demuxer approach to avoid generation loss.

## Streamline Loudness Normalization

The `apply_loudnorm_two_pass` function adds a full render pass for loudness measurement followed by the actual normalization. For large projects where perfect loudness compliance is less critical than turnaround time, expose a `--quick-loudnorm` flag that uses the one-pass mode already implemented for `--preview` mode.

```python
ap.add_argument(
    "--quick-loudnorm",
    action="store_true",
    help="Use one-pass loudnorm (faster, slightly less accurate)."
)

# Inside main():

if args.quick_loudnorm:
    apply_loudnorm_two_pass(tmp_composite, out_path, preview=True)
else:
    apply_loudnorm_two_pass(tmp_composite, out_path, preview=args.draft)

```

This skips the expensive `measure_loudness` call and the associated `ffprobe` subprocess, cutting the final processing stage in half.

## Tune FFmpeg Threading Parameters

While FFmpeg defaults to automatic thread detection, explicit tuning can improve performance on high-core-count workstations or when processing 4K sources. Pass `-threads 0` (auto-detect) or a specific value through `extract_segment` and the final composite call:

```python
cmd = [
    "ffmpeg", "-y", "-threads", "0",
    "-ss", f"{seg_start:.3f}",
    # ... remaining arguments

]

```

This ensures FFmpeg fully utilizes available CPU resources during the encode/decode phases within each segment processing task.

## Summary

- **Parallelize extraction** using `ThreadPoolExecutor` in `extract_all_segments` to eliminate the sequential processing bottleneck.
- **Cache probe results** with `lru_cache` on `is_hdr_source` and `measure_loudness` to reduce redundant `ffprobe` subprocesses.
- **Use RAM disks** by setting `TMPDIR` to `/dev/shm` to minimize disk I/O latency for temporary MP4 files.
- **Batch concatenation** via FFmpeg filter graphs (when codec uniformity allows) to skip the intermediate lossless concat file.
- **Skip two-pass loudnorm** by implementing `--quick-loudnorm` for faster, single-pass audio normalization.
- **Tune threading** with explicit `-threads` parameters to maximize CPU utilization per FFmpeg process.

## Frequently Asked Questions

### Does parallel extraction affect video quality?

No. Parallel extraction preserves the exact same FFmpeg command arguments and filter graphs used in the sequential version. Each segment is rendered independently to its own temporary file, so there is no risk of cross-contamination or quality degradation. The final concatenation step remains identical, ensuring bit-exact output compared to the original sequential implementation.

### How much RAM do I need for the RAM disk optimization?

Allocate enough space to hold all intermediate segment files simultaneously. For a 1080p project with 1,000 segments averaging 50MB each, approximately 50GB of free RAM is required. If physical memory is constrained, use the parallel extraction optimization instead, as the RAM disk strategy is only beneficial when the working set fits entirely in memory without swapping.

### Can I use these optimizations with preview mode?

Yes. The `preview` flag in `extract_all_segments` triggers lower-resolution processing that benefits even more from parallelization due to reduced per-segment processing time. The `--quick-loudnorm` flag is particularly effective in preview mode, as it uses the existing one-pass loudness logic intended for draft renders, providing nearly instant feedback on audio levels.

### Why does the batch concatenation strategy require identical codecs?

The batch concatenation strategy uses FFmpeg's `concat` filter, which decodes all inputs, concatenates them in the filter graph, and then re-encodes the output. If inputs have different codecs, resolutions, or pixel formats, the filter graph fails or requires complex normalization filters. The default concat demuxer (`-c copy`) avoids re-encoding by stream copying, which is safer for heterogeneous EDLs but requires the intermediate file. Use batch concatenation only when your entire EDL uses uniform export settings from [`helpers/grade.py`](https://github.com/browser-use/video-use/blob/main/helpers/grade.py).