streaming part1

This commit is contained in:
2025-07-27 08:01:08 -07:00
parent 277d554ecc
commit 4b058c2405
17 changed files with 3072 additions and 683 deletions

242
vr180_streaming/config.py Normal file
View File

@@ -0,0 +1,242 @@
"""
Configuration management for VR180 streaming
"""
import yaml
from pathlib import Path
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
@dataclass
class InputConfig:
video_path: str
start_frame: int = 0
max_frames: Optional[int] = None
@dataclass
class StreamingOptions:
mode: bool = True
buffer_frames: int = 10
write_interval: int = 1 # Write every N frames
@dataclass
class ProcessingConfig:
scale_factor: float = 0.5
adaptive_scaling: bool = True
target_gpu_usage: float = 0.7
min_scale: float = 0.25
max_scale: float = 1.0
@dataclass
class DetectionConfig:
confidence_threshold: float = 0.7
model: str = "yolov8n"
device: str = "cuda"
@dataclass
class MattingConfig:
sam2_model_cfg: str = "sam2.1_hiera_l"
sam2_checkpoint: str = "segment-anything-2/checkpoints/sam2.1_hiera_large.pt"
memory_offload: bool = True
fp16: bool = True
continuous_correction: bool = True
correction_interval: int = 300
@dataclass
class StereoConfig:
mode: str = "master_slave" # "master_slave", "independent", "joint"
master_eye: str = "left"
disparity_correction: bool = True
consistency_threshold: float = 0.3
baseline: float = 65.0 # mm
focal_length: float = 1000.0 # pixels
@dataclass
class OutputConfig:
path: str
format: str = "greenscreen" # "alpha" or "greenscreen"
background_color: List[int] = field(default_factory=lambda: [0, 255, 0])
video_codec: str = "h264_nvenc"
quality_preset: str = "p4"
crf: int = 18
maintain_sbs: bool = True
@dataclass
class HardwareConfig:
device: str = "cuda"
max_vram_gb: float = 40.0
max_ram_gb: float = 48.0
@dataclass
class RecoveryConfig:
enable_checkpoints: bool = True
checkpoint_interval: int = 1000
auto_resume: bool = True
checkpoint_dir: str = "./checkpoints"
@dataclass
class PerformanceConfig:
profile_enabled: bool = True
log_interval: int = 100
memory_monitor: bool = True
class StreamingConfig:
"""Complete configuration for VR180 streaming processing"""
def __init__(self):
self.input = InputConfig("")
self.streaming = StreamingOptions()
self.processing = ProcessingConfig()
self.detection = DetectionConfig()
self.matting = MattingConfig()
self.stereo = StereoConfig()
self.output = OutputConfig("")
self.hardware = HardwareConfig()
self.recovery = RecoveryConfig()
self.performance = PerformanceConfig()
@classmethod
def from_yaml(cls, yaml_path: str) -> 'StreamingConfig':
"""Load configuration from YAML file"""
config = cls()
with open(yaml_path, 'r') as f:
data = yaml.safe_load(f)
# Update each section
if 'input' in data:
config.input = InputConfig(**data['input'])
if 'streaming' in data:
config.streaming = StreamingOptions(**data['streaming'])
if 'processing' in data:
for key, value in data['processing'].items():
setattr(config.processing, key, value)
if 'detection' in data:
config.detection = DetectionConfig(**data['detection'])
if 'matting' in data:
config.matting = MattingConfig(**data['matting'])
if 'stereo' in data:
config.stereo = StereoConfig(**data['stereo'])
if 'output' in data:
config.output = OutputConfig(**data['output'])
if 'hardware' in data:
config.hardware = HardwareConfig(**data['hardware'])
if 'recovery' in data:
config.recovery = RecoveryConfig(**data['recovery'])
if 'performance' in data:
for key, value in data['performance'].items():
setattr(config.performance, key, value)
return config
def to_dict(self) -> Dict[str, Any]:
"""Convert configuration to dictionary"""
return {
'input': {
'video_path': self.input.video_path,
'start_frame': self.input.start_frame,
'max_frames': self.input.max_frames
},
'streaming': {
'mode': self.streaming.mode,
'buffer_frames': self.streaming.buffer_frames,
'write_interval': self.streaming.write_interval
},
'processing': {
'scale_factor': self.processing.scale_factor,
'adaptive_scaling': self.processing.adaptive_scaling,
'target_gpu_usage': self.processing.target_gpu_usage,
'min_scale': self.processing.min_scale,
'max_scale': self.processing.max_scale
},
'detection': {
'confidence_threshold': self.detection.confidence_threshold,
'model': self.detection.model,
'device': self.detection.device
},
'matting': {
'sam2_model_cfg': self.matting.sam2_model_cfg,
'sam2_checkpoint': self.matting.sam2_checkpoint,
'memory_offload': self.matting.memory_offload,
'fp16': self.matting.fp16,
'continuous_correction': self.matting.continuous_correction,
'correction_interval': self.matting.correction_interval
},
'stereo': {
'mode': self.stereo.mode,
'master_eye': self.stereo.master_eye,
'disparity_correction': self.stereo.disparity_correction,
'consistency_threshold': self.stereo.consistency_threshold,
'baseline': self.stereo.baseline,
'focal_length': self.stereo.focal_length
},
'output': {
'path': self.output.path,
'format': self.output.format,
'background_color': self.output.background_color,
'video_codec': self.output.video_codec,
'quality_preset': self.output.quality_preset,
'crf': self.output.crf,
'maintain_sbs': self.output.maintain_sbs
},
'hardware': {
'device': self.hardware.device,
'max_vram_gb': self.hardware.max_vram_gb,
'max_ram_gb': self.hardware.max_ram_gb
},
'recovery': {
'enable_checkpoints': self.recovery.enable_checkpoints,
'checkpoint_interval': self.recovery.checkpoint_interval,
'auto_resume': self.recovery.auto_resume,
'checkpoint_dir': self.recovery.checkpoint_dir
},
'performance': {
'profile_enabled': self.performance.profile_enabled,
'log_interval': self.performance.log_interval,
'memory_monitor': self.performance.memory_monitor
}
}
def validate(self) -> List[str]:
"""Validate configuration and return list of errors"""
errors = []
# Check input
if not self.input.video_path:
errors.append("Input video path is required")
elif not Path(self.input.video_path).exists():
errors.append(f"Input video not found: {self.input.video_path}")
# Check output
if not self.output.path:
errors.append("Output path is required")
# Check scale factor
if not 0.1 <= self.processing.scale_factor <= 1.0:
errors.append("Scale factor must be between 0.1 and 1.0")
# Check SAM2 checkpoint
if not Path(self.matting.sam2_checkpoint).exists():
errors.append(f"SAM2 checkpoint not found: {self.matting.sam2_checkpoint}")
return errors