mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 10:51:05 -05:00
Core Systems:
Component-based architecture with lifecycle management Enhanced error handling and recovery mechanisms Comprehensive state management and tracking Event-driven architecture with monitoring Queue Management: Multiple processing strategies for different scenarios Advanced state management with recovery Comprehensive metrics and health monitoring Sophisticated cleanup system with multiple strategies Processing Pipeline: Enhanced message handling with validation Improved URL extraction and processing Better queue management and monitoring Advanced cleanup mechanisms Overall Benefits: Better code organization and maintainability Improved error handling and recovery Enhanced monitoring and reporting More robust and reliable system
This commit is contained in:
160
videoarchiver/ffmpeg/verification_manager.py
Normal file
160
videoarchiver/ffmpeg/verification_manager.py
Normal file
@@ -0,0 +1,160 @@
|
||||
"""Module for verifying FFmpeg functionality"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from .exceptions import (
|
||||
TimeoutError,
|
||||
VerificationError,
|
||||
EncodingError,
|
||||
handle_ffmpeg_error
|
||||
)
|
||||
|
||||
logger = logging.getLogger("FFmpegVerification")
|
||||
|
||||
class VerificationManager:
|
||||
"""Handles verification of FFmpeg functionality"""
|
||||
|
||||
def __init__(self, process_manager):
|
||||
self.process_manager = process_manager
|
||||
|
||||
def verify_ffmpeg(
|
||||
self,
|
||||
ffmpeg_path: Path,
|
||||
ffprobe_path: Path,
|
||||
gpu_info: Dict[str, bool]
|
||||
) -> None:
|
||||
"""Verify FFmpeg functionality with comprehensive checks
|
||||
|
||||
Args:
|
||||
ffmpeg_path: Path to FFmpeg binary
|
||||
ffprobe_path: Path to FFprobe binary
|
||||
gpu_info: Dictionary of GPU availability
|
||||
|
||||
Raises:
|
||||
VerificationError: If verification fails
|
||||
TimeoutError: If verification times out
|
||||
EncodingError: If required encoders are missing
|
||||
"""
|
||||
try:
|
||||
# Check FFmpeg version
|
||||
self._verify_ffmpeg_version(ffmpeg_path)
|
||||
|
||||
# Check FFprobe version
|
||||
self._verify_ffprobe_version(ffprobe_path)
|
||||
|
||||
# Check FFmpeg capabilities
|
||||
self._verify_ffmpeg_capabilities(ffmpeg_path, gpu_info)
|
||||
|
||||
logger.info("FFmpeg verification completed successfully")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"FFmpeg verification failed: {e}")
|
||||
if isinstance(e, (TimeoutError, EncodingError, VerificationError)):
|
||||
raise
|
||||
raise VerificationError(f"FFmpeg verification failed: {e}")
|
||||
|
||||
def _verify_ffmpeg_version(self, ffmpeg_path: Path) -> None:
|
||||
"""Verify FFmpeg version"""
|
||||
try:
|
||||
result = self._execute_command(
|
||||
[str(ffmpeg_path), "-version"],
|
||||
"FFmpeg version check"
|
||||
)
|
||||
logger.info(f"FFmpeg version: {result.stdout.split()[2]}")
|
||||
except Exception as e:
|
||||
raise VerificationError(f"FFmpeg version check failed: {e}")
|
||||
|
||||
def _verify_ffprobe_version(self, ffprobe_path: Path) -> None:
|
||||
"""Verify FFprobe version"""
|
||||
try:
|
||||
result = self._execute_command(
|
||||
[str(ffprobe_path), "-version"],
|
||||
"FFprobe version check"
|
||||
)
|
||||
logger.info(f"FFprobe version: {result.stdout.split()[2]}")
|
||||
except Exception as e:
|
||||
raise VerificationError(f"FFprobe version check failed: {e}")
|
||||
|
||||
def _verify_ffmpeg_capabilities(
|
||||
self,
|
||||
ffmpeg_path: Path,
|
||||
gpu_info: Dict[str, bool]
|
||||
) -> None:
|
||||
"""Verify FFmpeg capabilities and encoders"""
|
||||
try:
|
||||
result = self._execute_command(
|
||||
[str(ffmpeg_path), "-hide_banner", "-encoders"],
|
||||
"FFmpeg capabilities check"
|
||||
)
|
||||
|
||||
# Verify required encoders
|
||||
required_encoders = self._get_required_encoders(gpu_info)
|
||||
available_encoders = result.stdout.lower()
|
||||
|
||||
missing_encoders = [
|
||||
encoder for encoder in required_encoders
|
||||
if encoder not in available_encoders
|
||||
]
|
||||
|
||||
if missing_encoders:
|
||||
logger.warning(f"Missing encoders: {', '.join(missing_encoders)}")
|
||||
if "libx264" in missing_encoders:
|
||||
raise EncodingError("Required encoder libx264 not available")
|
||||
|
||||
except Exception as e:
|
||||
if isinstance(e, EncodingError):
|
||||
raise
|
||||
raise VerificationError(f"FFmpeg capabilities check failed: {e}")
|
||||
|
||||
def _execute_command(
|
||||
self,
|
||||
command: List[str],
|
||||
operation: str,
|
||||
timeout: int = 10
|
||||
) -> subprocess.CompletedProcess:
|
||||
"""Execute a command with proper error handling"""
|
||||
try:
|
||||
result = self.process_manager.execute_command(
|
||||
command,
|
||||
timeout=timeout,
|
||||
check=False
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
error = handle_ffmpeg_error(result.stderr)
|
||||
logger.error(f"{operation} failed: {result.stderr}")
|
||||
raise error
|
||||
|
||||
return result
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
raise TimeoutError(f"{operation} timed out")
|
||||
except Exception as e:
|
||||
if isinstance(e, (TimeoutError, EncodingError)):
|
||||
raise
|
||||
raise VerificationError(f"{operation} failed: {e}")
|
||||
|
||||
def _get_required_encoders(self, gpu_info: Dict[str, bool]) -> List[str]:
|
||||
"""Get list of required encoders based on GPU availability"""
|
||||
required_encoders = ["libx264"]
|
||||
|
||||
if gpu_info["nvidia"]:
|
||||
required_encoders.append("h264_nvenc")
|
||||
elif gpu_info["amd"]:
|
||||
required_encoders.append("h264_amf")
|
||||
elif gpu_info["intel"]:
|
||||
required_encoders.append("h264_qsv")
|
||||
|
||||
return required_encoders
|
||||
|
||||
def verify_binary_permissions(self, binary_path: Path) -> None:
|
||||
"""Verify and set binary permissions"""
|
||||
try:
|
||||
if os.name != "nt": # Not Windows
|
||||
os.chmod(str(binary_path), 0o755)
|
||||
except Exception as e:
|
||||
raise VerificationError(f"Failed to set binary permissions: {e}")
|
||||
Reference in New Issue
Block a user