mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 10:51:05 -05:00
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
161 lines
5.3 KiB
Python
161 lines
5.3 KiB
Python
"""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}")
|