video-processor/examples/video_360_example.py
Ryan Malloy cfda5d6777 Implement comprehensive 360° video processing support
Core Features:
- 360° video detection via metadata, aspect ratio, and filename patterns
- Automatic projection type identification (equirectangular, cubemap, etc.)
- 360° thumbnail generation with multiple viewing angles (front, back, up, down, stereographic)
- 360° sprite sheet creation for immersive video players
- Enhanced metadata extraction with spherical video information

Configuration:
- Optional 360° settings in ProcessorConfig with validation
- Bitrate multipliers for 360° content (typically 2.5x for quality)
- Configurable thumbnail projections and generation options
- Graceful degradation when optional dependencies unavailable

Architecture:
- Modular design with optional dependency detection
- Video360Detection class for intelligent 360° identification
- Thumbnail360Generator for perspective and stereographic projections
- Video360Utils for bitrate/resolution recommendations
- Extended VideoProcessingResult with 360° outputs

Testing & Examples:
- Comprehensive test suite covering detection, configuration, and integration
- Working example demonstrating 360° processing workflow
- Proper error handling and dependency validation

Backward Compatibility:
- All existing functionality preserved
- 360° features completely optional and isolated
- Clear error messages when dependencies missing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 09:45:09 -06:00

253 lines
9.3 KiB
Python

