npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@crafter/vcut

v0.23.0

Published

Cut dead air out of a recording, reproducibly. Agent-first CLI over ffmpeg.

Readme

npx @crafter/vcut recording.mp4

Why

Cutting silence out of a talking-head recording is mechanical work an agent should do. What an agent should not do is decide which of your mistakes stay in, or overwrite your only copy of a take.

vcut splits those. It proposes cuts as data, and every destructive step is gated. The thresholds are not invented: they come from a pipeline that ran in production on real published video.

Quick Start

npm install -g @crafter/vcut     # or: bun add -g @crafter/vcut
vcut doctor             # checks ffmpeg and ffprobe

Requires ffmpeg and ffprobe on your PATH. On macOS: brew install ffmpeg.

# 1. Find what is worth cutting
vcut detect recording.mp4 --preset clean > detect.json

# 2. Draft an edit decision list
vcut edl build --detect detect.json --output master.mp4 --campaign my-video

# 3. Iterate on the audio, which is where the decisions are
vcut render --edl edl.json --audio-only --output cut.wav

# 4. Preview it, watch it, then render the master
vcut render --edl edl.json --mode preview

Step 3 exists because a round of edits asks audio questions and rendering the picture to answer them costs far more wall clock than the round needs. Audio-only is not instant either: it costs roughly 1 second per 14 seconds of audio the cut keeps, driven by kept audio rather than segment count.

In a terminal you get a summary:

recording.mp4  6m 22s
  detected dead air       ###.................  16.5%  (1m 03s)
  net after margins       ##..................  10.3%  (~39s once 100ms is kept on each side)
  silences                119 spans, 1m 03s
  longest silence         1s at 6m 20s
  filler words            not scanned; a word list cannot tell filler from ordinary use. Run vcut semantic.
  review candidates       1 (never cut automatically)
                          clipping: peak level -0.24 dB exceeds -1 dBFS

Piped or captured, the same command emits JSON. No flag needed.

Commands

| Command | What it does | |---------|--------------| | vcut detect <input> | Silences, clipping, black and frozen frames | | vcut suspects --detect | Where to look first, ranked, from the pauses detect measured | | vcut edl build | Turns a detect report into a draft edit decision list | | vcut semantic export\|check\|review | Hands the transcript to a model, takes proposals back, reads the result | | vcut render | Renders an EDL; preview accepts proposals, master needs approval | | vcut locate --edl | Translates between master time and source time | | vcut audit --edl --render | Checks a render's audio against the EDL it came from | | vcut joins --edl --render | Verifies every semantic join in one call, the post-render twin of edl build's removedText | | vcut say <media> | Reads back what is spoken at a position, from a transcript or by asking the audio | | vcut silences <media> | Speech/silence blocks over a range, at a threshold and minimum you choose | | vcut converge <media> | Finds where a repeated phrase stops coming back | | vcut nonspeech <render> [--verify] | Finds audible sound that is not language; --verify reads a window around each span instead of the whole-file transcript | | vcut verify --windows <media> | Tiles the media into short windows, transcribes every one in parallel, and reports repeated phrases, truncated edges, and anomalies a whole-file transcript smooths away | | vcut open <media> | Opens or resumes a content-addressed session, maps its blocks with stable refs, caches detection across calls | | vcut peek <media> (--ref \| --at) | The four views of a position aligned in one call: cached transcript, re-transcribed audio, fine-resolution speech/silence blocks, level, and their disagreement named | | vcut cut <media> --refs \| --span | Proposes a semantic cut against a session's block refs, shows what it removes before any build | | vcut commit <media> [flags] | Builds and renders a session's accumulated proposals into a draft EDL, byte-identical to edl build run by hand | | vcut rounds <media> [--diff N M] | A session's committed rounds; --diff compares two build reports (removalPercent, segments, semantic cuts by span overlap) | | vcut session list\|gc [flags] | Lists sessions with size and lock state; gc clears disposable session cache (dry-run by default, --apply to delete) | | vcut schema [name] | The JSON contract per command, versioned | | vcut skills get core | The bundled agent manual, as markdown. --section <name> serves one deep-dive section; vcut skills list shows what sections exist | | vcut init | Installs everything a first run needs, and reports what it could not | | vcut doctor | Checks external dependencies | | vcut setup classifier | Fetches the optional non-speech classifier | | vcut <input> | Shorthand for vcut detect |

Cutting is a loop

Silence removal is the first round of several. Each class of defect only becomes visible once the one above it is gone: a pause two adjoining segments create together did not exist in either of them, a broken join only reads as broken once both sides are adjacent, and a discourse marker is inaudible inside loose speech and obvious inside tight speech.

The loop, its stopping condition, and what has already been tried and failed live in the manual the CLI serves, which always matches the version installed:

vcut skills get core      # the procedure, the invariants, what eleven runs taught
vcut skills get debug     # how to investigate a cut that came out wrong

Stop when a round proposes nothing, not when the removal percentage looks respectable, and never on the first round.

