queueVideoProcessing($inputFile, $videoKey, $options); } catch (Exception $e) { VLogger::getInstance()->error('Failed to queue video processing', [ 'video_key' => $videoKey, 'input_file' => $inputFile, 'error' => $e->getMessage() ]); return false; } } /** * Process video immediately (synchronous) * @param string $videoKey Video key * @param string $inputFile Input file path * @param array $options Processing options * @return array Processing result */ function process_video_sync($videoKey, $inputFile, $options = []) { try { $processor = new VVideoProcessor(); return $processor->processVideo($inputFile, $videoKey, $options); } catch (Exception $e) { VLogger::getInstance()->error('Synchronous video processing failed', [ 'video_key' => $videoKey, 'input_file' => $inputFile, 'error' => $e->getMessage() ]); return [ 'success' => false, 'error' => $e->getMessage(), 'video_key' => $videoKey ]; } } /** * Get video processing status * @param string $videoKey Video key * @return array|false Processing status or false if not found */ function get_video_processing_status($videoKey) { try { $db = VDatabase::getInstance(); $query = "SELECT processing_status, processed_at, processing_error, available_formats, hls_available, thumbnails_generated FROM db_videofiles WHERE file_key = ?"; $result = $db->doQuery($query, [$videoKey]); $row = $db->doFetch($result); if ($row) { return [ 'status' => $row['processing_status'], 'processed_at' => $row['processed_at'], 'error' => $row['processing_error'], 'available_formats' => json_decode($row['available_formats'], true) ?: [], 'hls_available' => (bool)$row['hls_available'], 'thumbnails_generated' => (bool)$row['thumbnails_generated'] ]; } return false; } catch (Exception $e) { VLogger::getInstance()->error('Failed to get video processing status', [ 'video_key' => $videoKey, 'error' => $e->getMessage() ]); return false; } } /** * Queue thumbnail generation * @param string $fileKey File key * @param string $filePath File path * @param string $fileType File type (video, image) * @param array $sizes Thumbnail sizes * @return string|false Job ID or false on failure */ function queue_thumbnail_generation($fileKey, $filePath, $fileType, $sizes = []) { try { $queue = new VQueue(); $jobData = [ 'file_key' => $fileKey, 'file_path' => $filePath, 'file_type' => $fileType, 'sizes' => $sizes ?: [ 'small' => [160, 120], 'medium' => [320, 240], 'large' => [640, 480] ] ]; return $queue->enqueue('ThumbnailGenerationJob', $jobData, 'thumbnails'); } catch (Exception $e) { VLogger::getInstance()->error('Failed to queue thumbnail generation', [ 'file_key' => $fileKey, 'file_path' => $filePath, 'error' => $e->getMessage() ]); return false; } } /** * Queue notification * @param string $type Notification type (email, push, in_app, sms, webhook) * @param string $recipient Recipient (email, user ID, phone, URL) * @param string $subject Subject/title * @param string $message Message content * @param array $templateData Additional template data * @param string $priority Priority (low, normal, high, urgent) * @return string|false Job ID or false on failure */ function queue_notification($type, $recipient, $subject, $message, $templateData = [], $priority = 'normal') { try { $queue = new VQueue(); $jobData = [ 'type' => $type, 'recipient' => $recipient, 'subject' => $subject, 'message' => $message, 'template_data' => $templateData, 'priority' => $priority ]; $queuePriority = $priority === 'urgent' ? 2 : ($priority === 'high' ? 1 : 0); return $queue->enqueue('NotificationJob', $jobData, 'notifications', 0, $queuePriority); } catch (Exception $e) { VLogger::getInstance()->error('Failed to queue notification', [ 'type' => $type, 'recipient' => $recipient, 'error' => $e->getMessage() ]); return false; } } /** * Get queue statistics * @param string $queue Queue name (optional) * @return array Queue statistics */ function get_queue_stats($queue = null) { try { $queueInstance = new VQueue(); return $queueInstance->getQueueStats($queue); } catch (Exception $e) { VLogger::getInstance()->error('Failed to get queue statistics', [ 'queue' => $queue, 'error' => $e->getMessage() ]); return []; } } /** * Check if video processing is available * @return bool True if FFmpeg is available */ function is_video_processing_available() { static $available = null; if ($available === null) { // Check if FFmpeg is available $output = shell_exec('ffmpeg -version 2>&1'); $available = $output && strpos($output, 'ffmpeg version') !== false; } return $available; } /** * Get supported video formats * @return array Supported formats */ function get_supported_video_formats() { return [ 'mp4' => 'MP4 Video', 'avi' => 'AVI Video', 'mov' => 'QuickTime Video', 'wmv' => 'Windows Media Video', 'flv' => 'Flash Video', 'webm' => 'WebM Video', 'mkv' => 'Matroska Video', '3gp' => '3GP Video' ]; } /** * Get video processing formats * @return array Available processing formats */ function get_video_processing_formats() { return [ '1080p' => ['width' => 1920, 'height' => 1080, 'bitrate' => '5000k'], '720p' => ['width' => 1280, 'height' => 720, 'bitrate' => '2500k'], '480p' => ['width' => 854, 'height' => 480, 'bitrate' => '1000k'], '360p' => ['width' => 640, 'height' => 360, 'bitrate' => '750k'], '240p' => ['width' => 426, 'height' => 240, 'bitrate' => '400k'] ]; } /** * Estimate video processing time * @param string $inputFile Input file path * @param array $formats Formats to process * @return int Estimated processing time in seconds */ function estimate_video_processing_time($inputFile, $formats = ['720p', '480p', '360p']) { if (!file_exists($inputFile)) { return 0; } $fileSize = filesize($inputFile); $fileSizeMB = $fileSize / (1024 * 1024); // Rough estimation: 1MB takes about 2-5 seconds per format $baseTimePerMB = 3; // seconds $timePerFormat = $fileSizeMB * $baseTimePerMB; return (int)($timePerFormat * count($formats)); } /** * Clean up old processed files * @param int $daysOld Days old threshold * @return int Number of files cleaned */ function cleanup_old_processed_files($daysOld = 30) { try { $processedDir = _FPATH . 'f_data/processed/'; $cutoffTime = time() - ($daysOld * 24 * 60 * 60); $cleanedCount = 0; if (!is_dir($processedDir)) { return 0; } $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($processedDir), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($iterator as $file) { if ($file->isFile() && $file->getMTime() < $cutoffTime) { if (unlink($file->getPathname())) { $cleanedCount++; } } } VLogger::getInstance()->info('Cleaned up old processed files', [ 'days_old' => $daysOld, 'files_cleaned' => $cleanedCount ]); return $cleanedCount; } catch (Exception $e) { VLogger::getInstance()->error('Failed to cleanup old processed files', [ 'days_old' => $daysOld, 'error' => $e->getMessage() ]); return 0; } }