Configuration¶
VBC can be configured via YAML files and CLI arguments. CLI arguments always override config file settings.
Configuration File¶
Default location: conf/vbc.yaml
Demo Configuration¶
Demo mode uses a separate simulation file: conf/demo.yaml.
This file controls simulated file counts, size distribution, processing speed, and error mix.
Full Example¶
input_dirs:
- path: /path/to/videos
enabled: true
- path: /path/to/folder with spaces
enabled: true
- path: /path/to/disabled-folder
enabled: false
# When using output_dirs, set suffix_output_dirs to null.
output_dirs:
- /path/to/videos_out
- /path/to/folder with spaces_out
suffix_output_dirs: null
# When using errors_dirs, set suffix_errors_dirs to null.
errors_dirs:
- /path/to/videos_err
- /path/to/folder with spaces_err
suffix_errors_dirs: null
general:
# === Core Settings ===
threads: 8 # Max concurrent compression threads (>0; executor max_workers=16)
prefetch_factor: 1 # Submit-on-demand multiplier (>=1)
gpu: true # Use GPU (NVENC) vs CPU (SVT-AV1)
queue_sort: name # Queue order: name, rand, dir, size, size-asc, size-desc, ext
queue_seed: null # Optional seed for deterministic rand order
log_path: /tmp/vbc/compression.log # Log file location
cpu_fallback: false # Retry on CPU if NVENC hits HW cap error
ffmpeg_cpu_threads: null # Max CPU threads per ffmpeg worker (null = auto)
# === Input/Output ===
extensions: # File extensions to process
- ".mp4"
- ".mov"
- ".avi"
- ".flv"
- ".webm"
min_size_bytes: 1048576 # Minimum file size (1 MiB)
# === Metadata ===
copy_metadata: true # Copy EXIF/XMP tags from source
use_exif: true # Use ExifTool for deep metadata analysis
# === Filtering ===
skip_av1: false # Skip files already encoded in AV1
filter_cameras: [] # Only process specific camera models (empty = all)
# Example: ["ILCE-7RM5", "DJI OsmoPocket3"]
# === Quality Control ===
dynamic_quality: # Camera-specific quality rules
"ILCE-7RM5":
cq: 38 # CQ mode override
rate: # Optional rate override
bps: "0.8"
minrate: "0.7"
maxrate: "0.9"
"DC-GH7":
cq: 40
"DJI OsmoPocket3":
cq: 45
rate:
bps: "180M"
quality_mode: cq # cq (default) or rate
bps: null # e.g. 200Mbps, 200M, 200000k, 0.8
minrate: null # optional; same class as bps
maxrate: null # optional; same class as bps
rate_target_max_bps: null # optional hard cap for resolved target bitrate (absolute only)
min_compression_ratio: 0.1 # Minimum savings required (0.0-1.0)
# If compression < 10%, keep original
# === Error Handling ===
clean_errors: false # Remove .err markers on startup
verify_fail_action: false # false | log | pause | exit
# === UI/Display ===
strip_unicode_display: true # Replace emoji/unicode with '?' in UI
debug: false # Enable verbose debug logging
# === Manual Rotation ===
manual_rotation: null # Global rotation (null, 0, 90, 180, 270)
gpu_config:
enabled: true
sample_interval_s: 5.0
history_window_s: 300.0
nvtop_device_index: 0
gpu_encoder:
advanced: false
common_args:
- "-c:v av1_nvenc"
- "-preset p7"
- "-tune hq"
- "-b:v 0"
- "-cq 45"
- "-f mp4"
advanced_args:
- "-c:v av1_nvenc"
- "-preset p7"
- "-tune hq"
- "-b:v 0"
- "-cq 45"
- "-rc vbr"
- "-multipass fullres"
- "-rc-lookahead 32"
- "-spatial-aq 1"
- "-temporal-aq 1"
- "-aq-strength 8"
- "-b_ref_mode middle"
- "-f mp4"
cpu_encoder:
advanced: false
common_args:
- "-c:v libsvtav1"
- "-preset 6"
- "-crf 32"
- "-svtav1-params tune=0:enable-overlays=1"
- "-f mp4"
advanced_enforce_input_pix_fmt: true
advanced_args:
- "-c:v libaom-av1"
- "-crf 30"
- "-b:v 0"
- "-cpu-used 0"
- "-tune ssim"
- "-lag-in-frames 35"
- "-aq-mode 1"
- "-row-mt 1"
- "-threads 0"
- "-f matroska"
ui:
activity_feed_max_items: 5
panel_height_scale: 0.7
autorotate:
patterns: # Regex -> Rotation angle
"DJI_.*\\.MP4": 0 # DJI drones - no rotation
"GOPR\\d+\\.MP4": 180 # GoPro pattern - 180° flip
"IMG_\\d{4}\\.MOV": 90 # iPhone pattern - 90° rotation
Configuration Reference¶
General Settings¶
threads¶
- Type: Integer (>0)
- Default: 1
- Description: Maximum number of concurrent compression threads
- Note: Runtime keyboard adjustment (
</>) clamps to 1-8 threads - Implementation detail: Worker pool is created with
max_workers=16, so practical upper parallelism is 16
Quality Defaults¶
- Source: Encoder args (
gpu_encoder/cpu_encoder) via-cq(GPU) or-crf(CPU) - Override:
--qualityCLI flag orgeneral.dynamic_qualitymappings - Recommendation ranges (0-63, lower = better quality):
- 35-38: Archival quality
- 40-45: High quality daily use
- 48-52: Good quality, smaller files
- 55+: Low quality, very small files
prefetch_factor¶
- Type: Integer (>=1)
- Default: 1
- Description: Submit-on-demand queue multiplier. Higher values = more files queued.
- Formula:
max_queued = prefetch_factor × threads
queue_sort¶
- Type: String
- Default:
name - Description: Processing order for files in the queue
- Values:
name,rand,dir,size,size-asc,size-desc,ext - Notes:
sizeis an alias forsize-ascrandcan be made deterministic withqueue_seedextuses the order ofextensionsand requires a non-empty list
queue_seed¶
- Type: Integer or null
- Default:
null - Description: Seed for deterministic
randqueue order - Example:
42(ensure same random order across runs)
log_path¶
- Type: String or null
- Default:
/tmp/vbc/compression.log - Description: Path to log file (overrides the output directory default)
- Note: If set to
null, logs are written to<output_dir>/compression.log.
cpu_fallback¶
- Type: Boolean
- Default: false
- Description: Retry on CPU when GPU encoding fails with hardware capability errors
- Note: Useful when NVENC runs out of sessions; pair with
ffmpeg_cpu_threads - Behavior: HW cap
.errmarkers are cleared on startup so files re-enter the queue
ffmpeg_cpu_threads¶
- Type: Integer or null
- Default:
null - Description: Max CPU threads per ffmpeg worker when using CPU encoding (including fallback)
- Note: Limits per-worker CPU usage; does not change
threads(worker count)
gpu¶
- Type: Boolean
- Default: true
- Description: Use GPU (NVENC) instead of CPU (SVT-AV1)
- GPU (NVENC):
- Pros: Very fast, good for 1080p/1440p
- Cons: Quality ceiling at ~CQ35-38, session limits
- CPU (SVT-AV1):
- Pros: Excellent quality, no session limits
- Cons: Much slower
gpu_refresh_rate¶
- Type: Integer
- Default:
5 - Description: (Deprecated) Use
gpu_config.sample_interval_sinstead. Kept for backwards compatibility. - Note: See deprecation notice in GPU Monitoring section
GPU Monitoring (gpu_config)¶
Advanced settings for GPU monitoring sparklines.
enabled¶
- Type: Boolean
- Default:
true - Description: Enable GPU monitoring and dashboard sparklines.
- Note: Requires NVIDIA GPU and
nvtop(VBC callsnvtop -s).nvidia-smiis only for driver checks.
sample_interval_s¶
- Type: Float
- Default:
5.0 - Description: How often to sample GPU metrics (seconds).
history_window_s¶
- Type: Float
- Default:
300.0 - Description: Total time window shown in sparklines (default 5 minutes).
nvtop_device_index¶
- Type: Integer
- Default:
0 - Description: Index of the GPU to monitor when multiple GPUs are present.
nvtop_device_name¶
- Type: String or null
- Default:
null - Description: Override device selection by name instead of index (e.g., "NVIDIA GeForce RTX 4090").
- Note: When set, takes precedence over
nvtop_device_index.
nvtop_path¶
- Type: String or null
- Default:
null - Description: Custom path to nvtop binary (e.g., "/usr/local/bin/nvtop"). Auto-detected if not set.
- Note: Useful when multiple nvtop versions are installed or nvtop is in a non-standard location.
refresh_rate¶
- Type: Integer
- Default:
5 - Description: (Deprecated) Use
sample_interval_sinstead. Kept for backwards compatibility.
Deprecated Fields
gpu_config.refresh_rateis deprecated in favor ofsample_interval_sgeneral.gpu_refresh_rateis deprecated in favor ofgpu_config.sample_interval_s
For backwards compatibility, VBC still accepts both old fields, but new configurations should use gpu_config.sample_interval_s.
GPU Encoder (gpu_encoder)¶
Encoder args are full FFmpeg argument lists. VBC uses one list:
common_args when advanced=false, otherwise advanced_args. Lists are not merged.
advanced¶
- Type: Boolean
- Default: false
- Description: Use
advanced_argsinstead ofcommon_args.
common_args¶
- Type: List of strings
- Default: NVENC baseline (
-c:v av1_nvenc,-preset p7,-tune hq,-b:v 0,-cq 45,-f mp4) - Description: Full FFmpeg arg list for standard GPU encoding.
advanced_args¶
- Type: List of strings
- Default: NVENC HQ set (adds
-rc vbr,-multipass fullres, AQ, lookahead, etc.) - Description: Full FFmpeg arg list for advanced GPU encoding.
CPU Encoder (cpu_encoder)¶
advanced¶
- Type: Boolean
- Default: false
- Description: Use
advanced_argsinstead ofcommon_args.
common_args¶
- Type: List of strings
- Default: SVT-AV1 baseline (
-c:v libsvtav1,-preset 6,-crf 32,-f mp4) - Description: Full FFmpeg arg list for standard CPU encoding.
advanced_enforce_input_pix_fmt¶
- Type: Boolean
- Default: true
- Description: When
advanced=true, force output-pix_fmtto match the input (from ffprobe).
advanced_args¶
- Type: List of strings
- Default: AOM AV1 HQ set (
-c:v libaom-av1,-crf 30,-cpu-used 0,-tune ssim, etc.) - Description: Full FFmpeg arg list for advanced CPU encoding (often outputs
-f matroska, so.mkv).
UI Configuration (ui)¶
Dashboard display settings.
activity_feed_max_items¶
- Type: Integer (1-20)
- Default:
5 - Description: Maximum number of events shown in the activity feed panel.
active_jobs_max_display¶
- Type: Integer (1-16)
- Default:
8 - Description: Maximum number of concurrent jobs to display in the active panel.
panel_height_scale¶
- Type: Float (0.3-1.0)
- Default:
0.7 - Description: Vertical scaling factor for panels (0.7 = 30% reduction in height).
Input/Output¶
input_dirs¶
- Type: List of objects (
{path: string, enabled: bool}) - Default:
[](empty) - Description: Ordered input directory entries used when no CLI input is provided
- Behavior:
- CLI input overrides config input (no merge)
- Only entries with
enabled: trueare processed - UI order is exactly the same as YAML order
- Duplicate
pathvalues are rejected (startup validation error) - Missing or inaccessible directories are skipped
- Startup fails if no valid directories remain
- Limits: max 50 enabled directories, max 150 characters per path
output_dirs¶
- Type: List of strings
- Default:
[](empty) - Description: Explicit output directories (one per enabled input directory, in order)
- Rules:
- Must exist and be writable
- Count must match enabled input directories
- Cannot be used with
suffix_output_dirs(set it tonull)
suffix_output_dirs¶
- Type: String or null
- Default:
_out - Description: Output directory suffix appended to each input directory name
- Notes:
- Set to
nullwhen usingoutput_dirs - Example:
/videos→/videos_out
errors_dirs¶
- Type: List of strings
- Default:
[](empty) - Description: Explicit directories for failed files (one per enabled input directory, in order)
- Rules:
- Must exist and be writable
- Count must match enabled input directories
- Cannot be used with
suffix_errors_dirs(set it tonull)
suffix_errors_dirs¶
- Type: String or null
- Default:
_err - Description: Suffix appended to each input directory name for failed files
- Behavior: After processing, failed source files and their
.errmarkers are moved here - Safety: If more than 100
.errfiles are found, VBC asks before moving them - Notes:
- Set to
nullwhen usingerrors_dirs - Example:
/videos→/videos_err
extensions¶
- Type: List of strings
- Default:
[".mp4", ".mov", ".avi", ".flv", ".webm"] - Description: File extensions to scan and process
- Note: Case-insensitive, can include or omit leading dot
min_size_bytes¶
- Type: Integer
- Default: 1048576 (1 MiB)
- Description: Minimum input file size to process
- Use case: Skip corrupted/incomplete files
Metadata¶
copy_metadata¶
- Type: Boolean
- Default: true
- Description: Copy EXIF/XMP/GPS tags from source to output
- Method: Uses ExifTool to preserve all metadata including GPS
use_exif¶
- Type: Boolean
- Default: true
- Description: Enable deep metadata analysis with ExifTool
- Required for:
dynamic_quality(camera-specific quality)filter_cameras(camera filtering)- GPS and camera model extraction
Filtering¶
skip_av1¶
- Type: Boolean
- Default: false
- Description: Skip files already encoded in AV1 codec
- Use case: Mixed libraries with some AV1 files already compressed
filter_cameras¶
- Type: List of strings
- Default:
[](empty = process all cameras) - Description: Only process files from specific camera models
- Example:
["ILCE-7RM5", "DJI OsmoPocket3"] - Matching: Case-insensitive substring against extracted camera metadata; exact model strings are most reliable.
Quality Control¶
dynamic_quality¶
- Type: Dictionary (string -> object)
- Default:
{}(empty) - Description: Camera model -> quality rule mapping.
- Matching: Full-text search in all EXIF metadata
- Example:
- Priority: First match wins (order matters in YAML)
- Required schema: each entry must be an object with
cq; legacy scalar format ("Sony": 40) is rejected.
quality_mode¶
- Type: String
- Default:
cq - Values:
cq,rate - Description:
cq: use encoder quality args (-cqon GPU,-crfon CPU)rate: use bitrate target (bps) with optionalminrate/maxrate- CLI validation rules:
--qualityis valid only forquality_mode=cq--bps/--minrate/--maxraterequirequality_mode=rate
bps¶
- Type: String or null
- Default:
null - Description: Target bitrate for
quality_mode=rate. - Accepted formats:
- Absolute:
200000000,200000k,200M,200Mbps - Relative:
0.8(input bitrate × 0.8)
minrate¶
- Type: String or null
- Default:
null - Description: Optional lower bitrate bound in
ratemode. - Rule: Must use the same numeric class as
bps(all absolute or all relative).
maxrate¶
- Type: String or null
- Default:
null - Description: Optional upper bitrate bound in
ratemode. - Rule: Must use the same numeric class as
bpsandminrate.
rate_target_max_bps¶
- Type: String or null
- Default:
null - Description: Optional hard cap applied after
bps/minrate/maxrateresolution inratemode. - Accepted formats: Absolute only (
95M,100Mbps,100000k,100000000). - Scope:
- Global:
general.rate_target_max_bps - Per camera override:
general.dynamic_quality.<pattern>.rate.rate_target_max_bps - Note: This caps target bitrate; it does not guarantee peak bitrate.
min_compression_ratio¶
- Type: Float (0.0-1.0)
- Default: 0.1 (10%)
- Description: Minimum compression savings required
- Behavior: If
(1 - output_size/input_size) < threshold, keep original file instead of compressed version - Use case: Prevent "compression" that makes files larger
Error Handling¶
clean_errors¶
- Type: Boolean
- Default: false
- Description: Remove existing
.errmarkers on startup and retry those files - Behavior:
false: Skip files with.errmarkerstrue: Delete.errfiles and retry compression
verify_fail_action¶
- Type: String
- Default:
false - CLI:
--verify-fail-action - Values:
false: disable output verificationlog: mark job as failed and continuepause: mark job as failed and pause queue withERRORstatus (wait forR/S)exit: mark job as failed and terminate processing with error- Verification checks (when mode is not
false): ffprobecan read output without errors- VBC tags exist:
VBCOriginalName,VBCOriginalSize,VBCQuality,VBCOriginalBitrate,VBCEncoder,VBCFinishedAt
repair_corrupted_flv¶
- Type: Boolean
- Default: false
- Description: Attempt to repair corrupted FLV files using FFmpeg
- Behavior:
true: When a file fails processing and is moved to errors folder, attempts to repair itfalse: No repair attempt
wait_on_finish¶
- Type: Boolean
- Default: false
- CLI:
--wait/--no-wait - Description: After all tasks complete, wait for user input instead of auto-exiting
- Behavior:
true: Displays WAITING status; press R to restart scan or S/Ctrl+C to exitfalse: VBC exits automatically when processing finishes
bell_on_finish¶
- Type: Boolean
- Default: false
- CLI:
--bell/--no-bell - Description: Play a terminal bell (BEL character) as a completion notification
- Triggers:
- When entering wait state (if
wait_on_finish=true) - Just before exit (if
wait_on_finish=false) - After FLV repair completes with at least one repaired file
UI/Display¶
strip_unicode_display¶
- Type: Boolean
- Default: true
- Description: Replace non-ASCII characters (emoji, special Unicode) with '?' in UI
- Reason: Prevents table alignment issues with emoji in filenames
debug¶
- Type: Boolean
- Default: false
- Description: Enable verbose debug logging
- Logs: FFmpeg timing, ExifTool calls, compression stages
manual_rotation¶
- Type: Integer or null
- Default: null
- Values: null, 0, 90, 180, 270
- Description: Global rotation override (takes precedence over
autorotate)
Auto-Rotation¶
patterns¶
- Type: Dictionary (regex -> angle)
- Default:
{} - Description: Filename regex patterns mapped to rotation angles
- Example:
- Note: First match wins (order matters)
CLI Overrides¶
Only a subset of config keys can be overridden via CLI flags:
general.threads→--threads- encoder CQ/CRF value →
--quality(only whenquality_mode=cq) general.quality_mode→--quality-modegeneral.bps,general.minrate,general.maxrate→--bps,--minrate,--maxrate(only whenquality_mode=rate)general.gpu→--gpu/--cpugeneral.queue_sort,general.queue_seed→--queue-sort,--queue-seedgeneral.log_path→--log-pathgeneral.clean_errors→--clean-errorsgeneral.verify_fail_action→--verify-fail-actiongeneral.skip_av1→--skip-av1general.min_size_bytes→--min-sizegeneral.min_compression_ratio→--min-ratiogeneral.filter_cameras→--camerageneral.manual_rotation→--rotate-180general.debug→--debuggeneral.wait_on_finish→--wait/--no-waitgeneral.bell_on_finish→--bell/--no-bell
Other settings (for example prefetch_factor, dynamic_quality, encoder arg lists, directory mappings, and gpu_config) must be set in YAML.
# Override threads and quality
uv run vbc /videos --threads 8 --quality 38
# Override GPU setting
uv run vbc /videos --cpu # Force CPU mode
# Override camera filtering
uv run vbc /videos --camera "ILCE-7RM5,DJI"
# Override multiple settings
uv run vbc /videos \
--config custom.yaml \
--threads 8 \
--quality 40 \
--gpu \
--skip-av1 \
--clean-errors \
--min-size 5242880 \
--rotate-180 \
--debug
Local Overrides (VBC.YAML)¶
VBC scans input directories for VBC.YAML and applies the nearest ancestor file per job.
Priority: Global config → Local VBC.YAML → CLI.
Allowed root keys: general, gpu_encoder, cpu_encoder, autorotate, cq.
Allowed general keys: gpu, cpu_fallback, ffmpeg_cpu_threads, copy_metadata,
use_exif, filter_cameras, dynamic_quality, quality_mode, bps, minrate, maxrate, rate_target_max_bps,
extensions, min_size_bytes, clean_errors, verify_fail_action, skip_av1, manual_rotation,
min_compression_ratio, debug.
Special key: cq (int 0–63) overrides quality for both GPU and CPU encoder args.
Environment-Specific Configs¶
You can maintain multiple config files:
# Production (high quality, slow)
uv run vbc /videos --config conf/production.yaml
# Fast preview (low quality, fast)
uv run vbc /videos --config conf/preview.yaml
# Archival (maximum quality)
uv run vbc /videos --config conf/archive.yaml
Example conf/archive.yaml:
general:
threads: 4
gpu: false # CPU for best quality
copy_metadata: true
use_exif: true
min_compression_ratio: 0.05 # Must save at least 5%
cpu_encoder:
common_args:
- "-crf 30" # Very high quality
Validation¶
VBC uses Pydantic for config validation. Invalid settings will raise errors on startup:
# Invalid threads (must be > 0)
Error: threads must be greater than 0
# Invalid rotation angle
Error: Invalid rotation angle 45. Must be 0, 90, 180, or 270.
Next Steps¶
- Runtime Controls - Keyboard shortcuts
- Advanced Features - Dynamic Quality, auto-rotation
- Architecture Overview - How config is loaded