sound-effects/webhook_processor_audio.php
DJP 4c734e51d4 Initial commit: Sound Effects App
Added complete sound effects application with multiple versions (V1, V2),
configuration files, webhook functionality, and associated assets.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-14 16:04:47 -04:00

339 lines
No EOL
12 KiB
PHP

<?php
/**
* Audio Webhook Processor for AI Sound Generation Applications
*
* Adapted from the standardized WebhookProcessor for audio files.
* This class provides a standardized way to integrate webhook functionality
* into any application that generates AI audio/sound effects.
*
* Usage:
* require_once 'webhook_processor_audio.php';
* $processor = new AudioWebhookProcessor(['webhook_url' => '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);
}
?>