feat: Add comprehensive documentation suite and reorganize project structure

- Created complete documentation in docs/ directory
- Added PROJECT_OVERVIEW.md with feature highlights and getting started guide
- Added ARCHITECTURE.md with system design and technical details
- Added SECURITY.md with comprehensive security implementation guide
- Added DEVELOPMENT.md with development workflows and best practices
- Added DEPLOYMENT.md with production deployment instructions
- Added API.md with complete REST API documentation
- Added CONTRIBUTING.md with contribution guidelines
- Added CHANGELOG.md with version history and migration notes
- Reorganized all documentation files into docs/ directory for better organization
- Updated README.md with proper documentation links and quick navigation
- Enhanced project structure with professional documentation standards
This commit is contained in:
SamiAhmed7777
2025-10-21 00:39:45 -07:00
commit 0b7e2d0a5b
6080 changed files with 1332936 additions and 0 deletions

View File

@@ -0,0 +1,304 @@
<?php
/*******************************************************************************************************************
| Video Processing Helper Functions
| Convenience functions for video processing integration
|*******************************************************************************************************************/
defined('_ISVALID') or header('Location: /error');
/**
* Queue video for processing
* @param string $videoKey Video key
* @param string $inputFile Input file path
* @param array $options Processing options
* @return string|false Job ID or false on failure
*/
function queue_video_processing($videoKey, $inputFile, $options = [])
{
try {
$processor = new VVideoProcessor();
return $processor->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;
}
}