Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open more actions menu

Repository files navigation

SoftClip - Smart Auto-Clipper

Turns a long video (local file or a YouTube/Twitch/etc. URL) into a batch of vertical 9:16 short clips with face-following crop and TikTok-style burned-in captions.

Pipeline

source (file or URL)
  -> chunk into fixed-length segments
  -> for each chunk:
       - track subject position (Haar-cascade face detection + smoothing)
       - render 9:16 crop that pans to follow the subject
       - transcribe audio (word-level timestamps, faster-whisper, local/CPU)
       - burn in pop-on captions
  -> clips_output/clip_001.mp4, clip_002.mp4, ...

Setup

pip install yt-dlp faster-whisper opencv-python --break-system-packages

You also need ffmpeg and ffprobe on PATH (most systems already have this; sudo apt install ffmpeg on Ubuntu/Debian if not).

First run will download the Whisper model (~150MB for base) from Hugging Face — needs internet access once, then it's cached locally.

Usage

# Local file (active_speaker mode by default — hard cuts to whoever's talking)
python3 main.py my_podcast.mp4

# From YouTube/Twitch/etc.
python3 main.py https://youtube.com/watch?v=XXXXXXXX

# Custom clip length (seconds)
python3 main.py my_podcast.mp4 --clip-length 60

# Cap total output to N clips (stops early, doesn't waste time on the rest)
python3 main.py my_podcast.mp4 --max-clips 5

# Explicitly choose tracking mode
python3 main.py my_podcast.mp4 --track-mode active_speaker   # hard-cut to whoever's talking (default)
python3 main.py my_podcast.mp4 --track-mode smooth_pan       # smooth eased pan that follows a face

# Skip captions (faster, no Whisper needed)
python3 main.py my_podcast.mp4 --no-captions

# Static center crop, no face tracking at all
python3 main.py my_podcast.mp4 --no-facetrack

Output lands in clips_output/clip_001.mp4, clip_002.mp4, etc. Intermediate files (downloads, per-chunk audio, subtitle files) go in work/ — safe to delete after a run, or keep for debugging.

Tuning

Everything adjustable lives in config.py:

Setting What it does
CLIP_LENGTH_SEC length of each output clip
OUTPUT_WIDTH / OUTPUT_HEIGHT output resolution (default 1080x1920)
FACE_TRACK_MODE "active_speaker" (default) or "smooth_pan"
FACE_DETECT_EVERY_N_FRAMES how often to re-run face detection (lower = more accurate, slower)
FACE_SMOOTHING_ALPHA smooth_pan mode only: 0–1, lower = smoother/slower pan
SPEAKER_REEVAL_INTERVAL_SEC active_speaker mode: how often to re-check who's talking and potentially cut (default 2.5s)
SWITCH_CONFIDENCE_MARGIN active_speaker mode: how much clearer a winner needs to be before cutting (1.3 = 30% margin, higher = fewer cuts)
WHISPER_MODEL_SIZE tiny/base/small/medium — bigger = more accurate, slower
CAPTION_MAX_WORDS_PER_CHUNK how many words appear per caption "pop" (1–3 reads best)
CAPTION_FONT_SIZE, CAPTION_FONT_COLOR, etc. caption styling

How the tracking modes work

active_speaker (default): Every SPEAKER_REEVAL_INTERVAL_SEC seconds, it samples several frames from that window, detects all faces, and measures how much each face's mouth region changes frame-to-frame. The face with the most mouth movement wins that window, if it clearly beats the runner-up by SWITCH_CONFIDENCE_MARGIN — otherwise the previous speaker holds to avoid flickering on ambiguous/overlapping speech. When a winner is decided, the crop snaps instantly (hard cut) to center on them and stays there for the whole window.

smooth_pan: Detects the largest face every N frames and eases the crop center toward it with exponential smoothing. Good for single-speaker content; can look floaty on multi-person footage.

Both modes fall back to static center crop if no faces are detected.

Known limitation on detection: Haar cascades are fast and fully offline but not as robust as modern DNN detectors — side profiles, poor lighting, or small/distant faces can be missed. If tracking is unreliable on your footage, the swap point is face_tracker.py's _detect_largest_face and active_speaker_tracker.py's _detect_faces — a MediaPipe or OpenCV DNN detector can drop in without touching the rest of the pipeline.

Known issues / not yet verified

  • Caption burn-in (transcribe.py + captions.py + ffmpeg_utils.burn_captions) is implemented and logically sound but has not been visually verified end-to-end in development — the dev sandbox couldn't reach huggingface.co to download the Whisper model. Run once on a real clip and check the output before relying on it for a batch job.
  • Face tracking quality depends entirely on Haar cascade detection quality on your specific footage — test on a representative sample before processing a large batch.

Files

  • main.py — CLI entry point, orchestrates the pipeline
  • config.py — all tunable settings
  • source_input.py — local file resolution + yt-dlp downloads
  • chunker.py — splits source into fixed-length segments
  • face_tracker.py — Haar-cascade face detection + smoothing
  • crop_render.py — renders 9:16 crop following the tracked path
  • transcribe.py — faster-whisper word-level transcription
  • captions.py — builds ASS subtitle file (pop-on style)
  • ffmpeg_utils.py — audio extraction + caption burn-in helpers

Thank You

About

open source auto clipping project using open-cv and auto transcribe

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.