getRealPath(); $fileinfo->isDir() ? rmdir($filePath) : unlink($filePath); } rmdir($dir); } // STEP 1: Read and decode JSON input $raw = file_get_contents("php://input"); $data = json_decode($raw, true); if (!isset($data['videos']) || !is_array($data['videos'])) { echo json_encode(['success' => false, 'error' => 'Missing or invalid videos in JSON']); exit; } $videos = $data['videos']; $ffmpeg = '/usr/bin/ffmpeg'; // Ensure this path is correct $tmpDir = sys_get_temp_dir() . '/concat_text_video_' . uniqid(); mkdir($tmpDir, 0777, true); $listFile = "$tmpDir/list.txt"; $finalOutput = "$tmpDir/final.mp4"; // --- Configuration for Text Overlay (Customize these) --- $fontPath = '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'; // Adjust to a font file on your server $fontSize = 48; $fontColor = 'white'; $borderColor = 'black'; // Outline for text $borderWidth = 2; $textX = '(w-text_w)/2'; // Center horizontally $textY = 'h-th-20'; // 20 pixels from the bottom // Array to hold paths of processed videos (with text) $processedVideoPaths = []; // STEP 2: Download videos and process each with text overlay foreach ($videos as $i => $video) { $url = $video['url']; $downloadedPath = "$tmpDir/video_downloaded_$i.mp4"; $processedPath = "$tmpDir/video_processed_$i.mp4"; // Path for video after text overlay $text = isset($video['text']) ? $video['text'] : ''; // Get text, default to empty string // 2.1 Download the video $videoData = @file_get_contents($url); if (!$videoData) { echo json_encode(['success' => false, 'error' => "Failed to download: $url"]); cleanUpDir($tmpDir); exit; } file_put_contents($downloadedPath, $videoData); // 2.2 Prepare text for FFmpeg (escape special characters) // FFmpeg drawtext filter requires specific escaping for special characters like ' : \ // Simple way for now: just double quotes and newline $escapedText = str_replace(["'", ":", "\\", "\n"], ["\\'", "\\:", "\\\\", " "], $text); $escapedText = str_replace('"', '\"', $escapedText); // Escape double quotes // 2.3 Construct FFmpeg command for text overlay // Use scale=1920:-2 to standardize width to 1920px (height adjusted automatically) for consistency // This assumes you want a standard resolution. Adjust as needed. // Ensure the font file exists and is readable by the web server user. $ffmpegCommand = "$ffmpeg -i \"$downloadedPath\" -vf \"scale=1920:-2,drawtext=" . "fontfile='$fontPath':" . "text='$escapedText':" . "x=$textX:y=$textY:" . "fontsize=$fontSize:" . "fontcolor=$fontColor:" . "bordercolor=$borderColor:" . "borderw=$borderWidth:" . "box=1:boxcolor=black@0.5:boxborderw=10" . // Add a semi-transparent background box for text "\" -c:v libx264 -preset veryfast -crf 23 -c:a aac -b:a 128k -ar 44100 \"$processedPath\" 2>&1"; // Debugging: Uncomment to see the FFmpeg command // error_log("FFmpeg Command for video $i: " . $ffmpegCommand); // 2.4 Execute FFmpeg command for text overlay exec($ffmpegCommand, $output, $code); if ($code !== 0 || !file_exists($processedPath)) { echo json_encode(['success' => false, 'error' => "FFmpeg failed to process video with text: $url", 'details' => $output]); cleanUpDir($tmpDir); exit; } // Add processed video to the list for concatenation $processedVideoPaths[] = $processedPath; file_put_contents($listFile, "file '$processedPath'\n", FILE_APPEND); } // STEP 3: Run FFmpeg to concatenate processed videos // It's crucial that all processed videos have compatible streams for -c copy to work. // The previous step ensures this by re-encoding each to libx264/aac. exec("$ffmpeg -f concat -safe 0 -i $listFile -c copy \"$finalOutput\" 2>&1", $output, $code); if ($code !== 0 || !file_exists($finalOutput)) { cleanUpDir($tmpDir); echo json_encode(['success' => false, 'error' => 'FFmpeg concatenation failed', 'details' => $output]); exit; } // STEP 4: Move output to public folder $publicFolder = __DIR__ . '/videos/'; $publicName = 'concat_' . time() . '.mp4'; $publicPath = $publicFolder . $publicName; // Ensure your web server serves this path $videoUrl = 'https://maqaayad.dahabside.com/video-api/videos/' . $publicName; if (!file_exists($publicFolder)) { mkdir($publicFolder, 0755, true); } copy($finalOutput, $publicPath); // STEP 5: Send to webhook $WEBHOOK_URL = 'https://connect.pabbly.com/workflow/sendwebhookdata/IjU3NjYwNTY4MDYzZjA0MzA1MjZlNTUzYzUxM2Ii_pc'; $payload = json_encode([ 'video_url' => $videoUrl, 'texts' => array_column($videos, 'text') // Still send all texts in the webhook ]); $context = stream_context_create([ 'http' => [ 'header' => "Content-Type: application/json", 'method' => 'POST', 'content' => $payload ] ]); $webhookResult = @file_get_contents($WEBHOOK_URL, false, $context); // STEP 6: Clean up temp files cleanUpDir($tmpDir); // STEP 7: Return result echo json_encode([ 'success' => true, 'video_url' => $videoUrl, 'webhook_result' => $webhookResult ]); ?>