#!/usr/bin/env python3
"""
360° Video Processing Example
This example demonstrates how to use the video processor with 360° video features.
Prerequisites:
- Install with 360° support: uv add "video-processor[video-360-full]"
- Have a 360° video file to process
Features demonstrated:
- Automatic 360° video detection
- 360° thumbnail generation with multiple viewing angles
- 360° sprite sheet creation
- Configuration options for 360° processing
"""
import tempfile
from pathlib import Path
from video_processor import ProcessorConfig, VideoProcessor, HAS_360_SUPPORT
def check_360_dependencies():
"""Check if 360° dependencies are available."""
print("=== 360° Video Processing Dependencies ===")
print(f"360° Support Available: {HAS_360_SUPPORT}")
if not HAS_360_SUPPORT:
try:
from video_processor import Video360Utils
missing = Video360Utils.get_missing_dependencies()
print(f"Missing dependencies: {missing}")
print("\nTo install 360° support:")
print(" uv add 'video-processor[video-360-full]'")
print(" # or")
print(" pip install 'video-processor[video-360-full]'")
return False
except ImportError:
print("360° utilities not available")
return False
print("✅ All 360° dependencies available")
return True
def basic_360_processing():
"""Demonstrate basic 360° video processing."""
print("\n=== Basic 360° Video Processing ===")
# Create configuration with 360° features enabled
config = ProcessorConfig(
base_path=Path("/tmp/video_360_output"),
output_formats=["mp4", "webm"],
quality_preset="high", # Use high quality for 360° videos
# 360° specific settings
enable_360_processing=True,
auto_detect_360=True, # Automatically detect 360° videos
generate_360_thumbnails=True,
thumbnail_360_projections=["front", "back", "up", "stereographic"], # Multiple viewing angles
video_360_bitrate_multiplier=2.5, # Higher bitrate for 360° videos
)
print(f"Configuration created with 360° processing: {config.enable_360_processing}")
print(f"Auto-detect 360° videos: {config.auto_detect_360}")
print(f"360° thumbnail projections: {config.thumbnail_360_projections}")
print(f"Bitrate multiplier for 360° videos: {config.video_360_bitrate_multiplier}x")
# Create processor
processor = VideoProcessor(config)
# Example input file (would need to be a real 360° video file)
input_file = Path("example_360_video.mp4")
if input_file.exists():
print(f"\nProcessing 360° video: {input_file}")
result = processor.process_video(
input_path=input_file,
output_dir="360_output"
)
print(f"✅ Processing complete!")
print(f"Video ID: {result.video_id}")
print(f"Output formats: {list(result.encoded_files.keys())}")
# Show 360° detection results
if result.metadata and "video_360" in result.metadata:
video_360_info = result.metadata["video_360"]
print(f"\n360° Video Detection:")
print(f" Is 360° video: {video_360_info['is_360_video']}")
print(f" Projection type: {video_360_info['projection_type']}")
print(f" Detection confidence: {video_360_info['confidence']}")
print(f" Detection methods: {video_360_info['detection_methods']}")
# Show regular thumbnails
if result.thumbnails:
print(f"\nRegular thumbnails generated: {len(result.thumbnails)}")
for thumb in result.thumbnails:
print(f" 📸 {thumb}")
# Show 360° thumbnails
if result.thumbnails_360:
print(f"\n360° thumbnails generated: {len(result.thumbnails_360)}")
for key, thumb_path in result.thumbnails_360.items():
print(f" 🌐 {key}: {thumb_path}")
# Show 360° sprite files
if result.sprite_360_files:
print(f"\n360° sprite sheets generated: {len(result.sprite_360_files)}")
for angle, (sprite_path, webvtt_path) in result.sprite_360_files.items():
print(f" 🎞️ {angle}:")
print(f" Sprite: {sprite_path}")
print(f" WebVTT: {webvtt_path}")
else:
print(f"❌ Input file not found: {input_file}")
print("Create a 360° video file or modify the path in this example.")
def manual_360_detection():
"""Demonstrate manual 360° video detection."""
print("\n=== Manual 360° Video Detection ===")
from video_processor import Video360Detection
# Example: Test detection on various metadata scenarios
test_cases = [
{
"name": "Aspect Ratio Detection (4K 360°)",
"metadata": {
"video": {"width": 3840, "height": 1920},
"filename": "sample_video.mp4"
}
},
{
"name": "Filename Pattern Detection",
"metadata": {
"video": {"width": 1920, "height": 1080},
"filename": "my_360_VR_video.mp4"
}
},
{
"name": "Spherical Metadata Detection",
"metadata": {
"video": {"width": 2560, "height": 1280},
"filename": "video.mp4",
"format": {
"tags": {
"Spherical": "1",
"ProjectionType": "equirectangular",
"StereoMode": "mono"
}
}
}
},
{
"name": "Regular Video (No 360°)",
"metadata": {
"video": {"width": 1920, "height": 1080},
"filename": "regular_video.mp4"
}
}
]
for test_case in test_cases:
print(f"\n{test_case['name']}:")
result = Video360Detection.detect_360_video(test_case["metadata"])
print(f" 360° Video: {result['is_360_video']}")
if result['is_360_video']:
print(f" Projection: {result['projection_type']}")
print(f" Confidence: {result['confidence']:.1f}")
print(f" Methods: {result['detection_methods']}")
def advanced_360_configuration():
"""Demonstrate advanced 360° configuration options."""
print("\n=== Advanced 360° Configuration ===")
from video_processor import Video360Utils
# Show bitrate recommendations
print("Bitrate multipliers by projection type:")
projection_types = ["equirectangular", "cubemap", "cylindrical", "stereographic"]
for projection in projection_types:
multiplier = Video360Utils.get_recommended_bitrate_multiplier(projection)
print(f" {projection}: {multiplier}x")
# Show optimal resolutions
print("\nOptimal resolutions for equirectangular 360° videos:")
resolutions = Video360Utils.get_optimal_resolutions("equirectangular")
for width, height in resolutions[:5]: # Show first 5
print(f" {width}x{height} ({width//1000}K)")
# Create specialized configurations
print("\nSpecialized Configuration Examples:")
# High-quality archival processing
archival_config = ProcessorConfig(
enable_360_processing=True,
quality_preset="ultra",
video_360_bitrate_multiplier=3.0, # Even higher quality
thumbnail_360_projections=["front", "back", "left", "right", "up", "down"], # All angles
generate_360_thumbnails=True,
auto_detect_360=True,
)
print(f" 📚 Archival config: {archival_config.quality_preset} quality, {archival_config.video_360_bitrate_multiplier}x bitrate")
# Mobile-optimized processing
mobile_config = ProcessorConfig(
enable_360_processing=True,
quality_preset="medium",
video_360_bitrate_multiplier=2.0, # Lower for mobile
thumbnail_360_projections=["front", "stereographic"], # Minimal angles
generate_360_thumbnails=True,
auto_detect_360=True,
)
print(f" 📱 Mobile config: {mobile_config.quality_preset} quality, {mobile_config.video_360_bitrate_multiplier}x bitrate")
def main():
"""Run all 360° video processing examples."""
print("🌐 360° Video Processing Examples")
print("=" * 50)
# Check dependencies first
if not check_360_dependencies():
print("\n⚠️ 360° processing features are not fully available.")
print("Some examples will be skipped or show limited functionality.")
# Still show detection examples that work without full dependencies
manual_360_detection()
return
# Run all examples
try:
basic_360_processing()
manual_360_detection()
advanced_360_configuration()
print("\n✅ All 360° video processing examples completed successfully!")
except Exception as e:
print(f"\n❌ Error during 360° processing: {e}")
print("Make sure you have:")
print(" 1. Installed 360° dependencies: uv add 'video-processor[video-360-full]'")
print(" 2. A valid 360° video file to process")
if __name__ == "__main__":
main()