Processors Module¶
Video processing components for analysis, metadata, and validation.
Codec Detector¶
codec_detector
¶
Video codec detection module using FFprobe.
This module provides codec detection functionality to analyze video files and determine their codec, resolution, and other properties. It is used to identify H.264 videos that need conversion to H.265/HEVC.
SDS Reference: SDS-P01-002 SRS Reference: SRS-201 (Codec Detection)
Example
from video_converter.processors.codec_detector import CodecDetector detector = CodecDetector() info = detector.analyze(Path("vacation.mp4")) print(f"Codec: {info.codec}") # "h264" print(f"Resolution: {info.resolution_label}") # "4K" print(f"Needs conversion: {info.is_h264}") # True
InvalidVideoError
¶
Bases: Exception
Raised when a file is not a valid video.
This error indicates that the file cannot be recognized as a valid video format by FFprobe.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path to the invalid file. |
|
reason |
Explanation of why the file is invalid. |
Source code in src/video_converter/processors/codec_detector.py
CorruptedVideoError
¶
Bases: Exception
Raised when a video file is corrupted or incomplete.
This error indicates that while the file is recognized as a video, it cannot be properly read or is missing critical data.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path to the corrupted file. |
|
reason |
Explanation of the corruption. |
Source code in src/video_converter/processors/codec_detector.py
UnsupportedCodecError
¶
Bases: Exception
Raised when an unknown or unsupported codec is encountered.
This error indicates that the video uses a codec that is not recognized or supported by the converter.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path to the video file. |
|
codec |
The unsupported codec name. |
Source code in src/video_converter/processors/codec_detector.py
CodecInfo
dataclass
¶
CodecInfo(path, codec, width, height, fps, duration, bitrate, size, audio_codec, container, creation_time=None, color_space=None, bit_depth=None, profile=None, level=None)
Video codec and property information.
This class contains detailed information about a video file's codec and properties, used to determine if conversion is needed.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path
|
Path to the video file. |
codec |
str
|
Video codec name (e.g., "h264", "hevc", "vp9"). |
width |
int
|
Video width in pixels. |
height |
int
|
Video height in pixels. |
fps |
float
|
Frames per second. |
duration |
float
|
Duration in seconds. |
bitrate |
int
|
Video bitrate in bits per second. |
size |
int
|
File size in bytes. |
audio_codec |
str | None
|
Audio codec name (e.g., "aac", "opus"). |
container |
str
|
Container format (e.g., "mp4", "mov", "mkv"). |
creation_time |
datetime | None
|
Recording timestamp (if available). |
color_space |
str | None
|
Video color space (if available). |
bit_depth |
int | None
|
Video bit depth (if available). |
profile |
str | None
|
Codec profile (e.g., "High", "Main"). |
level |
str | None
|
Codec level (e.g., "4.0", "5.1"). |
Example
info = CodecInfo( ... path=Path("video.mp4"), ... codec="h264", ... width=3840, ... height=2160, ... fps=29.97, ... duration=180.5, ... bitrate=50_000_000, ... size=1_125_000_000, ... audio_codec="aac", ... container="mp4" ... ) print(f"Resolution: {info.resolution_label}") # "4K" print(f"Needs conversion: {info.is_h264}") # True
is_h264
property
¶
Check if video codec is H.264/AVC.
Returns:
| Type | Description |
|---|---|
bool
|
True if the codec is any variant of H.264. |
is_hevc
property
¶
Check if video codec is H.265/HEVC.
Returns:
| Type | Description |
|---|---|
bool
|
True if the codec is any variant of H.265/HEVC. |
needs_conversion
property
¶
Check if video needs H.265 conversion.
Returns:
| Type | Description |
|---|---|
bool
|
True if the video is H.264 and would benefit from conversion. |
resolution_label
property
¶
Get human-readable resolution label.
Returns:
| Type | Description |
|---|---|
str
|
Resolution label like "4K", "1080p", "720p", etc. |
aspect_ratio
property
¶
Calculate aspect ratio.
Returns:
| Type | Description |
|---|---|
str
|
Aspect ratio string like "16:9", "4:3", etc. |
bitrate_mbps
property
¶
Get bitrate in Mbps.
Returns:
| Type | Description |
|---|---|
float
|
Bitrate in megabits per second. |
size_mb
property
¶
Get file size in MB.
Returns:
| Type | Description |
|---|---|
float
|
File size in megabytes. |
size_gb
property
¶
Get file size in GB.
Returns:
| Type | Description |
|---|---|
float
|
File size in gigabytes. |
__str__
¶
Return human-readable summary.
CodecDetector
¶
Video codec detector using FFprobe.
This class analyzes video files to extract codec information and determine if conversion to H.265/HEVC is needed.
SDS Reference: SDS-P01-002
Example
detector = CodecDetector() info = detector.analyze(Path("vacation.mp4")) if info.needs_conversion: ... print(f"Converting {info.path.name} from {info.codec} to HEVC") ...
Batch analysis¶
videos = list(Path("videos").glob("*.mp4")) h264_videos = [v for v in videos if detector.analyze(v).is_h264]
Attributes:
| Name | Type | Description |
|---|---|---|
ffprobe |
FFprobe runner instance. |
|
timeout |
Default timeout for FFprobe commands. |
Initialize CodecDetector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ffprobe_runner
|
FFprobeRunner | None
|
FFprobe runner to use. If None, creates a new one. |
None
|
timeout
|
float
|
Default timeout for FFprobe commands in seconds. |
30.0
|
Source code in src/video_converter/processors/codec_detector.py
analyze
¶
Analyze a video file and return codec information.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
CodecInfo
|
CodecInfo containing video properties. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
InvalidVideoError
|
If the file is not a valid video. |
CorruptedVideoError
|
If the video file is corrupted. |
CommandNotFoundError
|
If FFprobe is not installed. |
Source code in src/video_converter/processors/codec_detector.py
analyze_async
async
¶
Analyze a video file asynchronously.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
CodecInfo
|
CodecInfo containing video properties. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
InvalidVideoError
|
If the file is not a valid video. |
CorruptedVideoError
|
If the video file is corrupted. |
CommandNotFoundError
|
If FFprobe is not installed. |
Source code in src/video_converter/processors/codec_detector.py
is_h264
¶
Quick check if a video is H.264 encoded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the video is H.264, False otherwise. |
Source code in src/video_converter/processors/codec_detector.py
is_hevc
¶
Quick check if a video is H.265/HEVC encoded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the video is HEVC, False otherwise. |
Source code in src/video_converter/processors/codec_detector.py
needs_conversion
¶
Check if a video needs conversion to H.265.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the video is H.264 and should be converted. |
Source code in src/video_converter/processors/codec_detector.py
get_codec
¶
Get the video codec name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Codec name (e.g., "h264", "hevc"). |
Raises:
| Type | Description |
|---|---|
InvalidVideoError
|
If the file is not a valid video. |
Source code in src/video_converter/processors/codec_detector.py
Metadata Processor¶
metadata
¶
Metadata processing module for video files.
This module provides ExifTool integration for extracting and applying metadata on video files. It handles GPS coordinates, creation dates, camera information, and other critical metadata tags.
SDS Reference: SDS-P01-002 SRS Reference: SRS-401 (Metadata Preservation)
Example
from video_converter.utils.command_runner import CommandRunner runner = CommandRunner() processor = MetadataProcessor(runner) metadata = processor.extract(Path("video.mp4")) print(metadata.get("QuickTime:CreateDate"))
Copy all metadata¶
processor.copy_all(source_path, dest_path)
Verify critical tags¶
results = processor.verify_critical_tags(original, converted) for tag, matched in results.items(): ... print(f"{tag}: {'OK' if matched else 'MISMATCH'}")
MetadataExtractionError
¶
MetadataApplicationError
¶
GPSCoordinates
dataclass
¶
GPS coordinate data.
Attributes:
| Name | Type | Description |
|---|---|---|
latitude |
float
|
Latitude in decimal degrees. |
longitude |
float
|
Longitude in decimal degrees. |
altitude |
float | None
|
Altitude in meters (optional). |
__str__
¶
Return human-readable coordinate string.
Source code in src/video_converter/processors/metadata.py
MetadataVerificationResult
dataclass
¶
MetadataVerificationResult(all_matched, tag_results=dict(), missing_in_source=list(), missing_in_dest=list())
Result of metadata verification between two files.
Attributes:
| Name | Type | Description |
|---|---|---|
all_matched |
bool
|
True if all critical tags matched. |
tag_results |
dict[str, bool]
|
Dictionary mapping tag names to match status. |
missing_in_source |
list[str]
|
Tags present in source but missing in destination. |
missing_in_dest |
list[str]
|
Tags missing in destination that were in source. |
MetadataProcessor
¶
Handle video metadata extraction and application using ExifTool.
This class provides methods to extract metadata from video files, copy metadata between files, and verify that critical metadata was preserved during conversion.
Attributes:
| Name | Type | Description |
|---|---|---|
EXIFTOOL_CMD |
The exiftool command name. |
|
CRITICAL_TAGS |
List of metadata tags that must be preserved. |
|
GPS_TAGS |
Tags related to GPS/location data. |
|
DATE_TAGS |
Tags related to dates and times. |
Example
runner = CommandRunner() processor = MetadataProcessor(runner) metadata = processor.extract(Path("video.mp4")) gps = processor.extract_gps(Path("video.mp4")) if gps: ... print(f"Location: {gps}")
Initialize MetadataProcessor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
command_runner
|
CommandRunner | None
|
CommandRunner instance to use. If None, creates a new one. |
None
|
Source code in src/video_converter/processors/metadata.py
is_available
¶
Check if ExifTool is available.
Returns:
| Type | Description |
|---|---|
bool
|
True if exiftool command is available. |
ensure_available
¶
Ensure ExifTool is available, raising error if not.
Raises:
| Type | Description |
|---|---|
CommandNotFoundError
|
If exiftool is not installed. |
extract
¶
Extract all metadata from a video file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
include_binary
|
bool
|
Include binary data in output (default: False). |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary of metadata tags and values. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
MetadataExtractionError
|
If extraction fails. |
CommandNotFoundError
|
If exiftool is not installed. |
Source code in src/video_converter/processors/metadata.py
extract_gps
¶
Extract GPS coordinates from a video file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
GPSCoordinates | None
|
GPSCoordinates if found, None otherwise. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
MetadataExtractionError
|
If extraction fails. |
Source code in src/video_converter/processors/metadata.py
copy_all
¶
Copy all metadata from source to destination file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Source file with metadata. |
required |
dest
|
Path
|
Destination file to receive metadata. |
required |
overwrite_original
|
bool
|
If True, modify dest in place without backup. |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
True if metadata was copied successfully. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If source or dest doesn't exist. |
MetadataApplicationError
|
If copying fails. |
Source code in src/video_converter/processors/metadata.py
copy_tags
¶
Copy specific metadata tags from source to destination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Source file with metadata. |
required |
dest
|
Path
|
Destination file to receive metadata. |
required |
tags
|
list[str]
|
List of tag patterns (e.g., ["GPS*", "CreateDate"]). |
required |
overwrite_original
|
bool
|
If True, modify dest in place. |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
True if tags were copied successfully. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If source or dest doesn't exist. |
MetadataApplicationError
|
If copying fails. |
Source code in src/video_converter/processors/metadata.py
copy_gps
¶
Copy GPS metadata from source to destination.
This is a convenience method that copies all GPS-related tags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Source file with GPS data. |
required |
dest
|
Path
|
Destination file. |
required |
overwrite_original
|
bool
|
If True, modify dest in place. |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
True if GPS data was copied successfully. |
Source code in src/video_converter/processors/metadata.py
copy_dates
¶
Copy date/time metadata from source to destination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Source file with date metadata. |
required |
dest
|
Path
|
Destination file. |
required |
overwrite_original
|
bool
|
If True, modify dest in place. |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
True if dates were copied successfully. |
Source code in src/video_converter/processors/metadata.py
verify_critical_tags
¶
Verify that critical metadata was preserved during conversion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
Path
|
Original source file. |
required |
converted
|
Path
|
Converted output file. |
required |
Returns:
| Type | Description |
|---|---|
MetadataVerificationResult
|
MetadataVerificationResult with comparison details. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If either file doesn't exist. |
MetadataExtractionError
|
If metadata extraction fails. |
Source code in src/video_converter/processors/metadata.py
set_tag
¶
Set a single metadata tag on a file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the file. |
required |
tag
|
str
|
Tag name to set. |
required |
value
|
str
|
Value to set. |
required |
overwrite_original
|
bool
|
If True, modify file in place. |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
True if the tag was set successfully. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
MetadataApplicationError
|
If setting fails. |
Source code in src/video_converter/processors/metadata.py
batch_copy_all
¶
Copy metadata for multiple file pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source_dest_pairs
|
list[tuple[Path, Path]]
|
List of (source, dest) path tuples. |
required |
overwrite_original
|
bool
|
If True, modify dest files in place. |
True
|
Returns:
| Type | Description |
|---|---|
dict[Path, bool]
|
Dictionary mapping destination paths to success status. |
Source code in src/video_converter/processors/metadata.py
Quality Validator¶
quality_validator
¶
Video quality validation module.
This module provides video file integrity validation using FFprobe to ensure converted files are playable and not corrupted. It also includes compression ratio validation to detect encoding issues.
SDS Reference: SDS-P01-003 SRS Reference: SRS-501 (Conversion Result Verification) SRS Reference: SRS-503 (Compression Ratio Validation)
Example
validator = VideoValidator() result = validator.validate(Path("output.mp4")) if result.valid: ... print("Video is valid!") ... else: ... print(f"Errors: {result.errors}")
Compression ratio validation¶
comp_validator = CompressionValidator() result = comp_validator.validate(100_000_000, 40_000_000) print(f"Compression ratio: {result.compression_ratio:.1%}")
ValidationStrictness
¶
Bases: Enum
Validation strictness levels.
Attributes:
| Name | Type | Description |
|---|---|---|
QUICK |
Only check if file is readable (fastest). |
|
STANDARD |
Check integrity and basic properties (default). |
|
STRICT |
Full validation including all streams and metadata. |
StreamInfo
dataclass
¶
StreamInfo(index, codec_type, codec_name, duration=None, bit_rate=None, width=None, height=None, fps=None, channels=None, sample_rate=None)
Information about a media stream.
Attributes:
| Name | Type | Description |
|---|---|---|
index |
int
|
Stream index in the file. |
codec_type |
str
|
Type of stream (video, audio, subtitle, etc.). |
codec_name |
str
|
Name of the codec (h264, hevc, aac, etc.). |
duration |
float | None
|
Duration in seconds (if available). |
bit_rate |
int | None
|
Bit rate in bits/second (if available). |
width |
int | None
|
Width in pixels (video only). |
height |
int | None
|
Height in pixels (video only). |
fps |
float | None
|
Frames per second (video only). |
channels |
int | None
|
Number of audio channels (audio only). |
sample_rate |
int | None
|
Audio sample rate (audio only). |
VideoInfo
dataclass
¶
Complete video file information.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path
|
Path to the video file. |
format_name |
str
|
Container format name. |
duration |
float
|
Total duration in seconds. |
size |
int
|
File size in bytes. |
bit_rate |
int | None
|
Overall bit rate. |
streams |
list[StreamInfo]
|
List of stream information. |
video_streams |
list[StreamInfo]
|
List of video stream information. |
audio_streams |
list[StreamInfo]
|
List of audio stream information. |
ValidationResult
dataclass
¶
ValidationResult(valid, integrity_ok, properties_match=True, compression_normal=True, vmaf_score=None, errors=list(), warnings=list(), video_info=None)
Result of video validation.
Attributes:
| Name | Type | Description |
|---|---|---|
valid |
bool
|
Overall validation result (True if all checks passed). |
integrity_ok |
bool
|
File integrity check passed. |
properties_match |
bool
|
Properties match expected values. |
compression_normal |
bool
|
Compression ratio is within normal range. |
vmaf_score |
float | None
|
VMAF quality score (if measured, None otherwise). |
errors |
list[str]
|
List of error messages (validation failures). |
warnings |
list[str]
|
List of warning messages (non-critical issues). |
video_info |
VideoInfo | None
|
Parsed video information (if successful). |
add_error
¶
VideoValidator
¶
Video file integrity validator using FFprobe.
This class provides comprehensive validation for video files to ensure they are playable and not corrupted. It supports configurable strictness levels for different use cases.
SDS Reference: SDS-P01-003
Validation Checks
- File existence and size > 0
- FFprobe can read the file without errors
- Video stream exists and is decodable
- Audio stream integrity (if present)
- Duration is valid (> 0)
- Codec information is extractable
Example
validator = VideoValidator()
Quick validation¶
if validator.quick_validate(Path("video.mp4")): ... print("Video is playable")
Full validation¶
result = validator.validate(Path("video.mp4")) print(f"Valid: {result.valid}, Errors: {result.errors}")
Attributes:
| Name | Type | Description |
|---|---|---|
ffprobe |
FFprobe runner instance. |
|
strictness |
Validation strictness level. |
|
timeout |
Maximum time for FFprobe commands. |
Initialize the video validator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strictness
|
ValidationStrictness
|
Validation strictness level. |
STANDARD
|
timeout
|
float
|
Maximum time for FFprobe operations (seconds). |
30.0
|
ffprobe
|
FFprobeRunner | None
|
FFprobe runner to use (creates new one if None). |
None
|
Source code in src/video_converter/processors/quality_validator.py
quick_validate
¶
Quickly check if a video file is valid.
This performs a minimal check to see if the file can be opened. Use this for fast validation when detailed error information is not needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the file appears valid, False otherwise. |
Source code in src/video_converter/processors/quality_validator.py
validate
¶
Validate a video file comprehensively.
Performs full validation according to the specified strictness level. Returns detailed information about any issues found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file to validate. |
required |
strictness
|
ValidationStrictness | None
|
Override the default strictness level. |
None
|
Returns:
| Type | Description |
|---|---|
ValidationResult
|
ValidationResult containing validation details. |
Raises:
| Type | Description |
|---|---|
CommandNotFoundError
|
If FFprobe is not installed. |
Source code in src/video_converter/processors/quality_validator.py
validate_async
async
¶
Validate a video file asynchronously.
Async version of validate() for use in async contexts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file to validate. |
required |
strictness
|
ValidationStrictness | None
|
Override the default strictness level. |
None
|
Returns:
| Type | Description |
|---|---|
ValidationResult
|
ValidationResult containing validation details. |
Source code in src/video_converter/processors/quality_validator.py
ComparisonSeverity
¶
Bases: Enum
Severity level for property mismatch.
Attributes:
| Name | Type | Description |
|---|---|---|
ERROR |
Mismatch indicates a critical problem. |
|
WARNING |
Mismatch is notable but not critical. |
PropertyComparison
dataclass
¶
PropertyComparison(property_name, original_value, converted_value, matches, tolerance=None, severity=WARNING, message='')
Result of comparing a single video property.
SDS Reference: SDS-P05-002 SRS Reference: SRS-502 (Video Property Comparison)
Attributes:
| Name | Type | Description |
|---|---|---|
property_name |
str
|
Name of the property being compared. |
original_value |
Any
|
Value from the original file. |
converted_value |
Any
|
Value from the converted file. |
matches |
bool
|
Whether the values match within tolerance. |
tolerance |
float | None
|
Tolerance used for comparison (if applicable). |
severity |
ComparisonSeverity
|
Severity level if mismatch occurs. |
message |
str
|
Human-readable description of the comparison result. |
PropertyComparisonResult
dataclass
¶
Result of comparing all video properties.
SDS Reference: SDS-P05-002
Attributes:
| Name | Type | Description |
|---|---|---|
all_match |
bool
|
True if all critical properties match. |
comparisons |
list[PropertyComparison]
|
List of individual property comparisons. |
errors |
list[str]
|
List of error messages (critical mismatches). |
warnings |
list[str]
|
List of warning messages (non-critical mismatches). |
add_comparison
¶
Add a property comparison result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
comparison
|
PropertyComparison
|
The comparison result to add. |
required |
Source code in src/video_converter/processors/quality_validator.py
PropertyComparer
¶
Compare video properties between original and converted files.
This class provides comparison of video properties to ensure that the conversion process did not alter critical parameters.
SDS Reference: SDS-P05-002 SRS Reference: SRS-502 (Video Property Comparison)
Tolerance Settings
- Resolution: Exact match required (Error on mismatch)
- Frame Rate: ±0.001 fps tolerance (Warning on mismatch)
- Duration: ±0.5 second tolerance (Warning on mismatch)
- Aspect Ratio: Exact match required (Error on mismatch)
- Audio Codec: Exact match required (Warning on mismatch)
- Audio Channels: Exact match required (Error on mismatch)
Example
comparer = PropertyComparer() result = comparer.compare(original_info, converted_info) if result.all_match: ... print("All properties match!") else: ... print(f"Errors: {result.errors}") ... print(f"Warnings: {result.warnings}")
Initialize the property comparer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fps_tolerance
|
float
|
Tolerance for frame rate comparison (default: ±0.001 fps). |
FPS_TOLERANCE
|
duration_tolerance
|
float
|
Tolerance for duration comparison (default: ±0.5 seconds). |
DURATION_TOLERANCE
|
Source code in src/video_converter/processors/quality_validator.py
compare
¶
Compare all properties between original and converted video.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
VideoInfo
|
VideoInfo from the original file. |
required |
converted
|
VideoInfo
|
VideoInfo from the converted file. |
required |
Returns:
| Type | Description |
|---|---|
PropertyComparisonResult
|
PropertyComparisonResult containing all comparison details. |
Source code in src/video_converter/processors/quality_validator.py
ContentType
¶
Bases: Enum
Content type for compression ratio validation.
Different content types have different expected compression ratios. High-motion content (sports, action) compresses less efficiently, while low-motion content (interviews, static scenes) compresses better.
Attributes:
| Name | Type | Description |
|---|---|---|
STANDARD |
Normal video content (default). |
|
HIGH_MOTION |
High-motion content like sports or action. |
|
LOW_MOTION |
Low-motion content like interviews or static scenes. |
CompressionRange
dataclass
¶
Expected compression ratio range for a content type.
SDS Reference: SDS-P05-003
Attributes:
| Name | Type | Description |
|---|---|---|
min_ratio |
float
|
Minimum expected compression ratio (0.0 to 1.0). |
max_ratio |
float
|
Maximum expected compression ratio (0.0 to 1.0). |
content_type |
ContentType
|
The content type this range applies to. |
__post_init__
¶
Validate range values.
Source code in src/video_converter/processors/quality_validator.py
CompressionSeverity
¶
Bases: Enum
Severity level for compression ratio issues.
Attributes:
| Name | Type | Description |
|---|---|---|
NORMAL |
Compression ratio is within expected range. |
|
WARNING |
Compression ratio is outside expected range but not critical. |
|
ERROR |
Compression ratio indicates a serious encoding issue. |
CompressionValidationResult
dataclass
¶
CompressionValidationResult(valid, compression_ratio, original_size, converted_size, content_type, severity, message='', expected_range=None)
Result of compression ratio validation.
SDS Reference: SDS-P05-003 SRS Reference: SRS-503 (Compression Ratio Validation)
Attributes:
| Name | Type | Description |
|---|---|---|
valid |
bool
|
Overall validation result (True if within acceptable range). |
compression_ratio |
float
|
Calculated compression ratio (0.0 to 1.0). |
original_size |
int
|
Original file size in bytes. |
converted_size |
int
|
Converted file size in bytes. |
content_type |
ContentType
|
Content type used for validation. |
severity |
CompressionSeverity
|
Severity level of the result. |
message |
str
|
Human-readable description of the result. |
expected_range |
CompressionRange | None
|
The expected compression range for the content type. |
CompressionValidator
¶
CompressionValidator(*, ranges=None, critical_low=DEFAULT_CRITICAL_LOW, critical_high=DEFAULT_CRITICAL_HIGH)
Validate compression ratio is within expected range.
This class validates that the compression ratio of a converted video falls within expected ranges for different content types. It helps detect encoding issues such as: - File grew significantly (encoding issue) - Below expected compression (quality setting too high) - Too aggressive compression (quality loss)
SDS Reference: SDS-P05-003 SRS Reference: SRS-503 (Compression Ratio Validation)
Expected Compression Ranges
- Standard Video: 30% - 70%
- High Motion: 20% - 60%
- Low Motion: 40% - 80%
Warning Thresholds
- < 20%: File grew significantly (encoding issue)
- < 30%: Below expected (quality setting too high?)
-
80%: Too aggressive (quality loss?)
Example
validator = CompressionValidator() result = validator.validate(100_000_000, 40_000_000) if result.valid: ... print(f"Compression OK: {result.compression_ratio:.1%}") else: ... print(f"Warning: {result.message}")
Attributes:
| Name | Type | Description |
|---|---|---|
ranges |
Dictionary mapping content types to compression ranges. |
|
critical_low |
Threshold below which indicates serious encoding issue. |
|
critical_high |
Threshold above which indicates excessive compression. |
Initialize the compression validator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranges
|
dict[ContentType, CompressionRange] | None
|
Custom compression ranges per content type. Uses default ranges if not provided. |
None
|
critical_low
|
float
|
Threshold below which is a critical issue (default: 0.20). |
DEFAULT_CRITICAL_LOW
|
critical_high
|
float
|
Threshold above which is a critical issue (default: 0.80). |
DEFAULT_CRITICAL_HIGH
|
Source code in src/video_converter/processors/quality_validator.py
validate
¶
Validate compression ratio is within expected range.
Calculates the compression ratio and checks if it falls within the expected range for the given content type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original_size
|
int
|
Original file size in bytes. |
required |
converted_size
|
int
|
Converted file size in bytes. |
required |
content_type
|
ContentType
|
Type of video content (default: STANDARD). |
STANDARD
|
Returns:
| Type | Description |
|---|---|
CompressionValidationResult
|
CompressionValidationResult containing validation details. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If original_size is not positive. |
Source code in src/video_converter/processors/quality_validator.py
get_expected_range
¶
Get the expected compression range for a content type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content_type
|
ContentType
|
The content type to get the range for. |
required |
Returns:
| Type | Description |
|---|---|
CompressionRange | None
|
CompressionRange for the content type, or None if not defined. |
Source code in src/video_converter/processors/quality_validator.py
set_range
¶
Set a custom compression range for a content type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content_type
|
ContentType
|
The content type to set the range for. |
required |
range_
|
CompressionRange
|
The compression range to set. |
required |
Source code in src/video_converter/processors/quality_validator.py
GPS Handler¶
gps
¶
GPS coordinate handling for video metadata.
This module provides specialized handling for GPS coordinate preservation during video conversion. It ensures location data is accurately maintained across different metadata container formats.
SDS Reference: SDS-P01-003 SRS Reference: SRS-402 (GPS Preservation)
Example
from video_converter.utils.command_runner import CommandRunner from video_converter.processors.gps import GPSHandler handler = GPSHandler(CommandRunner()) coords = handler.extract(Path("video.mp4")) if coords: ... print(f"Location: {coords}") ... print(f"QuickTime format: {coords.to_quicktime()}")
Verify GPS was preserved¶
result = handler.verify(original_path, converted_path) if result.passed: ... print("GPS preserved successfully")
GPSFormat
¶
Bases: Enum
GPS coordinate storage formats.
Different metadata containers store GPS data in different formats. This enum identifies the source format for proper handling.
GPSCoordinates
dataclass
¶
GPS coordinate data with format conversion support.
This class represents GPS coordinates with support for converting between different metadata container formats. It preserves accuracy to 6 decimal places (~0.1 meter precision).
Attributes:
| Name | Type | Description |
|---|---|---|
latitude |
float
|
Latitude in decimal degrees (-90 to 90). |
longitude |
float
|
Longitude in decimal degrees (-180 to 180). |
altitude |
float | None
|
Altitude in meters (optional). |
accuracy |
float | None
|
Horizontal accuracy in meters (optional). |
source_format |
GPSFormat
|
Original format the coordinates were parsed from. |
Example
coords = GPSCoordinates( ... latitude=37.7749, ... longitude=-122.4194, ... altitude=10.5 ... ) print(coords.to_quicktime()) +37.774900-122.419400/
__post_init__
¶
Validate and normalize coordinates.
Source code in src/video_converter/processors/gps.py
__str__
¶
Return human-readable coordinate string.
Source code in src/video_converter/processors/gps.py
to_quicktime
¶
Convert to QuickTime GPS format.
QuickTime uses ISO 6709 format: +DD.DDDDDD-DDD.DDDDDD/
Returns:
| Type | Description |
|---|---|
str
|
GPS string in QuickTime format. |
Example
coords = GPSCoordinates(37.7749, -122.4194) coords.to_quicktime() '+37.774900-122.419400/'
Source code in src/video_converter/processors/gps.py
to_xmp
¶
Convert to XMP GPS format.
XMP uses "DD.DDDDDD,D" format with direction suffix.
Returns:
| Type | Description |
|---|---|
tuple[str, str]
|
Tuple of (latitude_string, longitude_string). |
Example
coords = GPSCoordinates(37.7749, -122.4194) coords.to_xmp() ('37.774900 N', '122.419400 W')
Source code in src/video_converter/processors/gps.py
to_exif_dms
¶
Convert to EXIF DMS (degrees, minutes, seconds) format.
Returns:
| Type | Description |
|---|---|
tuple[str, str, str, str]
|
Tuple of (latitude, lat_ref, longitude, lon_ref). |
Example
coords = GPSCoordinates(37.775, -122.4194) lat, lat_ref, lon, lon_ref = coords.to_exif_dms() print(f"{lat} {lat_ref}") 37 deg 46' 30.00" N
Source code in src/video_converter/processors/gps.py
matches
¶
Check if coordinates match within tolerance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
GPSCoordinates
|
Another GPSCoordinates to compare. |
required |
tolerance
|
float | None
|
Optional custom tolerance in decimal degrees. Defaults to TOLERANCE (0.000001 = ~0.1m). |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if coordinates match within tolerance. |
Source code in src/video_converter/processors/gps.py
distance_to
¶
Calculate approximate distance to another coordinate in meters.
Uses the Haversine formula for spherical distance calculation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
GPSCoordinates
|
Another GPSCoordinates. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Approximate distance in meters. |
Source code in src/video_converter/processors/gps.py
from_quicktime
classmethod
¶
Parse QuickTime GPS format (ISO 6709).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
GPS string like "+37.7749-122.4194/" or "+37.7749-122.4194+10.5/" |
required |
Returns:
| Type | Description |
|---|---|
GPSCoordinates | None
|
GPSCoordinates if parsed successfully, None otherwise. |
Source code in src/video_converter/processors/gps.py
from_xmp
classmethod
¶
Parse XMP GPS format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat_str
|
str
|
Latitude string like "37.7749 N" or "37.7749,N" |
required |
lon_str
|
str
|
Longitude string like "122.4194 W" or "122.4194,W" |
required |
Returns:
| Type | Description |
|---|---|
GPSCoordinates | None
|
GPSCoordinates if parsed successfully, None otherwise. |
Source code in src/video_converter/processors/gps.py
from_exif_dms
classmethod
¶
Parse EXIF DMS format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat_dms
|
str
|
Latitude in DMS like "37 deg 46' 30.00"" |
required |
lat_ref
|
str
|
Latitude reference ("N" or "S") |
required |
lon_dms
|
str
|
Longitude in DMS like "122 deg 25' 10.00"" |
required |
lon_ref
|
str
|
Longitude reference ("E" or "W") |
required |
Returns:
| Type | Description |
|---|---|
GPSCoordinates | None
|
GPSCoordinates if parsed successfully, None otherwise. |
Source code in src/video_converter/processors/gps.py
GPSVerificationResult
dataclass
¶
GPSVerificationResult(passed, original=None, converted=None, distance_meters=None, tolerance_used=TOLERANCE, details='')
Result of GPS coordinate verification.
Attributes:
| Name | Type | Description |
|---|---|---|
passed |
bool
|
True if GPS was preserved within tolerance. |
original |
GPSCoordinates | None
|
Original GPS coordinates (None if not present). |
converted |
GPSCoordinates | None
|
Converted GPS coordinates (None if not present). |
distance_meters |
float | None
|
Distance between coordinates in meters (if both exist). |
tolerance_used |
float
|
Tolerance used for comparison in decimal degrees. |
details |
str
|
Additional verification details. |
GPSHandler
¶
Handle GPS coordinate preservation during video conversion.
This class provides specialized methods for extracting, applying, and verifying GPS coordinates across different metadata formats.
Example
handler = GPSHandler(CommandRunner()) coords = handler.extract(Path("video.mp4")) if coords: ... handler.apply(Path("output.mp4"), coords) ... result = handler.verify(Path("video.mp4"), Path("output.mp4")) ... print(f"Verification: {result.passed}")
Initialize GPSHandler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata_processor
|
MetadataProcessor | None
|
MetadataProcessor to use for metadata operations. If None, creates a new one. |
None
|
Source code in src/video_converter/processors/gps.py
extract
¶
Extract GPS coordinates from a video file.
Checks all possible GPS tag locations (QuickTime, XMP, EXIF, Keys) and returns coordinates if found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
GPSCoordinates | None
|
GPSCoordinates if found, None otherwise. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
MetadataExtractionError
|
If extraction fails. |
Source code in src/video_converter/processors/gps.py
apply
¶
Apply GPS coordinates to a video file.
Writes GPS data in multiple formats to ensure maximum compatibility.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
coords
|
GPSCoordinates
|
GPS coordinates to apply. |
required |
overwrite_original
|
bool
|
If True, modify file in place. |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
True if GPS was applied successfully. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
Source code in src/video_converter/processors/gps.py
copy
¶
Copy GPS data from source to destination file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Source file with GPS data. |
required |
dest
|
Path
|
Destination file. |
required |
overwrite_original
|
bool
|
If True, modify dest in place. |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
True if GPS was copied successfully. |
Source code in src/video_converter/processors/gps.py
verify
¶
Verify GPS was preserved during conversion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
Path
|
Original source file. |
required |
converted
|
Path
|
Converted output file. |
required |
tolerance
|
float | None
|
Custom tolerance in decimal degrees. Defaults to GPSCoordinates.TOLERANCE (~0.1m). |
None
|
Returns:
| Type | Description |
|---|---|
GPSVerificationResult
|
GPSVerificationResult with detailed comparison. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If either file doesn't exist. |
Source code in src/video_converter/processors/gps.py
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 | |
has_gps
¶
Check if a video file has GPS data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the video file. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the file has GPS coordinates. |
Source code in src/video_converter/processors/gps.py
VMAF Analyzer¶
vmaf_analyzer
¶
VMAF (Video Multimethod Assessment Fusion) quality measurement module.
This module provides VMAF-based perceptual video quality measurement to compare original and converted video files. VMAF is a metric developed by Netflix that predicts subjective video quality.
SDS Reference: SDS-P05-004 SRS Reference: SRS-504 (VMAF Quality Measurement)
VMAF Score Interpretation
- 93+: Visually lossless (indistinguishable from original)
- 80-93: High quality (minor differences, acceptable for most use cases)
- 60-80: Good quality (noticeable differences, acceptable for streaming)
- <60: Noticeable degradation (quality issues visible)
Example
analyzer = VmafAnalyzer() if analyzer.is_available(): ... result = analyzer.analyze( ... original=Path("original.mp4"), ... converted=Path("converted.mp4"), ... ) ... print(f"VMAF Score: {result.scores.mean:.2f}") ... print(f"Quality: {result.quality_level.name}") ... else: ... print("VMAF not available (libvmaf not installed)")
VmafNotAvailableError
¶
Bases: Exception
Raised when VMAF analysis is requested but libvmaf is not available.
This exception indicates that FFmpeg was not compiled with libvmaf support or libvmaf is not installed on the system.
Attributes:
| Name | Type | Description |
|---|---|---|
message |
Explanation of why VMAF is not available. |
Source code in src/video_converter/processors/vmaf_analyzer.py
VmafAnalysisError
¶
Bases: Exception
Raised when VMAF analysis fails.
Attributes:
| Name | Type | Description |
|---|---|---|
original |
Path to the original video. |
|
converted |
Path to the converted video. |
|
reason |
Explanation of the failure. |
Source code in src/video_converter/processors/vmaf_analyzer.py
VmafQualityLevel
¶
Bases: Enum
VMAF quality level classification.
Based on Netflix's VMAF score interpretation guidelines.
Attributes:
| Name | Type | Description |
|---|---|---|
VISUALLY_LOSSLESS |
Score >= 93, indistinguishable from original. |
|
HIGH_QUALITY |
Score 80-93, minor differences acceptable for most use cases. |
|
GOOD_QUALITY |
Score 60-80, noticeable differences acceptable for streaming. |
|
NOTICEABLE_DEGRADATION |
Score < 60, visible quality issues. |
from_score
classmethod
¶
Determine quality level from VMAF score.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
score
|
float
|
VMAF score (0-100). |
required |
Returns:
| Type | Description |
|---|---|
VmafQualityLevel
|
Corresponding VmafQualityLevel. |
Source code in src/video_converter/processors/vmaf_analyzer.py
VmafScores
dataclass
¶
VMAF score statistics.
Contains various percentile and aggregate scores from VMAF analysis.
Attributes:
| Name | Type | Description |
|---|---|---|
mean |
float
|
Mean VMAF score across all frames. |
min |
float
|
Minimum VMAF score (worst frame). |
max |
float
|
Maximum VMAF score (best frame). |
percentile_5 |
float
|
5th percentile score (worst 5% of frames). |
percentile_95 |
float
|
95th percentile score (best 5% excluded). |
harmonic_mean |
float | None
|
Harmonic mean (if available). |
std_dev |
float | None
|
Standard deviation (if available). |
__str__
¶
Return human-readable summary.
VmafResult
dataclass
¶
VmafResult(original_path, converted_path, scores, quality_level, frame_count, sampled=False, sample_interval=1, model_version='vmaf_v0.6.1', warnings=list(), raw_data=None)
Complete VMAF analysis result.
SDS Reference: SDS-P05-004
Attributes:
| Name | Type | Description |
|---|---|---|
original_path |
Path
|
Path to the original video file. |
converted_path |
Path
|
Path to the converted video file. |
scores |
VmafScores
|
VMAF score statistics. |
quality_level |
VmafQualityLevel
|
Quality classification based on mean score. |
frame_count |
int
|
Number of frames analyzed. |
sampled |
bool
|
Whether sampling was used for faster analysis. |
sample_interval |
int
|
Sampling interval used (1 = every frame). |
model_version |
str
|
VMAF model version used. |
warnings |
list[str]
|
List of warning messages. |
raw_data |
dict[str, Any] | None
|
Raw JSON output from VMAF (if available). |
VmafAnalyzer
¶
VmafAnalyzer(*, ffmpeg_path=None, timeout=VMAF_ANALYSIS_TIMEOUT, model_path=None, command_runner=None)
VMAF quality analyzer for video comparison.
This class provides VMAF-based quality measurement to compare original and converted videos. It supports sampling for faster analysis and gracefully handles missing libvmaf.
SDS Reference: SDS-P05-004 SRS Reference: SRS-504 (VMAF Quality Measurement)
Features
- Calculate VMAF scores between original and converted videos
- Support sampling for faster analysis of long videos
- Report percentile scores (min, 5th, mean, 95th)
- Gracefully handle missing libvmaf
Example
analyzer = VmafAnalyzer()
Check availability first¶
if not analyzer.is_available(): ... print("VMAF not available") ... return
Full analysis¶
result = analyzer.analyze( ... original=Path("original.mp4"), ... converted=Path("converted.mp4"), ... ) print(f"Score: {result.scores.mean:.2f}")
Sampled analysis for long videos (faster)¶
result = analyzer.analyze( ... original=Path("long_video.mp4"), ... converted=Path("converted.mp4"), ... sample_interval=10, # Analyze every 10th frame ... )
Attributes:
| Name | Type | Description |
|---|---|---|
ffmpeg_path |
Path to FFmpeg executable. |
|
timeout |
Default timeout for VMAF analysis. |
|
model_path |
Path to VMAF model file (optional). |
Initialize VMAF analyzer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ffmpeg_path
|
str | None
|
Custom path to FFmpeg. Uses PATH if None. |
None
|
timeout
|
float
|
Default timeout for analysis in seconds. |
VMAF_ANALYSIS_TIMEOUT
|
model_path
|
str | None
|
Custom path to VMAF model file. Uses default if None. |
None
|
command_runner
|
CommandRunner | None
|
CommandRunner instance. Creates new one if None. |
None
|
Source code in src/video_converter/processors/vmaf_analyzer.py
is_available
¶
Check if VMAF analysis is available.
Checks if FFmpeg is installed and has libvmaf support.
Returns:
| Type | Description |
|---|---|
bool
|
True if VMAF is available, False otherwise. |
Source code in src/video_converter/processors/vmaf_analyzer.py
analyze
¶
Analyze video quality using VMAF.
Compares the converted video against the original and returns VMAF scores and quality assessment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
Path
|
Path to the original (reference) video. |
required |
converted
|
Path
|
Path to the converted (distorted) video. |
required |
sample_interval
|
int
|
Analyze every Nth frame (1 = all frames). Use higher values for faster analysis of long videos. |
1
|
timeout
|
float | None
|
Analysis timeout in seconds. Uses default if None. |
None
|
resolution
|
tuple[int, int] | None
|
Target resolution for comparison (width, height). If None, videos are scaled to match if needed. |
None
|
Returns:
| Type | Description |
|---|---|
VmafResult
|
VmafResult containing scores and quality assessment. |
Raises:
| Type | Description |
|---|---|
VmafNotAvailableError
|
If libvmaf is not available. |
VmafAnalysisError
|
If analysis fails. |
FileNotFoundError
|
If either video file doesn't exist. |
Example
result = analyzer.analyze( ... original=Path("original.mp4"), ... converted=Path("converted.mp4"), ... sample_interval=5, # Every 5th frame for speed ... ) if result.is_visually_lossless: ... print("Excellent quality!")
Source code in src/video_converter/processors/vmaf_analyzer.py
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | |
analyze_async
async
¶
Analyze video quality using VMAF asynchronously.
Async version of analyze() for use in async contexts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
Path
|
Path to the original (reference) video. |
required |
converted
|
Path
|
Path to the converted (distorted) video. |
required |
sample_interval
|
int
|
Analyze every Nth frame (1 = all frames). |
1
|
timeout
|
float | None
|
Analysis timeout in seconds. Uses default if None. |
None
|
resolution
|
tuple[int, int] | None
|
Target resolution for comparison (width, height). |
None
|
Returns:
| Type | Description |
|---|---|
VmafResult
|
VmafResult containing scores and quality assessment. |
Raises:
| Type | Description |
|---|---|
VmafNotAvailableError
|
If libvmaf is not available. |
VmafAnalysisError
|
If analysis fails. |
FileNotFoundError
|
If either video file doesn't exist. |
Source code in src/video_converter/processors/vmaf_analyzer.py
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | |
quick_analyze
¶
Perform quick VMAF analysis with sampling.
Uses aggressive sampling for a quick quality estimate. Suitable for initial screening of conversion quality.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
Path
|
Path to original video. |
required |
converted
|
Path
|
Path to converted video. |
required |
timeout
|
float | None
|
Analysis timeout in seconds. |
None
|
Returns:
| Type | Description |
|---|---|
float | None
|
Mean VMAF score, or None if analysis fails. |
Source code in src/video_converter/processors/vmaf_analyzer.py
get_quality_assessment
¶
Get human-readable quality assessment for a VMAF score.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
score
|
float
|
VMAF score (0-100). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Human-readable quality assessment string. |
Source code in src/video_converter/processors/vmaf_analyzer.py
Verification¶
verification
¶
Metadata verification system for video conversion.
This module provides a comprehensive metadata verification system that compares original and converted files to ensure all critical metadata was preserved during conversion.
SDS Reference: SDS-P01-004 SRS Reference: SRS-403 (Metadata Verification)
Example
from video_converter.processors.verification import MetadataVerifier verifier = MetadataVerifier() result = verifier.verify(Path("original.mp4"), Path("converted.mp4")) if result.passed: ... print("All metadata preserved successfully") else: ... for check in result.failed_checks: ... print(f"FAILED: {check.category} - {check.details}")
VerificationCategory
¶
Bases: Enum
Categories of metadata verification.
Attributes:
| Name | Type | Description |
|---|---|---|
DATE_TIME |
Date and time metadata (CreateDate, ModifyDate). |
|
GPS |
GPS location data (Latitude, Longitude, Altitude). |
|
CAMERA |
Camera information (Make, Model). |
|
VIDEO |
Video properties (Duration, Rotation). |
|
AUDIO |
Audio properties (Codec, Channels). |
CheckStatus
¶
Bases: Enum
Status of a single verification check.
Attributes:
| Name | Type | Description |
|---|---|---|
PASSED |
Check passed successfully. |
|
FAILED |
Check failed - values don't match within tolerance. |
|
MISSING_IN_SOURCE |
Field not present in original file. |
|
MISSING_IN_CONVERTED |
Field was in original but missing in converted. |
|
ERROR |
An error occurred during verification. |
ToleranceSettings
dataclass
¶
ToleranceSettings(date_seconds=1.0, gps_degrees=1e-06, duration_seconds=0.1, numeric_relative=0.001)
Configurable tolerance settings for metadata verification.
Attributes:
| Name | Type | Description |
|---|---|---|
date_seconds |
float
|
Tolerance for date/time comparison in seconds. |
gps_degrees |
float
|
Tolerance for GPS coordinates in decimal degrees. |
duration_seconds |
float
|
Tolerance for video duration in seconds. |
numeric_relative |
float
|
Relative tolerance for other numeric values. |
CheckResult
dataclass
¶
CheckResult(category, field_name, status, original_value=None, converted_value=None, tolerance_used=None, details='')
Result of a single metadata verification check.
Attributes:
| Name | Type | Description |
|---|---|---|
category |
VerificationCategory
|
The verification category this check belongs to. |
field_name |
str
|
Name of the metadata field being verified. |
status |
CheckStatus
|
Status of the verification check. |
original_value |
Any
|
Value from the original file. |
converted_value |
Any
|
Value from the converted file. |
tolerance_used |
float | None
|
Tolerance value applied to comparison. |
details |
str
|
Additional details about the check result. |
__str__
¶
Return human-readable check result.
VerificationResult
dataclass
¶
VerificationResult(passed, original_path, converted_path, checks=list(), verification_time=now(), tolerance_settings=ToleranceSettings())
Result of complete metadata verification between two files.
Attributes:
| Name | Type | Description |
|---|---|---|
passed |
bool
|
True if all critical checks passed. |
original_path |
Path
|
Path to the original file. |
converted_path |
Path
|
Path to the converted file. |
checks |
list[CheckResult]
|
List of individual check results. |
verification_time |
datetime
|
When the verification was performed. |
tolerance_settings |
ToleranceSettings
|
Tolerance settings used for verification. |
get_summary
¶
Generate a summary of the verification result.
Source code in src/video_converter/processors/verification.py
MetadataVerifier
¶
Verify metadata preservation during video conversion.
This class provides comprehensive metadata verification comparing original and converted files across all critical metadata categories.
Attributes:
| Name | Type | Description |
|---|---|---|
DATE_TIME_FIELDS |
Fields to check for date/time category. |
|
CAMERA_FIELDS |
Fields to check for camera information. |
|
VIDEO_FIELDS |
Fields to check for video properties. |
|
AUDIO_FIELDS |
Fields to check for audio properties. |
Example
verifier = MetadataVerifier() result = verifier.verify(Path("original.mp4"), Path("converted.mp4")) print(result.get_summary()) Verification Result: PASSED Original: original.mp4 Converted: converted.mp4 Checks: 10/10 passed, 0 failed
Initialize MetadataVerifier.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata_processor
|
MetadataProcessor | None
|
MetadataProcessor instance for metadata extraction. |
None
|
gps_handler
|
GPSHandler | None
|
GPSHandler instance for GPS verification. |
None
|
tolerance
|
ToleranceSettings | None
|
ToleranceSettings for comparison. Defaults to standard settings. |
None
|
Source code in src/video_converter/processors/verification.py
verify
¶
Run all verification checks on two files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
Path
|
Path to the original video file. |
required |
converted
|
Path
|
Path to the converted video file. |
required |
tolerance
|
ToleranceSettings | None
|
Optional custom tolerance settings for this verification. |
None
|
categories
|
list[VerificationCategory] | None
|
Optional list of categories to verify. If None, verifies all. |
None
|
Returns:
| Type | Description |
|---|---|
VerificationResult
|
VerificationResult with all check details. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If either file doesn't exist. |
Source code in src/video_converter/processors/verification.py
Timestamp¶
timestamp
¶
File timestamp synchronization for video conversion.
This module provides functionality to synchronize filesystem timestamps (creation date, modification date) between original and converted video files. This ensures converted videos appear in the correct chronological order when sorted by date in macOS Finder.
SDS Reference: SDS-P01-004 SRS Reference: SRS-403 (Timestamp Preservation)
Example
from video_converter.processors.timestamp import TimestampSynchronizer synchronizer = TimestampSynchronizer()
Copy all timestamps from original to converted¶
result = synchronizer.sync_from_file( ... source=Path("original.mov"), ... dest=Path("converted.mp4"), ... ) if result.success: ... print("Timestamps synchronized successfully")
Verify timestamps were preserved¶
verification = synchronizer.verify( ... original=Path("original.mov"), ... converted=Path("converted.mp4"), ... ) print(f"Passed: {verification.passed}")
TimestampError
¶
Bases: Exception
Base exception for timestamp operations.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
The path where the error occurred. |
|
reason |
Description of the error. |
Source code in src/video_converter/processors/timestamp.py
TimestampSyncError
¶
Bases: TimestampError
Raised when timestamp synchronization fails.
Source code in src/video_converter/processors/timestamp.py
TimestampReadError
¶
Bases: TimestampError
Raised when reading timestamps fails.
Source code in src/video_converter/processors/timestamp.py
FileTimestamps
dataclass
¶
FileTimestamps(path, birth_time=None, modification_time=None, access_time=None, metadata_change_time=None)
Container for file timestamp information.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path
|
Path to the file. |
birth_time |
datetime | None
|
File creation time (macOS-specific, may be None on other OS). |
modification_time |
datetime | None
|
Last modification time. |
access_time |
datetime | None
|
Last access time. |
metadata_change_time |
datetime | None
|
Last metadata change time (read-only on most systems). |
Example
timestamps = FileTimestamps.from_file(Path("video.mp4")) print(f"Created: {timestamps.birth_time}") print(f"Modified: {timestamps.modification_time}")
from_file
classmethod
¶
Extract timestamps from a file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the file. |
required |
Returns:
| Type | Description |
|---|---|
FileTimestamps
|
FileTimestamps with all available timestamp information. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
TimestampReadError
|
If reading timestamps fails. |
Source code in src/video_converter/processors/timestamp.py
__str__
¶
Return human-readable timestamp information.
Source code in src/video_converter/processors/timestamp.py
TimestampSyncResult
dataclass
¶
TimestampSyncResult(success, source, dest, birth_time_synced=False, modification_time_synced=False, access_time_synced=False, error_message=None, warnings=list())
Result of a timestamp synchronization operation.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether synchronization completed successfully. |
source |
Path
|
Source file path. |
dest |
Path
|
Destination file path. |
birth_time_synced |
bool
|
Whether birth time was synchronized. |
modification_time_synced |
bool
|
Whether modification time was synchronized. |
access_time_synced |
bool
|
Whether access time was synchronized. |
error_message |
str | None
|
Error message if synchronization failed. |
warnings |
list[str]
|
Non-critical issues encountered. |
Example
result = synchronizer.sync_from_file(source, dest) if result.success: ... print("All timestamps synced") else: ... print(f"Error: {result.error_message}")
TimestampVerificationResult
dataclass
¶
TimestampVerificationResult(passed, original=None, converted=None, birth_time_match=False, modification_time_match=False, tolerance_seconds=TIMESTAMP_TOLERANCE_SECONDS, details='')
Result of timestamp verification between two files.
Attributes:
| Name | Type | Description |
|---|---|---|
passed |
bool
|
Whether timestamps match within tolerance. |
original |
FileTimestamps | None
|
Timestamps from original file. |
converted |
FileTimestamps | None
|
Timestamps from converted file. |
birth_time_match |
bool
|
Whether birth times match. |
modification_time_match |
bool
|
Whether modification times match. |
tolerance_seconds |
float
|
Tolerance used for comparison. |
details |
str
|
Additional verification details. |
Example
result = synchronizer.verify(original, converted) if result.passed: ... print("Timestamps preserved correctly") else: ... print(result.details)
TimestampSynchronizer
¶
Synchronize filesystem timestamps between video files.
This class handles copying timestamps from original files to converted files, ensuring that Finder sorting by date works correctly. It supports macOS-specific features like birth time (creation date).
Attributes:
| Name | Type | Description |
|---|---|---|
is_macos |
Whether running on macOS. |
Example
synchronizer = TimestampSynchronizer()
Sync from original file¶
result = synchronizer.sync_from_file( ... source=Path("original.mov"), ... dest=Path("converted.mp4"), ... )
Or sync from specific datetime¶
result = synchronizer.sync_from_datetime( ... path=Path("converted.mp4"), ... creation_date=datetime(2023, 1, 15, 10, 30, 0), ... )
Initialize TimestampSynchronizer.
Source code in src/video_converter/processors/timestamp.py
sync_from_file
¶
sync_from_file(source, dest, *, sync_birth_time=True, sync_modification_time=True, sync_access_time=True)
Copy timestamps from source file to destination file.
Copies creation date, modification date, and access time from the source file to the destination file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Source file to copy timestamps from. |
required |
dest
|
Path
|
Destination file to apply timestamps to. |
required |
sync_birth_time
|
bool
|
Whether to sync birth time (creation date). |
True
|
sync_modification_time
|
bool
|
Whether to sync modification time. |
True
|
sync_access_time
|
bool
|
Whether to sync access time. |
True
|
Returns:
| Type | Description |
|---|---|
TimestampSyncResult
|
TimestampSyncResult with details of the synchronization. |
Example
result = synchronizer.sync_from_file( ... source=Path("original.mov"), ... dest=Path("converted.mp4"), ... ) print(f"Success: {result.success}")
Source code in src/video_converter/processors/timestamp.py
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | |
sync_from_datetime
¶
Set file timestamps from datetime values.
Allows setting specific timestamps on a file without a source file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the file to modify. |
required |
creation_date
|
datetime | None
|
Creation date to set (macOS only). |
None
|
modification_date
|
datetime | None
|
Modification date to set. |
None
|
access_date
|
datetime | None
|
Access date to set. |
None
|
Returns:
| Type | Description |
|---|---|
TimestampSyncResult
|
TimestampSyncResult with details of the synchronization. |
Example
from datetime import datetime result = synchronizer.sync_from_datetime( ... path=Path("video.mp4"), ... creation_date=datetime(2023, 1, 15, 10, 30, 0), ... modification_date=datetime(2023, 1, 15, 10, 30, 0), ... )
Source code in src/video_converter/processors/timestamp.py
get_timestamps
¶
Get all timestamps from a file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to the file. |
required |
Returns:
| Type | Description |
|---|---|
FileTimestamps
|
FileTimestamps with all available timestamp information. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
TimestampReadError
|
If reading timestamps fails. |
Source code in src/video_converter/processors/timestamp.py
verify
¶
verify(original, converted, *, tolerance_seconds=TIMESTAMP_TOLERANCE_SECONDS, check_birth_time=True, check_modification_time=True)
Verify timestamps were preserved during conversion.
Compares timestamps between original and converted files to ensure they match within the specified tolerance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original
|
Path
|
Original source file. |
required |
converted
|
Path
|
Converted output file. |
required |
tolerance_seconds
|
float
|
Maximum allowed difference in seconds. |
TIMESTAMP_TOLERANCE_SECONDS
|
check_birth_time
|
bool
|
Whether to check birth time match. |
True
|
check_modification_time
|
bool
|
Whether to check modification time match. |
True
|
Returns:
| Type | Description |
|---|---|
TimestampVerificationResult
|
TimestampVerificationResult with detailed comparison. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If either file doesn't exist. |
Example
result = synchronizer.verify( ... original=Path("original.mov"), ... converted=Path("converted.mp4"), ... ) if result.passed: ... print("Timestamps preserved correctly")
Source code in src/video_converter/processors/timestamp.py
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | |