Domain API¶
This page documents the core domain models and events.
Models¶
Domain models are framework-agnostic business entities.
models ¶
Domain models for video compression pipeline.
Defines the core entities (VideoFile, CompressionJob) and enumerations that represent the problem domain, independent of infrastructure and UI.
JobStatus ¶
Bases: str, Enum
Enumeration of compression job states.
Attributes:
| Name | Type | Description |
|---|---|---|
PENDING |
Waiting to be processed. |
|
PROCESSING |
Currently being compressed. |
|
COMPLETED |
Successfully compressed. |
|
SKIPPED |
Skipped due to filter (e.g., already AV1, below min size). |
|
FAILED |
Compression failed; .err marker created. |
|
HW_CAP_LIMIT |
GPU hardware capability exceeded; may retry on CPU if enabled. |
|
INTERRUPTED |
Ctrl+C during processing; partial output may exist. |
ConfigSource ¶
Bases: str, Enum
Source of configuration parameters.
Attributes:
| Name | Type | Description |
|---|---|---|
GLOBAL |
Global conf/vbc.yaml configuration. |
|
LOCAL |
Local VBC.YAML in video directory. |
|
CLI |
CLI arguments (highest priority). |
VideoMetadata ¶
Bases: BaseModel
Extracted video stream information.
Attributes:
| Name | Type | Description |
|---|---|---|
width, |
height
|
Dimensions in pixels. |
codec |
str
|
Primary video codec name (h264, hevc, av1, etc.). |
audio_codec |
Optional[str]
|
Primary audio codec name (pcm_s16le, aac, etc.). |
fps |
float
|
Frames per second. |
camera_model |
Optional[str]
|
Inferred camera model from EXIF (for dynamic_quality matching). |
camera_raw |
Optional[str]
|
Raw EXIF camera string before normalization. |
custom_cq |
Optional[int]
|
Camera-specific CQ override from dynamic_quality[camera].cq. |
bitrate_kbps |
Optional[float]
|
Input stream bitrate. |
megapixels |
Optional[int]
|
Estimated megapixel value (for reference). |
color_space |
Optional[str]
|
FFmpeg color space (e.g., "bt709", "yuv420p"). |
pix_fmt |
Optional[str]
|
Pixel format from ffprobe (e.g., "yuv420p10le"). |
duration |
Optional[float]
|
Total duration in seconds. |
VideoFile ¶
Bases: BaseModel
A discovered video file to process.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
Path
|
Full path to the source file. |
size_bytes |
int
|
File size in bytes. |
metadata |
Optional[VideoMetadata]
|
Video stream information (extracted during discovery or processing). |
CompressionJob ¶
Bases: BaseModel
A video compression task being processed or completed.
Tracks the full lifecycle of a job from discovery through completion, including output metadata and error details.
Attributes:
| Name | Type | Description |
|---|---|---|
source_file |
VideoFile
|
The input video file. |
status |
JobStatus
|
Current job state (PENDING, PROCESSING, COMPLETED, FAILED, etc.). |
output_path |
Optional[Path]
|
Path where compressed video is written (created during processing). |
output_size_bytes |
Optional[int]
|
Final output file size (set when complete). |
error_message |
Optional[str]
|
Error description if status is FAILED or HW_CAP_LIMIT. |
duration_seconds |
Optional[float]
|
Wall-clock time spent in FFmpeg (excludes metadata ops). |
rotation_angle |
Optional[int]
|
Applied rotation in degrees (0, 90, 180, 270) or None. |
progress_percent |
float
|
[0-100] progress during encoding (updated by FFmpeg adapter). |
quality_value |
Optional[int]
|
CQ/CRF numeric value used for this job (legacy field). |
quality_display |
Optional[str]
|
Human-readable quality label (e.g., "CQ45", "200 Mbps"). |
config_source |
ConfigSource
|
Configuration source (GLOBAL, LOCAL, or CLI). |
verification_passed |
bool
|
Output verification result for completed jobs. |
verification_error |
Optional[str]
|
Verification error details when verification fails. |
Events¶
Domain events enable decoupled communication between components.
events ¶
Domain events for the video compression pipeline.
Events represent state changes and notifications that flow through the EventBus, decoupling the pipeline orchestrator from the UI layer and enabling extensibility.
See infrastructure/event_bus.py for the pub/sub mechanism.
Event ¶
Bases: BaseModel
Base class for all domain events.
Events are validated Pydantic models. They are not frozen by default.
HardwareCapabilityExceeded ¶
Bases: JobEvent
Emitted when GPU hardware limit is hit (HW_CAP_LIMIT status).
Can trigger CPU fallback if configured.
DiscoveryErrorEntry ¶
Bases: BaseModel
Discovery-time .err marker details used by Logs tab.
DiscoveryFinished ¶
Bases: Event
Emitted after file discovery and filtering is complete.
Provides summary counters of discovered and filtered files.
ProcessingPausedOnError ¶
WaitingForInput ¶
Bases: Event
Emitted by orchestrator when wait_on_finish=True and processing is done. Signals UI to display WAITING status and R/S hint.
Usage Examples¶
Working with VideoFile¶
from pathlib import Path
from vbc.domain.models import VideoFile, VideoMetadata
# Create a VideoFile
video = VideoFile(
path=Path("/videos/sample.mp4"),
size_bytes=125829120 # 120 MB
)
# Add metadata after extraction
video.metadata = VideoMetadata(
width=1920,
height=1080,
codec="h264",
fps=60.0,
camera_model="ILCE-7RM5",
bitrate_kbps=15000.0
)
# Access metadata
print(f"Resolution: {video.metadata.width}x{video.metadata.height}")
print(f"Camera: {video.metadata.camera_model}")
Working with CompressionJob¶
from vbc.domain.models import CompressionJob, JobStatus, VideoFile
from pathlib import Path
# Create a job
job = CompressionJob(
source_file=VideoFile(
path=Path("/videos/sample.mp4"),
size_bytes=125829120
),
output_path=Path("/videos_out/sample.mp4"),
rotation_angle=180
)
# Initial status
assert job.status == JobStatus.PENDING
# Update during processing
job.status = JobStatus.PROCESSING
# Mark as completed
job.status = JobStatus.COMPLETED
job.output_size_bytes = 45891200 # 43 MB
job.duration_seconds = 127.5
# Calculate compression ratio
ratio = job.output_size_bytes / job.source_file.size_bytes
savings = (1 - ratio) * 100
print(f"Compression: {savings:.1f}% savings") # 63.5% savings
Using Events¶
from vbc.infrastructure.event_bus import EventBus
from vbc.domain.events import JobStarted, JobCompleted
from vbc.domain.models import CompressionJob, VideoFile
from pathlib import Path
# Create event bus
bus = EventBus()
# Subscribe to events
def on_job_started(event: JobStarted):
print(f"Job started: {event.job.source_file.path.name}")
def on_job_completed(event: JobCompleted):
print(f"Job completed: {event.job.source_file.path.name}")
bus.subscribe(JobStarted, on_job_started)
bus.subscribe(JobCompleted, on_job_completed)
# Publish events
job = CompressionJob(
source_file=VideoFile(path=Path("video.mp4"), size_bytes=1000000)
)
bus.publish(JobStarted(job=job))
# Output: Job started: video.mp4
bus.publish(JobCompleted(job=job))
# Output: Job completed: video.mp4
Job Status Transitions¶
from vbc.domain.models import JobStatus
# Valid transitions
status = JobStatus.PENDING
status = JobStatus.PROCESSING
status = JobStatus.COMPLETED
# Error states
status = JobStatus.FAILED # Generic failure
status = JobStatus.HW_CAP_LIMIT # Hardware capability exceeded
status = JobStatus.SKIPPED # Skipped (AV1, camera filter, etc.)
status = JobStatus.INTERRUPTED # User interrupted (Ctrl+C)
Event Reference¶
| Event | Trigger | Data | Use Case |
|---|---|---|---|
DiscoveryStarted |
Orchestrator starts scanning | directory: Path |
UI: Show "Scanning..." |
DiscoveryFinished |
Scanning complete | File counts | UI: Update totals |
JobStarted |
Job begins processing | job: CompressionJob |
UI: Add to active list |
JobCompleted |
Job finishes successfully | job: CompressionJob |
UI: Update stats |
JobFailed |
Job fails | job, error_message |
UI: Increment errors |
HardwareCapabilityExceeded |
GPU lacks capability | job |
UI: Show HW_CAP count |
JobProgressUpdated |
FFmpeg progress update | progress_percent |
UI: Update progress bar |
QueueUpdated |
Pending files changed | pending_files: List |
UI: Show next in queue |
ActionMessage |
User action feedback | message: str |
UI: Show for 60s |
ProcessingFinished |
All jobs done | - | UI: Show completion |
RefreshRequested |
User pressed 'R' | - | Orchestrator: Re-scan |
ThreadControlEvent |
User pressed </> |
change: int |
Orchestrator: Adjust threads |
RequestShutdown |
User pressed 'S' | - | Orchestrator: Stop accepting jobs |
InterruptRequested |
User pressed Ctrl+C | - | Orchestrator: Terminate active jobs |