Skip to main content

Black-frame video trimmer: detect long black + silent stretches and remove all but the first moment of each.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bfvt-0.1.0.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bfvt-0.1.0-py3-none-any.whl (16.6 kB view details)

Uploaded Python 3

File details

Details for the file bfvt-0.1.0.tar.gz.

File metadata

  • Download URL: bfvt-0.1.0.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for bfvt-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8b06cabdfa0949b98b46ab231f9d3b122e55824f8d1b8fac6fb600e78c3f3225
MD5 f830a10111d0315332948ff5f3b8921e
BLAKE2b-256 37707e95a2dbbdcf17bb8c5e737691673c8f46f33fa96df1825e32537afdc510

See more details on using hashes here.

File details

Details for the file bfvt-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: bfvt-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for bfvt-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ad254b4f34c923237c5eaa3219402b8ebcdd6cb32fda6997847c64ed7d7b695c
MD5 1dde197634029e837a359838ef3e5f0f
BLAKE2b-256 ad23c029f710dc65e205b906a5b59ed78f480b52425c9c521ac018493e552892

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page