video-processor/tests/test_video_360.py
Ryan Malloy 840bd34f29 🎬 Video Processor v0.4.0 - Complete Multimedia Processing Platform
Professional video processing pipeline with AI analysis, 360° processing,
and adaptive streaming capabilities.

 Core Features:
• AI-powered content analysis with scene detection and quality assessment
• Next-generation codec support (AV1, HEVC, HDR10)
• Adaptive streaming (HLS/DASH) with smart bitrate ladders
• Complete 360° video processing with multiple projection support
• Spatial audio processing (Ambisonic, binaural, object-based)
• Viewport-adaptive streaming with up to 75% bandwidth savings
• Professional testing framework with video-themed HTML dashboards

🏗️ Architecture:
• Modern Python 3.11+ with full type hints
• Pydantic-based configuration with validation
• Async processing with Procrastinate task queue
• Comprehensive test coverage with 11 detailed examples
• Professional documentation structure

🚀 Production Ready:
• MIT License for open source use
• PyPI-ready package metadata
• Docker support for scalable deployment
• Quality assurance with ruff, mypy, and pytest
• Comprehensive example library

From simple encoding to immersive experiences - complete multimedia
processing platform for modern applications.
2025-09-22 01:18:49 -06:00

178 lines
6.7 KiB
Python

"""Tests for 360° video functionality."""
import pytest
from video_processor import HAS_360_SUPPORT, ProcessorConfig
from video_processor.utils.video_360 import Video360Detection, Video360Utils
class TestVideo360Detection:
"""Tests for 360° video detection."""
def test_aspect_ratio_detection(self):
"""Test 360° detection based on aspect ratio."""
# Mock metadata for 2:1 aspect ratio (typical 360° video)
metadata = {
"video": {
"width": 3840,
"height": 1920,
},
"filename": "test_video.mp4",
}
result = Video360Detection.detect_360_video(metadata)
assert result["is_360_video"] is True
assert "aspect_ratio" in result["detection_methods"]
assert result["confidence"] >= 0.8
def test_filename_pattern_detection(self):
"""Test 360° detection based on filename patterns."""
metadata = {
"video": {"width": 1920, "height": 1080},
"filename": "my_360_video.mp4",
}
result = Video360Detection.detect_360_video(metadata)
assert result["is_360_video"] is True
assert "filename" in result["detection_methods"]
assert result["projection_type"] == "equirectangular"
def test_spherical_metadata_detection(self):
"""Test 360° detection based on spherical metadata."""
metadata = {
"video": {"width": 1920, "height": 1080},
"filename": "test.mp4",
"format": {"tags": {"Spherical": "1", "ProjectionType": "equirectangular"}},
}
result = Video360Detection.detect_360_video(metadata)
assert result["is_360_video"] is True
assert "spherical_metadata" in result["detection_methods"]
assert result["confidence"] == 1.0
assert result["projection_type"] == "equirectangular"
def test_no_360_detection(self):
"""Test that regular videos are not detected as 360°."""
metadata = {
"video": {"width": 1920, "height": 1080},
"filename": "regular_video.mp4",
}
result = Video360Detection.detect_360_video(metadata)
assert result["is_360_video"] is False
assert result["confidence"] == 0.0
assert len(result["detection_methods"]) == 0
class TestVideo360Utils:
"""Tests for 360° video utilities."""
def test_bitrate_multipliers(self):
"""Test bitrate multipliers for different projection types."""
assert (
Video360Utils.get_recommended_bitrate_multiplier("equirectangular") == 2.5
)
assert Video360Utils.get_recommended_bitrate_multiplier("cubemap") == 2.0
assert Video360Utils.get_recommended_bitrate_multiplier("unknown") == 2.0
def test_optimal_resolutions(self):
"""Test optimal resolution recommendations."""
equirect_resolutions = Video360Utils.get_optimal_resolutions("equirectangular")
assert (3840, 1920) in equirect_resolutions # 4K 360°
assert (1920, 960) in equirect_resolutions # 2K 360°
def test_missing_dependencies(self):
"""Test missing dependency detection."""
missing = Video360Utils.get_missing_dependencies()
assert isinstance(missing, list)
# Without optional dependencies, these should be missing
if not HAS_360_SUPPORT:
assert "opencv-python" in missing
assert "py360convert" in missing
class TestProcessorConfig360:
"""Tests for 360° configuration."""
def test_default_360_settings(self):
"""Test default 360° configuration values."""
config = ProcessorConfig()
assert config.enable_360_processing == HAS_360_SUPPORT
assert config.auto_detect_360 is True
assert config.force_360_projection is None
assert config.video_360_bitrate_multiplier == 2.5
assert config.generate_360_thumbnails is True
assert "front" in config.thumbnail_360_projections
assert "stereographic" in config.thumbnail_360_projections
def test_360_validation_without_dependencies(self):
"""Test that 360° processing can't be enabled without dependencies."""
if not HAS_360_SUPPORT:
with pytest.raises(
ValueError, match="360° processing requires optional dependencies"
):
ProcessorConfig(enable_360_processing=True)
@pytest.mark.skipif(not HAS_360_SUPPORT, reason="360° dependencies not available")
def test_360_validation_with_dependencies(self):
"""Test that 360° processing can be enabled with dependencies."""
config = ProcessorConfig(enable_360_processing=True)
assert config.enable_360_processing is True
def test_bitrate_multiplier_validation(self):
"""Test bitrate multiplier validation."""
# Valid range
config = ProcessorConfig(video_360_bitrate_multiplier=3.0)
assert config.video_360_bitrate_multiplier == 3.0
# Invalid range should raise validation error
with pytest.raises(ValueError):
ProcessorConfig(video_360_bitrate_multiplier=0.5) # Below minimum
with pytest.raises(ValueError):
ProcessorConfig(video_360_bitrate_multiplier=6.0) # Above maximum
def test_custom_360_settings(self):
"""Test custom 360° configuration."""
config = ProcessorConfig(
auto_detect_360=False,
video_360_bitrate_multiplier=2.0,
generate_360_thumbnails=False,
thumbnail_360_projections=["front", "back"],
)
assert config.auto_detect_360 is False
assert config.video_360_bitrate_multiplier == 2.0
assert config.generate_360_thumbnails is False
assert config.thumbnail_360_projections == ["front", "back"]
# Integration test for basic video processor
class TestVideoProcessor360Integration:
"""Integration tests for 360° video processing."""
def test_processor_creation_without_360_support(self):
"""Test that video processor works without 360° support."""
from video_processor import VideoProcessor
config = ProcessorConfig() # 360° disabled by default when deps missing
processor = VideoProcessor(config)
assert processor.thumbnail_360_generator is None
@pytest.mark.skipif(not HAS_360_SUPPORT, reason="360° dependencies not available")
def test_processor_creation_with_360_support(self):
"""Test that video processor works with 360° support."""
from video_processor import VideoProcessor
config = ProcessorConfig(enable_360_processing=True)
processor = VideoProcessor(config)
assert processor.thumbnail_360_generator is not None