Skip to content

feat: manual "Remove Silence" auto-trim in the timeline - #27

Merged
Alfredoalv13 merged 1 commit into
mainfrom
feat/remove-silence
Jul 25, 2026
Merged

feat: manual "Remove Silence" auto-trim in the timeline#27
Alfredoalv13 merged 1 commit into
mainfrom
feat/remove-silence

Conversation

@Alfredoalv13

Copy link
Copy Markdown
Owner

Summary

  • Adds automatic silence/dead-air detection and removal as an explicit, user-triggered timeline toolbar action — a new "Remove Silence" button next to Split Clip.
  • Never automatic, never on by default — per explicit product direction: streamers and tutorial-makers often go quiet on purpose while performing an on-screen action (waiting for something to load, demonstrating a UI flow), and this must never silently cut that out. There is no auto-trigger-on-fresh-recording behavior (unlike the existing zoom-suggestion feature).
  • The user picks which audio track decides "this is silence" — the button opens a picker showing only the tracks that were confirmed to actually exist (mic sidecar / system-audio sidecar / the embedded-in-video "Full Recording" track), rather than the app guessing a mic-vs-system-audio heuristic.
  • Detection: RMS/energy-based, -40dB threshold, 700ms minimum gap duration (so natural speech pauses aren't chopped up), 120ms padding kept on each side of a cut so words aren't clipped.
  • Implementation-wise, a detected cut is just a real ClipRegion split (mirroring the app's existing manual split+delete trim pattern exactly) — fully undoable/draggable/deletable like any other edit, no new data model, no exporter changes needed.

Test plan

  • npx tsc -p tsconfig.json --noEmit — clean
  • npx vitest --run — 834/834 passing (15 new tests covering the pure detection/region-subtraction logic: threshold/min-duration/padding edge cases, multi-channel handling, span-at-boundary id preservation, full-clip removal, multi-span splitting)
  • Built, signed, ran the packaged app directly
  • Confirmed the track picker only shows "Full Recording" for a file with no mic/system sidecars (correct — nothing to choose from)
  • Ran it against a real recording with actual speech and pauses: detected 8 silence gaps, correctly split a single 24.5s clip into 9 surviving segments with plausible gap durations for the configured threshold
  • Confirmed Undo fully reverts the operation back to the original single clip

Adds automatic silence/dead-air detection and removal, as an explicit,
user-triggered timeline toolbar action - never automatic, never on by
default. Per explicit product direction: streamers and tutorial-makers
often go quiet on purpose while performing an on-screen action, so this
must only ever run when the user deliberately asks for it, and the user
picks which audio track decides "this is silence" themselves rather than
the app guessing a mic-vs-system-audio heuristic.

- silenceDetection.ts: pure, fully unit-tested RMS/energy-based silence
  span detection (-40dB threshold, 700ms minimum gap, 120ms padding kept
  on each side so words aren't clipped) plus a pure interval-subtraction
  function that splits existing ClipRegions around detected spans -
  mirrors the app's existing manual split+delete trim semantics exactly,
  so the derived TrimRegion/export/playback pipeline picks up the result
  with no further changes.
- silenceAudioSource.ts: thin, untested I/O layer - discovers which audio
  sources actually exist for a recording (separate mic/system-audio
  sidecar files, or just the embedded/mixed track) and decodes the
  user-chosen one to raw PCM via the Web Audio API.
- VideoEditor.tsx: a new toolbar button opens a track picker (only shows
  tracks that were confirmed to exist) and applies the detected cuts as
  real, undoable ClipRegion edits - same undo/redo path as every other
  timeline edit, with overlapping zoom/annotation/speed/audio regions
  purged the same way manual clip deletion already does it.

Verified live against a packaged build with a real recording containing
actual speech and pauses: detected 8 silence gaps and correctly split a
single 24.5s clip into 9 surviving segments with plausible gap durations
for the configured threshold; confirmed Undo fully reverts the operation
back to the original single clip.
@Alfredoalv13
Alfredoalv13 merged commit cdddf22 into main Jul 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants