
Raw Video Processing
Automatically cut dead air and long pauses out of screen recordings or talking-head clips so published videos stay tight for social and course content.
Overview
Raw Video Processing is an agent skill for the Grow phase that removes silent segments from video files using FFmpeg silencedetect and concatenates the rest into a tighter export.
Install
npx skills add https://github.com/zc277584121/marketing-skills --skill raw-video-processingWhat is this skill?
- FFmpeg silencedetect finds silent intervals with configurable noise threshold and minimum duration
- Cuts silent segments and concatenates remaining audio/video into a new output file
- CLI flags for output path, padding around cuts, threshold (e.g. -30dB), and duration (e.g. 0.5s)
- Python orchestration around ffmpeg and ffprobe for duration probing and segment assembly
- Suitable for raw marketing or tutorial footage before trimming in an editor
Adoption & trust: 833 installs on skills.sh; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You have long raw recordings full of awkward pauses and room silence that waste viewer time and slow down content shipping.
Who is it for?
Indie creators batching screen captures or talking-head drafts who want a fast first-pass silence trim before final edits.
Skip if: Builders who need frame-accurate creative editing, multi-track audio mixing, or cloud transcoding pipelines without running FFmpeg locally.
When should I use this skill?
You have a raw MP4 (or similar) with long silent gaps and want FFmpeg to detect and cut them with optional threshold, duration, and padding flags.
What do I get? / Deliverables
You get a shorter video file with silent gaps removed, ready to review and publish or import into your normal editing stack.
- Output video file with silent segments removed
- Configurable silence-detection parameters applied to the source
Recommended Skills
Journey fit
Canonical shelf is Grow because the output is edited media ready for publishing and lifecycle content, not app feature code. Content subphase covers video prep and post-production workflows solo creators run before distribution.
How it compares
A focused FFmpeg silence-cut script, not a full video editor skill or generative B-roll package.
Common Questions / FAQ
Who is raw-video-processing for?
Solo builders and marketers who record product demos or educational video and want automated dead-air removal from local files.
When should I use raw-video-processing?
Use it in Grow when polishing content assets—after recording, before upload—especially for social clips, tutorials, and webinar replays you want to tighten quickly.
Is raw-video-processing safe to install?
Review the Security Audits panel on this Prism page before running scripts that invoke FFmpeg on your filesystem; treat it like any repo script with shell access.
SKILL.md
READMESKILL.md - Raw Video Processing
#!/usr/bin/env python3 """ Remove silent segments from a video file. Uses FFmpeg's silencedetect filter to find silent parts, then cuts them out and concatenates the remaining (non-silent) segments into a new video. Usage: python remove_silence.py input.mp4 python remove_silence.py input.mp4 -o output.mp4 python remove_silence.py input.mp4 --threshold -30dB --duration 0.5 python remove_silence.py input.mp4 --padding 0.15 """ import argparse import json import os import re import subprocess import sys import tempfile from pathlib import Path def detect_silences(input_file: str, threshold: str, min_duration: float) -> list[dict]: """Use FFmpeg silencedetect to find silent segments.""" cmd = [ "ffmpeg", "-i", input_file, "-af", f"silencedetect=noise={threshold}:d={min_duration}", "-f", "null", "-" ] result = subprocess.run(cmd, capture_output=True, text=True) stderr = result.stderr silences = [] starts = re.findall(r"silence_start: ([\d.]+)", stderr) ends = re.findall(r"silence_end: ([\d.]+)", stderr) for i, start in enumerate(starts): end = ends[i] if i < len(ends) else None silences.append({ "start": float(start), "end": float(end) if end else None, }) return silences def get_duration(input_file: str) -> float: """Get total duration of the video in seconds.""" cmd = [ "ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", input_file ] result = subprocess.run(cmd, capture_output=True, text=True) info = json.loads(result.stdout) return float(info["format"]["duration"]) def compute_nonsilent_segments( silences: list[dict], total_duration: float, padding: float ) -> list[tuple[float, float]]: """Invert silence intervals to get non-silent segments. Args: silences: List of silence intervals with start/end. total_duration: Total video duration. padding: Seconds of padding to keep around each non-silent segment (prevents hard cuts on speech boundaries). """ if not silences: return [(0, total_duration)] segments = [] prev_end = 0.0 for s in silences: silence_start = s["start"] silence_end = s["end"] if s["end"] is not None else total_duration # Add padding: extend non-silent segment slightly into the silence seg_start = max(0, prev_end - padding) seg_end = min(total_duration, silence_start + padding) if seg_end > seg_start + 0.05: # skip tiny segments segments.append((seg_start, seg_end)) prev_end = silence_end # Trailing non-silent segment after last silence seg_start = max(0, prev_end - padding) if total_duration > seg_start + 0.05: segments.append((seg_start, total_duration)) # Merge overlapping segments merged = [] for seg in sorted(segments): if merged and seg[0] <= merged[-1][1]: merged[-1] = (merged[-1][0], max(merged[-1][1], seg[1])) else: merged.append(seg) return merged def export_video( input_file: str, segments: list[tuple[float, float]], output_file: str ) -> None: """Cut and concatenate non-silent segments using FFmpeg. Uses trim/atrim filters for frame-accurate cuts with proper A/V sync. Re-encodes the video (necessary for precise, non-keyframe-aligned cuts). """ if not segments: print("No non-silent segments found. The entire video appears silent.") sys.exit(1) # Build a single filtergraph: trim each segment, then concat all filter_parts = [] concat_inputs = [] for i, (start, end) in enumerate(segments): filter_parts.append( f"[0:v]trim=start={start:.3f}:end={end:.3f},setpts=PTS-STARTPTS[v{i}];" f"[0:a]atrim=start={start:.3f}:end={end:.3f},asetpts=PTS-STARTPTS[a{i}];" ) concat_inputs.app