✂️ Trim by Ranges
Cut the Dead Air Out of a Video Automatically
- ranges
- frames
- audio
- final_video_path
This is the payoff node of MediaForge's headline workflow. Three nodes - load a video, detect the silence, trim it - and the dead air vanishes from a lecture, podcast, or livestream recording without you scrubbing a timeline. MF_TrimByRanges is the last one in that chain, the one that actually cuts the video by time ranges. It also takes hand-written JSON ranges and can do the cut with zero re-encoding, which is rarer than it should be.
Wire it like this: MF_DetectSilence outputs SILENCE_RANGES (a list of [start, end] pairs), which plugs straight into this node's ranges pin. Set mode=remove, and it drops those ranges and keeps everything else. MF_DetectScenes produces the same connection type, so you can cut on scene changes instead - a highlight reel is "detect scenes, keep the ones you want."
How it works
Two precision modes, and they're meaningfully different:
precise (re-encode)(default) - cuts each segment with FFmpegtrim+setpts, then interleaves them with[v0][a0][v1][a1]…concat, so audio stays in sync across cuts. Frame-accurate, at the cost of a re-encode.lossless (stream copy)- keyframe-seek segment copy plus a concat demuxer merge. No re-encode at all, and much faster. The catch: each keep range's start snaps forward to the next source keyframe, and if a range is narrower than the source's GOP with no keyframe inside it, the node raises - switch back to precise or widen the range.crossfade_seccan't apply here (stream copy can't blend pixels), so it's ignored with a console warning.
The ranges pin wins over the ranges_json widget when it's wired - that matters for the common "detected zero silence" case, where an empty list from MF_DetectSilence must not fall back to your hand-typed default JSON.
The inputs that matter
mode-remove(drop ranges, keep the rest) orkeep(keep ranges, drop the rest).ranges(optional pin) - fromMF_DetectSilence/MF_DetectScenes. Unwired, the node falls back to theranges_jsonwidget, e.g.[[1.5, 3.0], [10.0, 12.5]].crossfade_sec- fades between adjacent kept segments;0is a hard cut. Only inprecisemode.precision- the re-encode vs. stream-copy choice above.codec/crf/preset- only used inprecisemode; they're hidden and ignored inlossless(the output follows the source's container instead).
Output: final_video_path (STRING) - a file in output/MediaForge/trimmed_*.mp4 (or the source's extension in lossless mode), plus ui.images metadata if you drive it from the API.
Install
Part of the MediaForge pack. ComfyUI Manager → search "MediaForge", or:
cd ComfyUI/custom_nodes
git clone https://github.com/leon80148/comfyui_MediaForge.git
Restart, find it under MediaForge/Video. You need FFmpeg on PATH (the pack's requirements.txt includes imageio-ffmpeg/static-ffmpeg fallbacks, but a real system ffmpeg gives you the full codec catalog - including the NVENC options in that codec dropdown, which are auto-detected).
Common issues
keepmode with empty ranges raises. It refuses to produce an empty output, which is a feature.removewith empty ranges is the opposite - an identity no-op that returns the full clip.- Lossless cut "failed" on a short range. That's the keyframe gap raising. It's not a crash bug; the range genuinely can't be represented by a stream copy. Use
precisefor that clip or a wider range. - Expecting lossless to be instant. It's not literally - before cutting, the node scans the source's keyframe index (
ffprobe -skip_frame nokey), which takes real time on long files. It's still far faster than a re-encode. - Multi-track audio sources (e.g. English + commentary) keep all their tracks in lossless mode instead of dropping the non-default ones. A nice touch most trim tools get wrong.
For auto-cutting silence, tune MF_DetectSilence (noise_db=-30, min_duration_sec=0.5 for typical podcasts) and let this node do the mechanical work. It's the least glamorous node in the chain and the one that saves the most time.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| video_path | STRING | input/sample.mp4 | — |
| filename_prefix | STRING | MediaForge/trimmed | — |
| mode | COMBO | remove | 2 options: keep, remove |
| ranges_json | STRING | [[0.0, 1.0], [5.0, 7.5]] | — |
| crossfade_sec | FLOAT | 0.000–2 | — |
| codec | COMBO | h264 NVIDIA GPU (h264_nvenc) | 7 options: h264 (libx264), hevc (libx265), av1 (libsvtav1), prores (prores_ks), h264 NVIDIA GPU (h264_nvenc), hevc NVIDIA GPU (hevc_nvenc), +1 |
| crf | INT | 180–51 | — |
| preset | COMBO | medium | 9 options: ultrafast, superfast, veryfast, faster, fast, medium, +3 |
| rangesopt | SILENCE_RANGES | — | |
| framesopt | IMAGE | — | |
| tensor_fpsopt | FLOAT | 30.01–240 | — |
| audioopt | AUDIO | — | |
| precisionopt | COMBO | precise (re-encode) | 2 options: precise (re-encode), lossless (stream copy) |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| final_video_path | STRING | — |