Skip to main content

Vid Cleaner

Changelog PyPI version PyPI - Python Version Tests codecov

Tools to transcode, inspect and convert videos. This package provides convenience wrappers around ffmpeg and ffprobe to make it easier to work with video files. The functionality is highly customized to my personal workflows and needs. I am sharing it in case it is useful to others.

Features

  • Remove unwanted audio and subtitle tracks, optionally keeping the original language audio track
  • Remove commentary, SDH, and description tracks
  • Determine a video's original language from its filename, its container metadata, or the TMDb, Radarr, and Sonarr APIs
  • Convert to H.265 or VP9
  • Convert 4k to 1080p
  • Downmix any surround layout (5.1, 7.1, and Atmos above 7.1) into a stereo track when one is missing, or recreate an existing stereo track with --force, using a dialogue-forward filter that keeps speech clear
  • Inspect the streams in a video file
  • Create clips from a video file
  • Search for video files under a directory that match specific criteria
  • Check that video files are valid, and exit non-zero when any file is not

Install

Before installing vid-cleaner, the following dependencies must be installed:

Every command except cache needs ffmpeg and ffprobe. If either program is absent from PATH, the command stops before it reads any file.

To install vid-cleaner, run:

# With uv
uv tool install vid-cleaner

# With pip
python -m pip install --user vid-cleaner

Usage

Run vidcleaner --help to see the available commands and options.

Inspecting a video file

vidcleaner inspect FILE prints a table of the video, audio, and subtitle streams in a file, with the codec, language, and channel layout of each one. Use --json to print the raw ffprobe output instead.

vidcleaner inspect movie.mkv
vidcleaner inspect --json movie.mkv

Searching for video files

vidcleaner search DIRECTORY finds video files under a directory and prints a table of matches. The directory defaults to the current directory. Narrow the search with --filters, control how deep it recurses with --depth, and change the order with --sort and --reverse. Use --limit to keep only the top results on the active sort key:

# The five largest 4k files, two directories deep
vidcleaner search /media --filters=4k --sort=size --depth=2 --limit=5

Listing several filters narrows the search rather than widening it: a file must have every trait you name to be returned.

# Only 4k files that also have a 5.1 track and no stereo track to go with it
vidcleaner search /media --filters=4k,surround5,needs_stereo

Cleaning what you searched for

clean accepts the same query flags as search, so a search command is a preview of the clean command that acts on it. Swap the positional directory for --from:

# Preview
vidcleaner search /media --filters=4k --sort=size --limit=5

# Act on exactly that selection
vidcleaner clean --from /media --filters=4k --sort=size --limit=5 --h265

clean renders the same table search does, then asks for confirmation before transcoding anything. The prompt states whether each original will be backed up or overwritten in place. Pass --yes to skip the prompt in scripts and cron jobs, or --dryrun to preview without being asked. Running without a terminal and without --yes is an error rather than a hang.

--from cannot be combined with explicit file paths or with --out, and must name an existing directory. --yes and the query flags (--filters, --sort, --reverse, --depth, --limit) are only meaningful with --from and are refused without it. --limit must be 1 or greater.

Where the output goes

clean and clip replace the file they were given. The original is not deleted: it is renamed alongside the result as a timestamped .bak copy. Pass --overwrite to skip the backup and rewrite the file in place with no way back, or --out PATH (single input file only) to write somewhere else and leave the input untouched.

--vp9 is the exception, because VP9 has to go in a WebM container. vidcleaner clean --vp9 movie.mkv writes movie.webm next to the input. Without --overwrite the original movie.mkv is left where it is. With --overwrite it is removed, so the container change does not leave two copies of the same film on disk.

When you clean or clip several files, a failure on one file does not stop the run. Every remaining file is still processed, failures are listed at the end, and the command exits with a non-zero status. clean and clip refuse a file that has no video stream, so an audio-only file with a video extension does not produce an output.

Checking that files are valid

vidcleaner check reports whether each video file is valid. If any file is not valid, the command exits 1. Use it to find damaged and mislabeled files in a library.

# Two files named directly
vidcleaner check movie.mkv other.mp4

# Every video file in a library, three levels deep
vidcleaner check --from /media --depth=3

The command prints one line for every file, so one invalid file does not hide the state of the others.

