# How Two-Pass Loudnorm Measurement Works in video-use

> Explore the two-pass loudnorm measurement mechanism in video-use. Learn how ffmpeg's loudnorm filter achieves precise audio loudness standards for optimal output.

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

---

**The two-pass loudnorm measurement in video-use analyzes audio using ffmpeg's loudnorm filter with `print_format=json` to capture precise loudness statistics, then feeds those measured values into a second pass to guarantee the output meets the target -14 LUFS integrated standard while preserving the original video stream.**

The browser-use/video-use repository implements broadcast-standard audio normalization for social media content through a precise two-step process. This mechanism ensures uploaded videos meet consistent loudness targets without re-encoding video streams, making it essential for creating platform-ready content efficiently.

## First Pass: Measurement and Analysis

The measurement phase occurs in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) within the `measure_loudness` function (lines 97-112). This function executes ffmpeg with the loudnorm filter configured to output diagnostic data rather than processed audio.

```python
def measure_loudness(video_path: Path) -> dict[str, str] | None:
    """
    Run ffmpeg loudnorm first pass and parse the JSON measurement.
    """
    filter_str = (
        f"loudnorm=I={LOUDNORM_I}:TP={LOUDNORM_TP}:LRA={LOUDNORM_LRA}:print_format=json"
    )
    cmd = [
        "ffmpeg", "-y", "-hide_banner", "-nostats",
        "-i", str(video_path),
        "-af", filter_str,
        "-vn", "-f", "null", "-",
    ]
    proc = subprocess.run(cmd, capture_output=True, text=True)
    stderr = proc.stderr
    # Extract the JSON block that loudnorm prints to stderr

    start = stderr.rfind("{")
    end   = stderr.rfind("}")
    data = json.loads(stderr[start : end + 1])
    return data

```

**Key technical details:** The filter analyzes the entire audio stream and writes a JSON object containing `input_i` (integrated loudness), `input_tp` (true peak), `input_lra` (loudness range), `input_thresh`, and `target_offset` to **stderr**. The code isolates this JSON block (lines 116-123) by finding the last occurrence of curly braces in the stderr output, ensuring reliable extraction even when ffmpeg logs additional information.

## Second Pass: Normalization with Measured Values

The `apply_loudnorm_two_pass` function (lines 131-190) orchestrates the full workflow by feeding the measured values back into ffmpeg. This second pass applies the calculated gain or attenuation needed to reach the target specification.

```python
def apply_loudnorm_two_pass(
    input_path: Path,
    output_path: Path,
    preview: bool = False,
) -> bool:
    # Full two-pass

    print(f"  loudnorm pass 1: measuring {input_path.name}")
    measurement = measure_loudness(input_path)
    if measurement is None:
        # Fallback to one-pass approximation if measurement fails

        return apply_loudnorm_two_pass(input_path, output_path, preview=True)
    
    filter_str = (
        f"loudnorm=I={LOUDNORM_I}:TP={LOUDNORM_TP}:LRA={LOUDNORM_LRA}"
        f":measured_I={measurement['input_i']}"
        f":measured_TP={measurement['input_tp']}"
        f":measured_LRA={measurement['input_lra']}"
        f":measured_thresh={measurement['input_thresh']}"
        f":offset={measurement['target_offset']}"
        f":linear=true"
    )
    cmd = [
        "ffmpeg", "-y", "-hide_banner", "-nostats",
        "-i", str(input_path),
        "-c:v", "copy",
        "-af", filter_str,
        "-c:a", "aac", "-b:a", "192k", "-ar", "48000",
        "-movflags", "+faststart",
        str(output_path),
    ]
    subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
    return True

```

**Critical implementation detail:** The second pass populates the `measured_I`, `measured_TP`, `measured_LRA`, `measured_thresh`, and `offset` parameters with values from the first pass. This tells the loudnorm filter exactly how much adjustment is required to hit the target loudness while preserving dynamic range. The video stream is copied directly (`-c:v copy`) to avoid quality loss and reduce processing time.

## Preview Mode and Single-Pass Fallback

When the `preview` parameter is `True` or when the first pass measurement fails, the system falls back to a **single-pass approximation**. This mode skips the measurement phase and runs loudnorm without the measured value parameters:

```python
if preview:
    filter_str = f"loudnorm=I={LOUDNORM_I}:TP={LOUDNORM_TP}:LRA={LOUDNORM_LRA}"

```

This approach is significantly faster but less accurate because the filter cannot adapt to the specific loudness characteristics of the source material. The fallback mechanism ensures robustness: if `measure_loudness` returns `None` due to parsing errors or ffmpeg failures, the code automatically retries with `preview=True`.

## Target Loudness Constants

The normalization targets are defined as constants at lines 90-94 in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py):

```python
LOUDNORM_I = -14.0   # target integrated LUFS

LOUDNORM_TP = -1.0   # target true-peak dB

LOUDNORM_LRA = 11.0  # target loudness range

```

These values represent the **social media loudness standard** (-14 LUFS integrated, -1 dBTP peak, 11 LU loudness range) used by major platforms to ensure consistent audio levels across user-generated content.

## Summary

- **Two-pass workflow**: First pass measures, second pass normalizes using measured values to guarantee target compliance.
- **JSON extraction**: The `measure_loudness` function parses loudnorm's JSON output from stderr by locating the last curly-brace block in the output.
- **Video preservation**: The second pass uses `-c:v copy` to maintain original video quality while only re-encoding the normalized audio stream.
- **Fallback strategy**: If measurement fails, the system automatically falls back to single-pass mode for reliability.
- **Social media standards**: Targets -14 LUFS integrated loudness with -1 dBTP true peak and 11 LU loudness range.

## Frequently Asked Questions

### Why does video-use use a two-pass loudnorm measurement instead of single-pass?

The two-pass approach guarantees precise loudness compliance by first measuring the actual integrated loudness, true peak, and loudness range of the source material, then calculating the exact gain correction needed. Single-pass mode must estimate these values on the fly, which can result in slight deviations from the target -14 LUFS standard, making the two-pass method essential for final delivery quality.

### What specific loudness values does video-use target?

According to the constants defined in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py), video-use targets **-14.0 LUFS** for integrated loudness (`LOUDNORM_I`), **-1.0 dBTP** for true peak (`LOUDNORM_TP`), and **11.0 LU** for loudness range (`LOUDNORM_LRA`). These values align with the social media loudness standard used by major platforms to ensure consistent audio levels.

### How does the measurement data transfer between the two passes?

The first pass captures a JSON object containing keys like `input_i`, `input_tp`, `input_lra`, `input_thresh`, and `target_offset` from ffmpeg's stderr output. The `measure_loudness` function returns this data as a dictionary, which `apply_loudnorm_two_pass` then injects into the second pass's filter string using the `measured_I`, `measured_TP`, `measured_LRA`, `measured_thresh`, and `offset` parameters.

### What happens if the first pass measurement fails?

If `measure_loudness` returns `None` due to parsing errors or ffmpeg execution issues, the code automatically triggers a fallback scenario. The `apply_loudnorm_two_pass` function recursively calls itself with `preview=True`, which skips the measurement phase and uses a single-pass loudnorm filter approximation instead, ensuring the pipeline completes even when precise measurement is unavailable.