'https://your-hook.com']); * $processor->sendGenerationData($data); */ class AudioWebhookProcessor { private $config; private $defaultWebhookUrl = 'https://hook.us1.make.celonis.com/sbhcpk0athbdbxxmgijxc5sbwtjsg33h'; /** * Initialize webhook processor with configuration * * @param array $config Configuration options: * - webhook_url: Target webhook URL (optional) * - client: Default client name (optional) * - user_email: Default user email (optional) * - deliverable_number: Default deliverable number (optional) * - timeout: cURL timeout in seconds (default: 30) * - verify_ssl: Whether to verify SSL certificates (default: true) */ public function __construct($config = []) { $this->config = array_merge([ 'webhook_url' => $this->defaultWebhookUrl, 'client' => 'Auto-Approved', 'user_email' => 'ai-comp-setup@oliver.agency', 'deliverable_number' => '1000000', 'timeout' => 30, 'verify_ssl' => true ], $config); } /** * Send AI sound generation data to webhook * * @param array $data Generation data: * - prompt: The user's text prompt (required) * - generation_type: Type of AI generation (ElevenLabs, etc.) * - settings: Generation settings array (duration, prompt_influence, etc.) * - audio_data: Raw audio binary data OR audio URL OR file path * - audio_url: Alternative to audio_data - URL to download audio * - audio_file: Alternative to audio_data - file path to read audio * - client: Client name (overrides default) * - user_email: User email (overrides default) * - deliverable_number: Deliverable number (overrides default) * - additional_data: Extra data to include in webhook * @param string $webhookUrl Optional webhook URL override * @return bool True on success, false on failure */ public function sendGenerationData($data, $webhookUrl = null) { $webhookUrl = $webhookUrl ?: $this->config['webhook_url']; // Build standardized webhook data $webhookData = $this->buildWebhookData($data); // Send the webhook return $this->sendWebhook($webhookData, $webhookUrl); } /** * Build standardized webhook data structure for audio * * @param array $data Input data * @return array Standardized webhook data */ private function buildWebhookData($data) { $webhookData = [ 'client' => $data['client'] ?? $this->config['client'], 'deliverableNumber' => $data['deliverable_number'] ?? $this->config['deliverable_number'], 'userEmail' => $data['user_email'] ?? $this->config['user_email'], 'generationType' => $data['generation_type'] ?? 'ElevenLabs Sound Effects', 'settings' => $data['settings'] ?? [], 'timestamp' => time(), ]; // Add prompt to settings if provided if (isset($data['prompt'])) { $webhookData['settings']['prompt'] = $data['prompt']; } // Process audio data if provided if (isset($data['audio_data'])) { $normalized = $this->normalizeAudioData($data['audio_data']); if ($normalized) { $webhookData['audioFile'] = $normalized['base64']; $webhookData['audioMimeType'] = $normalized['mime_type']; } } elseif (isset($data['audio_url'])) { $normalized = $this->processAudioUrl($data['audio_url']); if ($normalized) { $webhookData['audioFile'] = $normalized['base64']; $webhookData['audioMimeType'] = $normalized['mime_type']; } } elseif (isset($data['audio_file'])) { $normalized = $this->processAudioFile($data['audio_file']); if ($normalized) { $webhookData['audioFile'] = $normalized['base64']; $webhookData['audioMimeType'] = $normalized['mime_type']; } } // Add any additional data if (isset($data['additional_data']) && is_array($data['additional_data'])) { $webhookData = array_merge($webhookData, $data['additional_data']); } return $webhookData; } /** * Normalize audio data to standard format * * @param mixed $audioData Raw binary data, base64 string, or data URI * @return array|null Normalized audio data or null on failure */ private function normalizeAudioData($audioData) { // If already a data URI, extract the data if (is_string($audioData) && strpos($audioData, 'data:') === 0) { $parts = explode(',', $audioData, 2); if (count($parts) === 2) { $mimeType = explode(';', explode(':', $parts[0])[1])[0]; $audioData = base64_decode($parts[1]); } } // If base64 encoded string, decode it elseif (is_string($audioData) && base64_decode($audioData, true) !== false) { $audioData = base64_decode($audioData); } // Detect mime type $finfo = new finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->buffer($audioData); // Validate that it's an audio file if (strpos($mimeType, 'audio/') !== 0) { // Try common audio extensions based on magic bytes $audioTypes = [ 'audio/mpeg' => ["\xFF\xFB", "\xFF\xF3", "\xFF\xF2"], // MP3 'audio/wav' => ["RIFF"], // WAV 'audio/ogg' => ["OggS"], // OGG 'audio/mp4' => ["\x00\x00\x00"], // M4A/MP4 ]; foreach ($audioTypes as $type => $signatures) { foreach ($signatures as $signature) { if (strpos($audioData, $signature) === 0) { $mimeType = $type; break 2; } } } } return [ 'mime_type' => $mimeType, 'base64' => 'data:' . $mimeType . ';base64,' . base64_encode($audioData), 'data' => $audioData, 'size' => strlen($audioData) ]; } /** * Process audio from URL * * @param string $audioUrl URL to download * @return array|null Normalized audio data or null on failure */ private function processAudioUrl($audioUrl) { $context = stream_context_create([ 'http' => [ 'timeout' => $this->config['timeout'], 'user_agent' => 'AudioWebhookProcessor/1.0' ] ]); $audioData = @file_get_contents($audioUrl, false, $context); if ($audioData === false) { return null; } return $this->normalizeAudioData($audioData); } /** * Process audio from file path * * @param string $filePath Path to audio file * @return array|null Normalized audio data or null on failure */ private function processAudioFile($filePath) { if (!file_exists($filePath)) { return null; } $audioData = file_get_contents($filePath); if ($audioData === false) { return null; } return $this->normalizeAudioData($audioData); } /** * Send webhook using cURL * * @param array $data Data to send * @param string $webhookUrl Target URL * @return bool True on success, false on failure */ private function sendWebhook($data, $webhookUrl) { $ch = curl_init($webhookUrl); curl_setopt_array($ch, [ CURLOPT_POST => 1, CURLOPT_POSTFIELDS => json_encode($data), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => $this->config['verify_ssl'], CURLOPT_TIMEOUT => $this->config['timeout'], CURLOPT_USERAGENT => 'AudioWebhookProcessor/1.0' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); // Log errors if debugging is enabled if ($httpCode < 200 || $httpCode >= 300 || !empty($curlError)) { error_log("Audio Webhook failed: HTTP {$httpCode}, Error: {$curlError}, URL: {$webhookUrl}"); return false; } return true; } /** * Test webhook endpoint connectivity * * @param string $webhookUrl Optional URL to test (uses default if not provided) * @return array Test results with status, http_code, and response_time */ public function testWebhook($webhookUrl = null) { $webhookUrl = $webhookUrl ?: $this->config['webhook_url']; $testData = [ 'test' => true, 'timestamp' => time(), 'client' => 'AudioWebhookProcessor Test', 'generationType' => 'ElevenLabs Sound Effects Test', 'settings' => [ 'prompt' => 'Test sound generation', 'duration_seconds' => 5.0, 'prompt_influence' => 0.3 ] ]; $startTime = microtime(true); $ch = curl_init($webhookUrl); curl_setopt_array($ch, [ CURLOPT_POST => 1, CURLOPT_POSTFIELDS => json_encode($testData), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => $this->config['verify_ssl'], CURLOPT_TIMEOUT => $this->config['timeout'], CURLOPT_USERAGENT => 'AudioWebhookProcessor/1.0 Test' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); $responseTime = round((microtime(true) - $startTime) * 1000, 2); curl_close($ch); return [ 'success' => ($httpCode >= 200 && $httpCode < 300 && empty($curlError)), 'http_code' => $httpCode, 'response_time_ms' => $responseTime, 'error' => $curlError, 'response' => $response ]; } /** * Get current configuration * * @return array Current configuration (sensitive values masked) */ public function getConfig() { $config = $this->config; // Mask sensitive webhook URL if (isset($config['webhook_url'])) { $config['webhook_url'] = substr($config['webhook_url'], 0, 30) . '...'; } return $config; } /** * Update configuration * * @param array $newConfig New configuration values * @return void */ public function updateConfig($newConfig) { $this->config = array_merge($this->config, $newConfig); } } /** * Convenience function for quick audio webhook sending * * @param array $data Generation data * @param string $webhookUrl Webhook URL * @param array $config Optional processor configuration * @return bool Success status */ function sendAudioWebhook($data, $webhookUrl = null, $config = []) { if ($webhookUrl) { $config['webhook_url'] = $webhookUrl; } $processor = new AudioWebhookProcessor($config); return $processor->sendGenerationData($data); } ?>