# How video-use Applies Loudness Normalization to Hit -14 LUFS for Social Media

> Learn how video-use applies loudness normalization to achieve -14 LUFS for social media. Ensure your audio meets YouTube, Instagram, and TikTok standards.

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

---

**video-use automatically normalizes audio to -14 LUFS during the final render using a two-pass FFmpeg loudnorm filter, ensuring compliance with YouTube, Instagram, TikTok, and LinkedIn standards.**

The browser-use/video-use repository implements automated loudness normalization as a core step in its video rendering pipeline. By hard-coding industry-standard targets and executing a precise two-pass FFmpeg workflow, the tool ensures that exported videos meet the strict audio level requirements demanded by modern social platforms. This eliminates manual audio leveling and prevents videos from being penalized by platform algorithms for inconsistent loudness.

## Social Media Target Constants

The normalization targets are defined as module-level constants in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) to match the "social-ready" profile used by major platforms.

```python

# helpers/render.py

# Social-media standard: -14 LUFS integrated, -1 dBTP peak, LRA 11 LU.

# Matches YouTube / Instagram / TikTok / X / LinkedIn normalization targets.

LOUDNORM_I = -14.0          # ← target integrated loudness

LOUDNORM_TP = -1.0          # ← target true-peak

LOUDNORM_LRA = 11.0         # ← target loudness range

```

These values correspond to **-14 LUFS** integrated loudness, **-1 dBTP** true-peak limiting, and a **11 LU** loudness range. According to the source code comments at lines 690-695, this specific profile ensures that rendered videos upload to social platforms without triggering additional platform-side compression or normalization.

## Two-Pass Measurement with FFmpeg

Before applying correction, the system must measure the source audio characteristics. The `measure_loudness()` function runs a first-pass analysis using FFmpeg's `loudnorm` filter in JSON print mode.

```python
def measure_loudness(video_path: Path) -> dict[str, str] | None:
    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)
    # …extract JSON from proc.stderr…

```

This analysis pass (lines 998-1005) extracts the input file's measured integrated loudness (`input_i`), true-peak (`input_tp`), loudness range (`input_lra`), threshold (`input_thresh`), and the calculated target offset. The function returns these values as a dictionary to be consumed by the second pass.

## Applying the Normalization Filter

The `apply_loudnorm_two_pass()` function implements the actual correction logic. It distinguishes between **preview mode** (fast one-pass) and **final render mode** (accurate two-pass).

For final renders, the function feeds the measured values back into FFmpeg alongside the target constants:

```python
def apply_loudnorm_two_pass(input_path: Path, output_path: Path, preview: bool = False) -> bool:
    if preview:
        # one-pass approximation

        filter_str = f"loudnorm=I={LOUDNORM_I}:TP={LOUDNORM_TP}:LRA={LOUDNORM_LRA}"
        # …

    else:
        measurement = measure_loudness(input_path)
        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']}:linear=true"
        )
        # …

```

As implemented in lines 1020-1070, the two-pass approach uses the `linear=true` parameter for true-peak limiting and applies the measured offset to achieve the -14 LUFS target precisely. Preview mode skips the measurement phase for speed, using a single-pass approximation instead.

## Integration in the Rendering Pipeline

Loudness normalization is integrated into the final compositing workflow in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) (lines 644-652). After visual overlays and subtitles are composited, the script either writes directly to the destination or processes through the loudnorm pipeline:

```python

# helpers/render.py – main rendering flow (excerpt)

if args.no_loudnorm:
    build_final_composite(base_path, overlays, subs_path, out_path, edit_dir)
else:
    tmp_composite = out_path.with_suffix(".prenorm.mp4")
    build_final_composite(base_path, overlays, subs_path, tmp_composite, edit_dir)
    print("loudness normalization → social-ready (-14 LUFS / -1 dBTP / LRA 11)")
    apply_loudnorm_two_pass(tmp_composite, out_path, preview=args.draft)
    tmp_composite.unlink(missing_ok=True)

```

The default behavior includes normalization. The system creates a temporary "pre-norm" file, applies the two-pass loudness correction, then deletes the temporary file. Users can skip this step entirely using the `--no-loudnorm` flag for workflows requiring custom audio processing.

## Command-Line Usage Examples

**Default render (social-ready loudness):**

```bash
python helpers/render.py my_edit.edl.json -o final.mp4

```

*Result:* Composite → temporary pre-norm → two-pass loudnorm → `final.mp4` at -14 LUFS.

**Skip loudness normalization:**

```bash
python helpers/render.py my_edit.edl.json -o final.mp4 --no-loudnorm

```

*Result:* Composite writes directly to `final.mp4` without audio normalization, preserving original levels for external processing.

**Preview render (fast one-pass):**

```bash
python helpers/render.py my_edit.edl.json -o preview.mp4 --preview --draft

```

*Result:* Uses the one-pass approximation in `apply_loudnorm_two_pass(..., preview=True)` for faster iteration during editing.

## Summary

- **-14 LUFS target** is hard-coded via `LOUDNORM_I`, `LOUDNORM_TP`, and `LOUDNORM_LRA` constants in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) to match YouTube, Instagram, TikTok, and LinkedIn standards.
- **Two-pass measurement** occurs via `measure_loudness()` using FFmpeg's JSON output mode to capture precise input characteristics.
- **Correction application** happens in `apply_loudnorm_two_pass()`, which uses measured values for final renders and a fast approximation for preview mode.
- **Automatic integration** runs after visual compositing unless disabled with `--no-loudnorm`, ensuring all exports are "social-ready" without manual intervention.

## Frequently Asked Questions

### Why does video-use target -14 LUFS instead of -4 LUFS?

The -14 LUFS target aligns with the normalization standards used by YouTube, Instagram Reels, TikTok, X, and LinkedIn. As noted in the source code comments at [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) lines 690-695, these constants ensure videos are "social-ready" immediately after export. Users requiring broadcast standards (-4 LUFS) must manually modify the `LOUDNORM_I`, `LOUDNORM_TP`, and `LOUDNORM_LRA` constants in the source file.

### Can I skip loudness normalization for custom audio workflows?

Yes. Pass the `--no-loudnorm` flag to [`render.py`](https://github.com/browser-use/video-use/blob/main/render.py) to bypass the normalization pipeline entirely. When this flag is used, `build_final_composite()` writes the video directly to the output path without creating temporary pre-norm files or running the loudnorm filter, preserving the original audio levels for external processing.

### What is the difference between preview mode and final render for loudness?

Preview mode uses a **one-pass approximation** via `apply_loudnorm_two_pass(..., preview=True)` for speed during iterative editing. The final render uses a **two-pass process**: first calling `measure_loudness()` to analyze the source, then applying precise corrections using the measured input values (`measured_I`, `measured_TP`, etc.) to achieve the exact -14 LUFS target.

### Which source file contains the loudness normalization implementation?

All loudness logic resides in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py). The target constants are defined at lines 690-695, the measurement function `measure_loudness()` is implemented at lines 998-1005, and the application function `apply_loudnorm_two_pass()` spans lines 1020-1070. The integration into the main rendering flow occurs at lines 644-652.