8.2 KiB
8.2 KiB
VMAF Optimiser - Agent Guidelines
Quick Reference
Purpose: Video library optimization pipeline using VMAF quality targets with AV1 encoding.
Core Files:
optimize_library.py- Main Python script (342 lines)run_optimisation.sh- Linux/macOS wrapperrun_optimisation.ps1- Windows wrapper
Build/Lint/Test Commands
Development Setup
# Install dependencies (if not already)
cargo install ab-av1 # v0.10.3+
brew install ffmpeg # macOS
# OR: apt install ffmpeg # Linux/WSL
# OR: winget install ffmpeg # Windows
Linting
# Ruff is the linter (indicated by .ruff_cache/)
ruff check optimize_library.py
# Format with ruff
ruff format optimize_library.py
# Check specific issues
ruff check optimize_library.py --select E,F,W
Running the Application
# Linux/macOS
./run_optimisation.sh --directory /media --vmaf 95 --workers 1
# Windows
.\run_optimisation.ps1 -directory "D:\Movies" -vmaf 95 -workers 1
# Direct Python execution
python3 optimize_library.py /media --vmaf 95 --preset 6 --workers 1
Testing
No formal test suite exists currently. Test manually by:
# Test with single video file
python3 optimize_library.py /media/sample.mkv --vmaf 95 --workers 1
# Dry run (validate logic without encoding)
python3 optimize_library.py /media --vmaf 95 --thorough
# Check dependencies
python3 optimize_library.py 2>&1 | grep -E "(ffmpeg|ab-av1)"
Code Style Guidelines
Python Style (PEP 8 Compliant)
Imports:
# Standard library first, grouped logically
import os
import sys
import subprocess
import json
import shutil
import platform
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
Naming Conventions:
# Constants: UPPER_SNAKE_CASE
DEFAULT_VMAF = 95.0
DEFAULT_PRESET = 6
EXTENSIONS = {".mkv", ".mp4", ".mov", ".avi", ".ts"}
# Functions: snake_case
def get_video_info(filepath):
def build_ab_av1_command(input_path, output_path, args):
# Variables: snake_case
input_path = Path(filepath)
output_path = input_path.with_stem(input_path.stem + "_av1")
# Module-level cache: _PREFIX (private)
_AB_AV1_HELP_CACHE = {}
Formatting:
- 4-space indentation
- Line length: ~88-100 characters (ruff default: 88)
- No trailing whitespace
- One blank line between functions
- Two blank lines before class definitions (if any)
Function Structure:
def function_name(param1, param2, optional_param=None):
"""Brief description if needed."""
try:
# Implementation
return result
except Exception as e:
print(f"Error: {e}")
return None # or handle gracefully
Subprocess Calls:
# Use subprocess.run for all external commands
cmd = ["ffmpeg", "-i", input_file, output_file]
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
# Check return codes explicitly
if result.returncode != 0:
print(f"Command failed: {result.stderr}")
Error Handling
# Always wrap external tool calls in try-except
try:
info = get_video_info(filepath)
if not info:
return # Early return on None
except subprocess.CalledProcessError as e:
print(f"FFmpeg failed: {e}")
return
# Use specific exception types when possible
except FileNotFoundError:
print("File not found")
except json.JSONDecodeError:
print("Invalid JSON")
Platform Detection
# Use platform module for OS detection
def is_wsl():
if os.environ.get("WSL_DISTRO_NAME"):
return True
try:
with open("/proc/sys/kernel/osrelease", "r") as f:
return "microsoft" in f.read().lower()
except FileNotFoundError:
return False
def platform_label():
system = platform.system()
if system == "Linux" and is_wsl():
return "Linux (WSL)"
return system
Argument Parsing
def main():
parser = argparse.ArgumentParser(description="Description")
parser.add_argument("directory", help="Root directory")
parser.add_argument("--vmaf", type=float, default=95.0, help="Target VMAF")
args = parser.parse_args()
Shell Script Guidelines (run_optimisation.sh)
Shebang & Error Handling:
#!/bin/bash
set -e # Exit on error
Color Output:
COLOR_RED='\033[0;31m'
COLOR_GREEN='\033[0;32m'
COLOR_CYAN='\033[0;36m'
COLOR_RESET='\033[0m'
log_info() {
echo -e "${COLOR_CYAN}$*${COLOR_RESET}"
}
log_error() {
echo -e "${COLOR_RED}ERROR: $*${COLOR_RESET}" >&2
}
Argument Parsing:
while [[ $# -gt 0 ]]; do
case "$1" in
--vmaf)
VMAF="$2"
shift 2
;;
*)
DIRECTORY="$1"
shift
;;
esac
done
PowerShell Guidelines (run_optimisation.ps1)
Parameter Declaration:
param(
[Parameter(Mandatory=$false)]
[string]$Directory = ".",
[float]$Vmaf = 95.0,
[switch]$Thorough
)
Error Handling:
$ErrorActionPreference = "Stop"
function Write-ColorOutput {
param([string]$Message, [string]$Color = "White")
Write-Host $Message -ForegroundColor $Color
}
Process Management:
$process = Start-Process -FilePath $pythonCmd.Path -ArgumentList $arguments `
-NoNewWindow -PassThru
$process.WaitForExit()
$exitCode = $process.ExitCode
Key Constraints & Best Practices
When Modifying optimize_library.py
- Maintain platform compatibility: Always test on Linux, Windows, and macOS
- Preserve subprocess patterns: Use
subprocess.runwithcheck=True - Handle missing dependencies: Check
shutil.which()before running tools - Thread safety: The script uses
ThreadPoolExecutor- avoid global state - Path handling: Always use
Pathobjects frompathlib
When Modifying Wrapper Scripts
- Keep interfaces consistent: Both scripts should accept the same parameters
- Preserve color output: Users expect colored status messages
- Validate Python path: Handle
python3vspythonvspy - Check script existence: Verify
optimize_library.pyexists before running
File Organization
- Keep functions under 50 lines
- Use descriptive names (no abbreviations like
proc_file, useprocess_file) - Cache external command help text (see
_AB_AV1_HELP_CACHE) - Use constants for magic numbers and strings
Hardware Acceleration
- Auto-detect via
normalize_hwaccel()function - Respect
--hwaccelflag - Check ab-av1 support with
ab_av1_supports()before using flags - Default:
auto(d3d11va on Windows, videotoolbox on macOS, vaapi on Linux)
Common Patterns
Checking Tool Availability
def check_dependencies():
missing = []
for tool in ["ffmpeg", "ffprobe", "ab-av1"]:
if not shutil.which(tool):
missing.append(tool)
if missing:
print(f"Error: Missing tools: {', '.join(missing)}")
sys.exit(1)
Building Commands Conditionally
cmd = ["ab-av1", "auto-encode", "-i", input_path]
if args.encoder:
if ab_av1_supports("auto-encode", "--encoder"):
cmd.extend(["--encoder", args.encoder])
else:
print("Warning: Encoder not supported")
File Path Operations
# Use pathlib for cross-platform paths
input_path = Path(filepath)
output_path = input_path.with_stem(input_path.stem + "_av1")
# Safe existence check
if output_path.exists():
print(f"Skipping: {input_path.name}")
return
Version Control
# Check for changes
git status
# Format before committing
ruff format optimize_library.py
ruff check optimize_library.py
# Commit with conventional commits
git commit -m "feat: add hardware acceleration support"
git commit -m "fix: handle missing ffprobe gracefully"
git commit -m "docs: update setup instructions"
Important Notes
- No type hints: Current codebase doesn't use Python typing
- No formal tests: Test manually with sample videos
- No package.json: This is a standalone script, not a Python package
- Lock files:
.lock/directory created at runtime for multi-machine coordination - Logs: JSONL format in
logs/directory for structured data
Last Updated: December 31, 2025