# How the video-use Rendering Pipeline Manages and Cleans Up Temporary Files

> Discover how the video-use rendering pipeline efficiently manages and cleans temporary files. Learn about unlink() calls and TemporaryDirectory for deterministic cleanup.

- Repository: [Browser Use/video-use](https://github.com/browser-use/video-use)
- Tags: internals
- Published: 2026-06-30

---

**The video-use rendering pipeline creates short-lived temporary files during audio envelope extraction, frame extraction, and video composition, ensuring deterministic cleanup through explicit `unlink()` calls in `finally` blocks and context-managed `TemporaryDirectory` objects.**

The browser-use/video-use repository processes edit-decision lists (EDLs) through a multi-stage rendering pipeline that generates transient artifacts for timeline visualization and final output. Understanding how temporary files are managed and cleaned up by the rendering pipeline is essential for preventing disk pollution and ensuring robust error handling. The implementation guarantees that no stray files remain on disk, even when FFmpeg subprocesses fail or exceptions interrupt processing.

## Types of Temporary Files in the Rendering Pipeline

The pipeline creates four distinct categories of transient artifacts, each scoped to the editing directory (`edit_dir`) and removed immediately after use.

### Audio Envelope WAV Files

During timeline view generation, the system extracts audio envelopes by creating a mono 16 kHz WAV file for RMS analysis. In [`helpers/timeline_view.py`](https://github.com/browser-use/video-use/blob/main/helpers/timeline_view.py), the code uses `tempfile.NamedTemporaryFile(suffix=".wav", delete=False)` to create a persistent file handle that survives the `with` block, allowing FFmpeg to write the audio slice to disk.

```python

# helpers/timeline_view.py

with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
    wav = Path(f.name)                     # ← persisted for ffmpeg

# … ffmpeg writes to `wav` …

finally:
    wav.unlink(missing_ok=True)           # ← guaranteed removal

```

Cleanup occurs in a `finally:` block that calls `wav.unlink(missing_ok=True)`, ensuring the file is deleted even if an exception occurs during processing.

### Frame Extraction Directories

For the timeline view's frame extraction sandbox, the pipeline creates a temporary directory to hold JPEG frames extracted from source videos. The implementation uses `tempfile.TemporaryDirectory()` as a context manager in [`helpers/timeline_view.py`](https://github.com/browser-use/video-use/blob/main/helpers/timeline_view.py).

```python

# helpers/timeline_view.py

with tempfile.TemporaryDirectory() as tmp:
    tmp_dir = Path(tmp)
    frame_paths = extract_frames(video, start, end, n_frames, tmp_dir)

# ← exiting the `with` block automatically deletes `tmp_dir`

```

The context manager automatically removes the directory and all contained files when the block exits, providing implicit cleanup without manual intervention.

### Concat List Text Files

When joining segments losslessly, the render pipeline generates a plain-text file [`_concat.txt`](https://github.com/browser-use/video-use/blob/main/_concat.txt) that lists per-segment MP4s for the FFmpeg concat demuxer. The file is written to `edit_dir / "_concat.txt"` using `write_text` in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py).

After the concat command finishes, explicit cleanup occurs via `concat_list.unlink(missing_ok=True)`.

```python

# helpers/render.py

concat_list = edit_dir / "_concat.txt"
concat_list.write_text("".join(f"file '{p.resolve()}'\n" for p in segment_paths))

# … ffmpeg concat …

concat_list.unlink(missing_ok=True)        # ← clean-up

```

### Pre-Loud-Norm Composite MP4s

When loudness normalization is enabled, the pipeline creates an intermediate MP4 file (`<output>.prenorm.mp4`) containing video with overlays and subtitles but without audio normalization. This is constructed by `build_final_composite` and written to `tmp_composite` in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py).

Once the two-pass loudnorm step completes, the intermediate file is deleted with `tmp_composite.unlink(missing_ok=True)`.

```python

# helpers/render.py

tmp_composite = out_path.with_suffix(".prenorm.mp4")
build_final_composite(base_path, overlays, subs_path, tmp_composite, edit_dir)
apply_loudnorm_two_pass(tmp_composite, out_path, preview=args.draft)
tmp_composite.unlink(missing_ok=True)     # ← final removal

```

## Cleanup Guarantees and Error Handling

The rendering pipeline implements three layers of protection against file leakage according to the browser-use/video-use source code:

- **Explicit `unlink` calls**: Every temporary file includes a corresponding `unlink(missing_ok=True)` call, typically wrapped in `try/finally` blocks to ensure execution during exception handling.
- **Context manager scoping**: `TemporaryDirectory` handles frame extraction cleanup automatically, while `NamedTemporaryFile(delete=False)` is intentionally used to accommodate FFmpeg's requirement for concrete file paths, then manually unlinked.
- **Directory containment**: All temporary paths live under the editing directory (`edit_dir`), preventing pollution of the repository root or user's home folder.

## Summary

- **Audio envelopes**: Temporary WAV files created with `NamedTemporaryFile(delete=False)` in [`helpers/timeline_view.py`](https://github.com/browser-use/video-use/blob/main/helpers/timeline_view.py) are unlinked in `finally` blocks.
- **Frame extraction**: `TemporaryDirectory` context managers in [`helpers/timeline_view.py`](https://github.com/browser-use/video-use/blob/main/helpers/timeline_view.py) provide automatic cleanup of JPEG frames.
- **Concat lists**: Text files created in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) are explicitly removed after FFmpeg concatenation completes.
- **Intermediate MP4s**: Pre-normalization composites are deleted immediately after the two-pass loudnorm process finishes.
- **Error resilience**: `missing_ok=True` parameters ensure cleanup attempts never raise exceptions, and `finally` blocks guarantee execution regardless of processing failures.

## Frequently Asked Questions

### What happens if the FFmpeg subprocess crashes during audio extraction?

The `finally:` block in [`helpers/timeline_view.py`](https://github.com/browser-use/video-use/blob/main/helpers/timeline_view.py) executes `wav.unlink(missing_ok=True)` regardless of whether the FFmpeg command succeeds or raises an exception, ensuring the temporary WAV file is always removed.

### Why does the pipeline use `delete=False` with `NamedTemporaryFile` instead of automatic deletion?

The `delete=False` parameter is required because FFmpeg subprocesses need to write to a concrete file path on disk. If `delete=True` were used, the file would disappear when the `with` block closes, before FFmpeg can access it. The code explicitly manages deletion via `unlink()` after the subprocess completes.

### Where are temporary files stored during rendering?

All temporary files are scoped to the editing directory (`edit_dir`), including the [`_concat.txt`](https://github.com/browser-use/video-use/blob/main/_concat.txt) file and `.prenorm.mp4` intermediates. Frame extraction uses system temp directories via `tempfile.TemporaryDirectory()`, while audio envelopes use `NamedTemporaryFile()` which typically places files in the system temp location, though all are immediately unlinked after use.

### How does loudness normalization affect temporary file cleanup?

When normalization is enabled, [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) creates a pre-normalization MP4 that persists only for the duration of the two-pass process. The file is constructed by `build_final_composite` and unlinked immediately after `apply_loudnorm_two_pass()` returns, ensuring no intermediate artifacts remain regardless of the normalization outcome.