# How video-use Prevents Audio Pops at Segment Boundaries: Cross-Fade Implementation Explained

> Learn how video-use prevents audio pops at segment boundaries using ffmpeg's afade filter and symmetric cross-fades. Ensure smooth audio transitions in your video projects.

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

---

**video-use eliminates audio pops at cut points by applying symmetric 30 ms cross-fades to every extracted segment using ffmpeg's afade filter during the encoding phase.**

When editing long-form video into shorter segments, abrupt cuts in the audio waveform create audible "pop" or click artifacts at segment boundaries. These discontinuities occur because the raw audio stream starts and stops at non-zero amplitude points. The video-use library solves this problem by baking smooth fade envelopes directly into each clip during extraction, ensuring clean audio transitions without requiring post-processing.

## How the 30 ms Cross-Fade Works

The audio pop prevention strategy in video-use centers on two **afade** audio filters applied in a single ffmpeg pass. This approach guarantees that every extracted segment begins and ends at zero amplitude, creating continuous waveforms when clips are later concatenated.

### Fade Filter Construction in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py)

The implementation lives at lines 187-190 of [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py), where the code constructs a compound audio filter string:

```python
fade_out_start = max(0.0, duration - 0.03)
af = f"afade=t=in:st=0:d=0.03,afade=t=out:st={fade_out_start:.3f}:d=0.03"

```

This string is passed to ffmpeg via the `-af` (audio filter) option at lines 1000-1005 of the same file.

The filter consists of two operations:

- **Fade-in**: `afade=t=in:st=0:d=0.03` — Ramps audio from silence to full volume over the first 30 milliseconds
- **Fade-out**: `afade=t=out:st={fade_out_start}:d=0.03` — Ramps audio from full volume to silence over the final 30 milliseconds

The `max(0.0, duration - 0.03)` calculation protects against edge cases where a segment might be shorter than 30 ms, ensuring the fade-out never starts before the clip begins.

### Why 30 Milliseconds?

The 30 ms duration represents a pragmatic balance between:

- **Effectiveness**: Long enough to fully suppress audible clicks across the frequency spectrum of typical video content
- **Imperceptibility**: Short enough that listeners perceive no audible "ducking" or volume change during normal speech or music

The comment at line 187 explicitly documents this as "Rule 3" of the rendering pipeline: "30 ms audio fades at both edges (Rule 3) — prevent pops."

## Practical Implementation

### Python API: Extracting a Pop-Free Segment

The `extract_segment` function in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) automatically applies the cross-fade without requiring explicit configuration:

```python
from pathlib import Path
from helpers.render import extract_segment

source_video = Path("raw footage/scene1.mp4")
start_sec   = 12.345          # segment start time

duration    = 4.567           # segment length

grade_filter = ""             # optional colour-grade filter

out_file    = Path("edits/segment_01.mp4")

extract_segment(
    source=source_video,
    seg_start=start_sec,
    duration=duration,
    grade_filter=grade_filter,
    out_path=out_file,
    preview=False,
    draft=False,
)

```

The function returns an MP4 file with the fade envelopes already embedded in the audio track.

### Generated ffmpeg Command Structure

Under the hood, `extract_segment` builds and executes an ffmpeg command equivalent to:

```bash
ffmpeg -y \
  -ss 12.345 \
  -i raw\ footage/scene1.mp4 \
  -t 4.567 \
  -vf "scale=1920:-2" \
  -af "afade=t=in:st=0:d=0.03,afade=t=out:st=4.537:d=0.03" \
  -c:v libx264 -preset fast -crf 20 -pix_fmt yuv420p -r 24 \
  -c:a aac -b:a 192k -ar 48000 -movflags +faststart \
  edits/segment_01.mp4

```

The `-af` argument containing the fade filters is the critical component that prevents audio pops at segment boundaries.

## Integration with the Rendering Pipeline

The audio fade implementation operates within a broader segment extraction architecture defined across three key files:

| File | Role |
|------|------|
| [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) | Core logic for extracting segments, inserting audio fades, and encoding clips |
| [`helpers/grade.py`](https://github.com/browser-use/video-use/blob/main/helpers/grade.py) | Colour-grade filters that can be chained with the audio-fade pipeline |
| [`README.md`](https://github.com/browser-use/video-use/blob/main/README.md) | High-level workflow documentation |

Because the fades are applied during the **extraction** phase rather than during concatenation, the resulting clips are self-contained. This design decision simplifies downstream operations: when segments are joined into a final output, no additional audio processing is required to maintain pop-free transitions.

## Summary

- **video-use prevents audio pops** by applying symmetric 30 ms cross-fades at segment boundaries
- **Implementation location**: [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py), lines 187-190 and 1000-1005
- **Technical mechanism**: ffmpeg `afade` filters applied via the `-af` option during segment encoding
- **Fade-out protection**: `max(0.0, duration - 0.03)` calculation prevents invalid start times for very short clips
- **Pipeline benefit**: Fades are baked into extracted clips, eliminating post-processing requirements for concatenation

## Frequently Asked Questions

### Can I customize the fade duration in video-use?

The 30 ms duration is hardcoded in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) as part of the core extraction logic. To modify this value, you would need to edit the `0.03` constants in the fade filter string construction. The maintainers chose this duration as a universal default that works across speech, music, and ambient audio without perceptible quality loss.

### Why apply fades during extraction instead of concatenation?

Processing fades at extraction time ensures that each segment is a self-contained, valid media file. This architecture decouples segment creation from final assembly, allowing clips to be previewed individually, reused across different projects, or concatenated with simple file-level operations without requiring complex audio processing at output time.

### Does the cross-fade affect audio quality or introduce gaps?

The 30 ms linear fades are imperceptible during normal playback and do not create audible gaps. The fade-out completes exactly at the segment end, and the fade-in begins exactly at the segment start. When clips are concatenated, the zero-amplitude boundary points ensure waveform continuity with no discontinuity artifacts.

### What happens if a segment is shorter than 60 ms total?

The `max(0.0, duration - 0.03)` calculation ensures mathematical validity: for segments between 30 ms and 60 ms, the fade-out overlaps partially with the fade-in. For segments under 30 ms, both fades start at time zero, resulting in a brief triangular envelope. These edge cases are rare in practical video editing workflows where segments typically span multiple seconds.