✓ movie.mkv
✗ broken.mkv  Invalid data found when processing input
✗ audiobook.mkv  no video stream
✗ notes.txt  not a video file

Checked 4 file(s): 1 valid, 3 invalid

A file is valid when all of these conditions are true:

  • The file exists.
  • The file has a video container extension.
  • ffprobe can read the file.
  • The file has a minimum of one video stream.

Cover art does not count as a video stream. An audio-only file with an embedded poster is invalid.

The command prints valid files to stdout and invalid files to stderr. To hide the invalid files, run vidcleaner check FILES 2>/dev/null.

By default the command reads only the metadata of each file, which takes milliseconds. To decode every frame instead, use --deep. A deep check finds damage in the body of a file whose header is intact. It costs minutes for each file.

# Fully decode every 4k file to find damage that ffprobe cannot see
vidcleaner check --from /media --filters=4k --deep

check accepts the same query flags as search, but it refuses --limit. A truncated selection can exit 0 while files stay unchecked. A trait filter never hides an invalid file, because a file that ffprobe cannot read has no traits.

Configuration

Defaults for vid-cleaner are set in the configuration file located at ~/.config/vid-cleaner/config.toml. When vid-cleaner is run, it will create this file if it does not exist. All options can be overridden on the command line.

If you've updated your user config file, the flags for the cli will work in reverse order. For example, if you've set downmix_stereo = true in your user config file, the flag --downmix will actually disable downmixing.

Important: Vid-cleaner makes decisions about which audio and subtitle tracks to keep based on the original language of the video. To find that language, it looks for an IMDb or TMDB id in three places, stopping at the first one that resolves:

  1. The filename, matching either a bare tt0245712 or the {tmdb-55} naming convention.
  2. The container's own IMDB and TMDB metadata tags, as written by tools like mkvmerge.
  3. A Radarr or Sonarr title search.

The first two need only tmdb_api_key in the configuration file. Set the radarr_ and sonarr_ keys if you want the title search as a fallback.

# Languages to keep (list of ISO 639-1 codes)
langs_to_keep = ["en"]

# Keep subtitles matching the local language(s) even when the audio is not in the local language(s)
keep_local_subtitles = false

# Keep commentary audio
keep_commentary = false

# Force dropping local subtitles even if audio is not default language
drop_local_subs = false

# Keep all subtitles
keep_all_subtitles = false

# Drop original language audio if not specified in langs_to_keep
drop_original_audio = false

# Always create a stereo track
downmix_stereo = false

# External services used to determine the original language of a movie or TV show
radarr_api_key = ""
radarr_url     = ""
sonarr_api_key = ""
sonarr_url     = ""
tmdb_api_key   = ""

File Locations

Vid-cleaner uses the XDG specification for determining the locations of configuration files, logs, and caches.

  • Configuration file: ~/.config/vid-cleaner/config.toml
  • Cache: ~/.cache/vid-cleaner

Run vidcleaner cache to print the contents of the cache, and vidcleaner cache --clear to empty it.

Contributing

See CONTRIBUTING.md for more information.

Metadata

Release files for vid-cleaner 0.13.1

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

Source distribution (sdist)

Source distribution for vid-cleaner 0.13.1
File Size Uploaded
vid_cleaner-0.13.1.tar.gz 79.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vid-cleaner 0.13.1
File Interpreter ABI Platform
vid_cleaner-0.13.1-py3-none-any.whl Python 3 none any Details

Total release size: 156.5 kB

Release files / vid_cleaner-0.13.1.tar.gz

Download URL vid_cleaner-0.13.1.tar.gz
Size 79.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8e27a418ab56568ecfe70a905d2d05678f4ed2d82af868bae2c13a1a7e8b12a8
BLAKE2b-256 checksum
How to use checksums
d27c144510cfa1fac33bbf259c8b4b2cdce62e998b5177d91a8d10d24dfc457c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / vid_cleaner-0.13.1-py3-none-any.whl

Download URL vid_cleaner-0.13.1-py3-none-any.whl
Size 76.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8018b4775916e0f6811b3a768da7a79d92e67cffe2b97332a5a5e2dc459aa451
BLAKE2b-256 checksum
How to use checksums
8c24b9179cdf7668ed258bf0067c1230d8602f9c9e346474f2c5d3620687d2ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.13.1 This release

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.2

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

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