Beyond silence

  • --crop top:0.06 frames the whole edit at once, so remembering the menu bar after cutting does not mean redoing every segment.
  • --edge-fade (default 50ms) ramps each segment edge to zero. Not a crossfade: overlapping the sides would drift the audio against concatenated video.
  • Loudness is normalised to the speechTargetLufs the EDL declares, on the concatenated result rather than per segment.
  • vcut nonspeech <render> --verify finds breaths, mic bumps, and stretched hesitations the transcript cleaned away, which neither the silence pass nor the transcript can see on their own. --verify re-transcribes a short window around each span instead of checking it against the whole-file transcript, which is circular for exactly this class of sound. vcut setup classifier fetches what the underlying model needs; without it the check falls back to a human ear.

Presets

| Preset | Threshold | Use | | --- | --- | --- | | noisy (default) | -20 dB | Events, ambient noise | | clean | -30 dB | Studio, talking head | | podcast | -35 dB | Intentional pauses |

Tune with --min-silence (seconds, default 0.3) and --margin (seconds, default 0.10).

Filler words

Word-level timestamps mean one cue per word. A normal SRT has one cue per sentence, which is not enough to cut a single word without guessing. vcut tells you when this is the case instead of silently reporting zero.

whisper-cli -m ggml-large-v3-turbo.bin -f audio.wav -l es \
  --max-len 1 --split-on-word --output-srt

trx transcribe <input> --words --language es -m large-v3-turbo does the same from [email protected] on. --split-on-word is not optional: without it --max-len 1 cuts at token boundaries, so "Crafter" arrives as Cra + fter and the transcript looks word-level while breaking every cut that relies on it. Measured on one recording: 26% of cues were fragments without the flag, 0% with it, and detect now warns when it sees this.

Ask for a large model. One cue per word means one cue per token, and what counts as a token depends on the model. On the same three minutes of Spanish, small returns 26% of its cues as word fragments, splitting "Crafter" into Cra + fter; large-v3-turbo returns 0% and costs 13 seconds. Fragments weaken word clamping and make the semantic export unreadable.

vcut detect recording.mp4 --transcript words.srt --lang es

Lists ship for es, en, and pt.

detect finds silence, not filler words. A word list matches tokens, not intent: Spanish este is filler in "y este, entonces" and a demonstrative in "en este caso", and no list survives a new language. Filler words are proposed by a model through vcut semantic, like every other judgement call.

For agents

npx skills add Railly/vcut    # install the skill for Claude Code, Cursor, or any agent

The installed skill is a thin stub: it points at the CLI rather than copying its contents, so the guidance never drifts from the installed version.

vcut skills list                     # what the installed version ships, including core's sections
vcut skills get core                 # the small, always-loaded usage guide, as raw markdown
vcut skills get core --section cut   # one deep-dive section, loaded only when needed
vcut skills get debug                # how to investigate a cut that came out wrong
vcut schema detect                   # the JSON contract, versioned

debug is worth reading before diagnosing anything. Every method in it is cheap; none of them is the obvious one. It exists because for each question there is a more rigorous-looking instrument that cannot tell the hypotheses apart, and reaching for it is how confident wrong answers get written down.

JSON is emitted automatically when stdout is not a TTY, so an agent never needs --json. Data goes to stdout, diagnostics to stderr. Exit code 2 means the invocation was wrong, 1 means the run failed.

Guarantees

  • Source media is never modified. Sources are hashed; a changed hash aborts a master render.
  • Nothing is approved automatically. Segments are born proposed, the EDL draft. There is no --yes.
  • Renders are reproducible. The same EDL produces a byte-identical file, verified by the sha256 in the output.
  • The renderer checks its own work against the EDL: dimensions, pixel format, colour metadata, frame count, audio contract. A mismatch fails the run rather than shipping a bad file.
  • Session cache never eats an approved edit. commit writes the EDL wherever --output/--edl pointed, never inside a session directory session gc can clear; gc is dry-run unless --apply is passed, and a session a live process is writing to is always protected from it.

Limits

  • Semantic cutting is proposal-only. vcut semantic export hands the transcript to a model as numbered lines and edl build --semantic folds the proposals back in, each one marked semanticRisk: material. vcut never calls a model itself: no dependency, no API key, same EDL for the same proposals file.
  • Audio ramps 50ms at each segment edge (--edge-fade 0 disables it). Not a crossfade: overlapping the two sides would shorten the render against concatenated video and drift the audio out of sync, so each side fades within its own segment. A joint under a fully continuous sentence can still be heard as a dip.
  • A silence detector decides by level, so a soft consonant under the threshold is cut like a pause. If a word loses its opening sound, the fix is the recording or a lower threshold, not a larger margin.
  • Audio recorded separately works: detect --audio mic.wav measures silence on that file, and the EDL carries both sources. edl build --audio-offset <ms> corrects two recorders that did not start together.
  • Noise reduction is not offered. There is no safe default: the right amount depends on the room, and on one measured recording a denoiser at a default setting pushed a weak syllable from -45 dB to -57, which is the same defect as a threshold set too high. Loudness normalisation is the part that is safe to automate, and it is on by default.
  • No face tracking or automatic zoom.

Design

Why it is shaped this way: design-notes.md. Full documentation at vcut.crafter.run/docs.

License

MIT