Skip to main content

bfvt — black-frame video trimmer

Scan a video, find long stretches that are simultaneously black and silent, and remove all but the first moment of each — then write a re-encoded, trimmed file. Built for chopping the dead air out of recordings: the leader/trailer black, the gap between segments, the "I forgot to stop the screen recorder" tail.

Tiny stray bright pixels (codec ringing, a dead-pixel speck, a faint watermark) are still treated as black, so a frame doesn't get disqualified just because a handful of pixels aren't perfectly #000000.

How it decides what to cut

  1. Black detection (OpenCV). Frames are sampled (default 10 fps). A frame counts as black when the fraction of pixels brighter than a luma threshold is at or below a small ratio (default 0.2%) — that ratio is the "ignore stray pixels" knob.
  2. Silence detection (ffmpeg silencedetect). Audio below a noise floor (default −30 dB) is silence. Videos with no audio track are treated as wholly silent, so black detection alone drives the cut.
  3. Interval algebra (pure, deterministic). The black intervals are intersected with the silent intervals. Each overlapping run that lasts at least --min-duration (default 5 s) is trimmed, keeping the first --keep-head seconds (default 0.25 s) so a hard chapter cut doesn't become a jarring jump. Everything else in the run is removed.
  4. Re-encode (ffmpeg). The kept segments are concatenated via a trim/atrim + concat filtergraph and re-encoded (libx264 + AAC).

Given the same input and flags, the output is deterministic.

Install

pip install .
# or, for development + tests:
pip install -e ".[test]"

Requires ffmpeg and ffprobe on PATH. OpenCV is pulled in via opencv-python-headless.

Usage

# Trim, writing alongside the input as <name>.trimmed.mp4
bfvt input.mp4

# Choose the output and the threshold
bfvt input.mp4 -o clean.mp4 --min-duration 5 --keep-head 0.25

# See what WOULD be cut without re-encoding
bfvt input.mp4 --dry-run

# Trim on darkness alone (ignore audio)
bfvt input.mp4 --ignore-audio

Key options

Flag Default Meaning
--min-duration SEC 5.0 Minimum black+silent run before anything is trimmed
--keep-head SEC 0.25 Seconds at the start of each run to preserve
--luma-threshold N 32 0–255 luma above which a pixel is "bright"
--bright-ratio R 0.002 Max fraction of bright pixels for a frame to still be black
--sample-fps FPS 10 Frame sampling rate for black detection
--noise-db DB -30 Audio below this dB is silence
--ignore-audio off Trim on darkness only
--crf / --preset 18 / medium libx264 quality/speed
--dry-run off Report cuts, write nothing

Library

from bfvt import TrimConfig, analyze, run

cfg = TrimConfig(min_duration=5.0, keep_head=0.25)
res = analyze("input.mp4", cfg)      # inspect res.black / res.silent / res.cuts
run("input.mp4", "out.mp4", cfg)     # do the trim

The interval logic is exposed directly (merge_segments, intersect_segments, black_silent_cuts, keep_segments_from_cuts) and is pure/dependency-free.

Tests

pytest -q                  # all tests (integration generates a real clip)
pytest -q -m "not integration"   # pure unit tests only, no ffmpeg/OpenCV needed

The unit tests cover the interval algebra, the black-frame pixel classifier (including the stray-pixel tolerance), the silencedetect log parser, and the ffmpeg filtergraph builder. The integration test synthesizes a blue → black/silent → green clip with ffmpeg, runs the whole pipeline, and asserts the black stretch is detected and removed.

License

MIT — see LICENSE.

Metadata

Release files for bfvt 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bfvt 0.1.0
File Size Uploaded
bfvt-0.1.0.tar.gz 21.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bfvt 0.1.0
File Interpreter ABI Platform
bfvt-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.8 kB

Release files / bfvt-0.1.0.tar.gz

Download URL bfvt-0.1.0.tar.gz
Size 21.2 kB
Tags Source
SHA-256 checksum
How to use checksums
8b06cabdfa0949b98b46ab231f9d3b122e55824f8d1b8fac6fb600e78c3f3225
BLAKE2b-256 checksum
How to use checksums
37707e95a2dbbdcf17bb8c5e737691673c8f46f33fa96df1825e32537afdc510
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / bfvt-0.1.0-py3-none-any.whl

Download URL bfvt-0.1.0-py3-none-any.whl
Size 16.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ad254b4f34c923237c5eaa3219402b8ebcdd6cb32fda6997847c64ed7d7b695c
BLAKE2b-256 checksum
How to use checksums
ad23c029f710dc65e205b906a5b59ed78f480b52425c9c521ac018493e552892
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page