Removes the maxOutputTokens: 1024 limit that was causing enhanced prompts to be truncated. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
262 lines
14 KiB
PHP
262 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* Prompt Enhancement API
|
|
* Uses Gemini AI to enhance cinematography prompts
|
|
*/
|
|
|
|
require_once 'config.php';
|
|
require_once 'webhook_logger.php';
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
// Initialize auth status with default
|
|
$authStatus = [
|
|
'authenticated' => true,
|
|
'user' => [
|
|
'name' => 'User',
|
|
'preferred_username' => 'anonymous@nano-banana-pro.com'
|
|
]
|
|
];
|
|
|
|
// Check authentication (with graceful fallback)
|
|
try {
|
|
if (file_exists(__DIR__ . '/AuthMiddleware.php')) {
|
|
require_once 'AuthMiddleware.php';
|
|
$auth = new AuthMiddleware();
|
|
$authStatus = $auth->isAuthenticated();
|
|
|
|
if (!$authStatus['authenticated']) {
|
|
http_response_code(401);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => 'Authentication required'
|
|
]);
|
|
exit;
|
|
}
|
|
}
|
|
} catch (Exception $e) {
|
|
// Log error but continue without auth (for testing)
|
|
error_log("Auth check failed in enhance_prompt.php: " . $e->getMessage());
|
|
}
|
|
|
|
// Get POST data
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
if (!$input) {
|
|
echo json_encode(['success' => false, 'error' => 'Invalid input']);
|
|
exit;
|
|
}
|
|
|
|
$sceneDescription = $input['sceneDescription'] ?? '';
|
|
$camera = $input['camera'] ?? '';
|
|
$lens = $input['lens'] ?? '';
|
|
$application = $input['application'] ?? '';
|
|
$aspectRatio = $input['aspectRatio'] ?? '16:9';
|
|
$creativeFreedom = floatval($input['creativeFreedom'] ?? 0.3);
|
|
|
|
// Camera physics data
|
|
$cameraPhysics = [
|
|
'Arri Alexa 35' => 'ArriRaw sensor data, pleasing noise floor, high dynamic range, natural skin micro-texture',
|
|
'Sony Venice 2' => 'Clean digital sensor, zero noise, high-frequency detail, modern sharpness',
|
|
'Red V-Raptor' => '8K RedCode RAW, clinical detail, hyper-sharp edges, high shutter angle crispness',
|
|
'Arriflex 416' => 'Kodak Vision3 500T film stock, heavy film grain, halation, soft organic edges, chemical color process',
|
|
'Arricam LT' => 'Kodak Vision3 50D film stock, fine grain, organic resolution, rich photochemical colors',
|
|
'Fujifilm GFX 100' => '100 Megapixel medium format sensor, pore-level skin detail, textile fiber detail, print quality resolution',
|
|
'Phantom Flex4K' => 'High-speed sensor readout, frozen temporal resolution, saturated color depth, zero motion blur artifacts',
|
|
'Blackmagic URSA Cine 12K' => '12K RGB pattern, infinite reframing capability, zero aliasing, analytics-grade edge definition'
|
|
];
|
|
|
|
// Lens physics data
|
|
$lensPhysics = [
|
|
'Panavision C-Series' => 'anamorphic optics, characteristic oval bokeh, horizontal blue lens flares, slight barrel distortion',
|
|
'Cooke S7/i' => 'Cooke speed panchrio look, warm color rendering, gentle focus falloff, flattering face compression',
|
|
'Canon K-35' => 'vintage aspherical elements, glowing highlights, low contrast, rainbow flaring, soft sharpness',
|
|
'Arri Signature' => 'telecentric optical design, zero breathing, ultra-flat field, modern rendering, pure black levels',
|
|
'Zeiss Super Speed' => 'vintage high-speed glass, triangular bokeh at wide apertures, chromatic aberration, gritty texture',
|
|
'Fujinon GF' => 'modern medium format optics, clinical edge-to-edge sharpness, zero distortion, high micro-contrast',
|
|
'Laowa Probe' => 'macro bug-eye perspective, extreme depth of field, tubular lens construction, surreal wide-angle macro',
|
|
'Helios 44-2' => 'Vintage Soviet glass, characteristic swirly bokeh at edges, low contrast flaring, soft center focus, dreamlike aberrations',
|
|
'Canon TS-E' => 'Tilted focal plane, miniature faking effect, selective focus slice, corrected perspective lines, architectural rigidity',
|
|
'Angénieux Optimo' => 'Cinema zoom optics, warm organic contrast, breathing-free focus pulls, uniform field illumination'
|
|
];
|
|
|
|
// Application lighting presets
|
|
$applicationLighting = [
|
|
'Portrait Studio' => 'Rembrandt lighting, softbox diffusion, 3-point setup',
|
|
'Corporate Headshot' => 'Clean white background, high-key lighting, professional balanced fill, sharp focus on eyes, moderate depth of field',
|
|
'Product (Crisp)' => 'Infinity curve, bright diffuse lighting, shadowless, high key',
|
|
'Food Photography' => 'Natural window light simulation, back-lighting for steam/texture, warm reflector fill, medium depth of field, focus on texture',
|
|
'Macro: Luxury Jewelry' => 'Sparkling point-source lighting, black velvet background, high contrast reflection control, focus stacking simulation for complete sharpness',
|
|
'Macro: Nature Details' => 'Diffused natural sunlight, shallow depth of field, vibrant greens, morning dew, microscopic texture',
|
|
'Tech Commercial (Macro)' => 'Slow moving light sweep (motion control), brushed metal reflections, dramatic rim lighting in a black void, sub-surface scattering on materials',
|
|
'Golden Hour (Outdoor)' => 'Sun low on horizon, warm orange glow, long dramatic shadows, volumetric backlight, magic hour atmosphere, cinematic depth',
|
|
'Blue Hour (City)' => 'Twilight, deep blue ambient sky light contrasting with warm practical street lamps, moody, atmospheric, balanced exposure',
|
|
'Wildlife / Safari' => 'Telephoto compression, frozen motion, golden hour backlight, natural habitat, separation from background',
|
|
'Sports Action' => 'High shutter speed, frozen particles/sweat, stadium floodlights, dynamic composition, sharp subject focus',
|
|
'Neon Cyberpunk' => 'Harsh neon signage, mixed color temp, wet reflections',
|
|
'Nostalgic Memory' => 'Hazy atmosphere, overexposed highlights, light leaks, warm color grade, sentimental mood, soft focus throughout',
|
|
'Cinematic Horror' => 'Underexposed, single harsh source (flashlight), heavy shadows',
|
|
'Cassette Futurism (Retro Sci-Fi)' => 'Flickering CRT monitor glow, harsh overhead fluorescent strips, brutalist shadows, beige and grey color palette, industrial haze',
|
|
'Surreal Infrared' => 'Full spectrum daylight, false color infrared shift (foliage turns pink/white), deep blue skies, high contrast, dreamlike atmosphere',
|
|
'Spaghetti Western' => 'Harsh high-noon sun, heat haze distortion, sweaty skin texture, extreme close-up on eyes, deep depth of field',
|
|
'Symmetrical Whimsy' => 'Shadowless high-key lighting, flat diorama aesthetic, vibrant pastel color palette, 90-degree planimetric composition',
|
|
'IMAX Scale Epic' => 'Naturalistic practical lighting, cool color temperature, high contrast, immense sense of scale, deep depth of field',
|
|
'Clinical Thriller' => 'Low-key chiaroscuro, controlled shadows, sickly green/yellow color grade, precise stabilized motion',
|
|
'Brutalist Atmosphere' => 'Single source silhouette, atmospheric haze, monochromatic orange/sepia tones, stark geometry, visual silence',
|
|
'Technicolor Dream' => 'Artificial studio lighting, high saturation, vibrant pinks and cyans, glossy plastic textures, high-key brightness',
|
|
'Obsessive Symmetry' => 'One-point perspective, deep focus, wide angle distortion, cold practical lighting, clinical perfection',
|
|
'Hong Kong Nostalgia' => 'Step-printing effect, motion blur, neon-soaked humidity, intimate handheld, rain-slicked textures',
|
|
'Industrial Haze' => 'Volumetric lighting, visible shafts of light (god rays), atmospheric smoke, high-density industrial detail',
|
|
'Gothic Fantasy' => 'German Expressionist lighting, high contrast long shadows, twisted geometry, desaturated palette',
|
|
'LED Volume (Virtual Production)' => 'Interactive environmental lighting, soft ambient wrap from LED panels, perfect reflection matching, zero green spill',
|
|
'Automotive: Showroom' => 'Massive softbox ceiling, continuous highlight lines along bodywork, negative fill to shape curves, pure white infinity cove',
|
|
'Automotive: Process Trailer' => 'Dynamic passing street lights, rhythmic shadow movement, wet road reflections, motion blur on background only',
|
|
'Product (Liquid/Splash)' => 'High-speed strobe lighting, frozen droplets, backlit fluid translucency, crystal clear refraction',
|
|
'VFX / Green Screen' => 'Raw chromakey plate, perfectly flat shadowless green background, distinct rim light for separation, zero color spill, high-fidelity capture',
|
|
'Knolling / Flat Lay' => 'Overhead soft diffuse light, shadowless cavity, high-key evenness, precise grid alignment',
|
|
'NYC Street Editorial' => 'Natural city canyon light, bounce board fill for face, sharp modern contrast, motion blur in background, high-resolution gloss',
|
|
'90s Grunge Editorial' => 'Hard direct flash, dirty green/yellow color cast, vignetting, unretouched skin texture, claustrophobic framing',
|
|
'Fashion Editorial' => 'Avant-garde lighting, colored gels, stark shadows, high fashion pose, studio backdrop, stylized depth',
|
|
'Underground Rave / Flash' => 'Direct on-camera flash with slow shutter drag (rear-curtain sync), light trails, laser rim lighting, sweaty atmosphere, darkness crushing the background',
|
|
'Conflict Photography' => 'Harsh midday sun, atmospheric dust and smoke, high contrast, documentary style reality, blown highlights, raw and unpolished',
|
|
'Street Photography' => 'Candid moment, natural available light, messy urban background, hyperfocal distance, deep depth of field, everything in focus',
|
|
'Docu / Realism' => 'Natural window key light, negative fill, messy authentic background',
|
|
'Architectural Digest Interior' => 'North-facing window soft light, large diffusion frames, negative fill for contrast, texture-raking angle, perfectly balanced exposure',
|
|
'Architecture' => 'Balanced mixed lighting, straight lines, airy atmosphere',
|
|
'Custom' => 'User-defined lighting setup'
|
|
];
|
|
|
|
// Aspect ratio prose
|
|
$aspectRatioProse = [
|
|
'16:9' => 'A cinematic 16:9 composition featuring',
|
|
'2.39:1' => 'A widescreen anamorphic-ratio composition featuring',
|
|
'4:3' => 'A classic 4:3 format composition featuring',
|
|
'1:1' => 'A square format composition featuring',
|
|
'9:16' => 'A vertical full-screen composition featuring'
|
|
];
|
|
|
|
if (empty($sceneDescription)) {
|
|
echo json_encode(['success' => false, 'error' => 'Scene description is required']);
|
|
exit;
|
|
}
|
|
|
|
// Build the enhancement prompt for Gemini
|
|
$cameraPhysicsText = $cameraPhysics[$camera] ?? '';
|
|
$lensPhysicsText = $lensPhysics[$lens] ?? '';
|
|
$lighting = $applicationLighting[$application] ?? '';
|
|
$aspectText = $aspectRatioProse[$aspectRatio] ?? 'A composition featuring';
|
|
|
|
$enhancementPrompt = "You are an expert Cinematographer and Optical Physicist.
|
|
Your goal is to Create a \"Thick Description\" prompt that emphasizes TEXTURE, ATMOSPHERE, and LIGHT.
|
|
|
|
INPUT VARIABLES:
|
|
- Scene: {$sceneDescription}
|
|
- Application: {$application}
|
|
- Camera: {$camera}
|
|
- Lens: {$lens}
|
|
- Aspect Ratio Prose: {$aspectText}
|
|
- Creative Freedom: {$creativeFreedom}
|
|
- Camera Physics: {$cameraPhysicsText}
|
|
- Lens Physics: {$lensPhysicsText}
|
|
- Lighting: {$lighting}
|
|
|
|
EXECUTION STEPS:
|
|
|
|
1. **SMART FILL CHECK:**
|
|
- IF input is short (less than 10 words) AND Creative Freedom is High (> 0.5):
|
|
INVENT details based on Application.
|
|
|
|
2. **REALISM vs. STYLE CHECK:**
|
|
- Application is {$application}
|
|
|
|
3. **SENSORY ENHANCEMENT (THE \"DEEP TEXTURE\" PASS):**
|
|
- **Skin:** If humans are present, describe skin texture (e.g., \"visible pores,\" \"slight sweat sheen,\" \"natural imperfections\").
|
|
- **Air:** Describe the air quality (e.g., \"humid haze,\" \"crisp winter air,\" \"dust motes in light beams\").
|
|
- **Light:** Describe the *quality* of light (e.g., \"diffused window light,\" \"specular highlights\").
|
|
- **Camera Sensor Physics:** Apply these characteristics: \"{$cameraPhysicsText}\"
|
|
|
|
4. **OPTICAL CHARACTERISTICS:**
|
|
- **Lens Physics:** Apply these optical traits: \"{$lensPhysicsText}\"
|
|
|
|
5. **ASSEMBLY:**
|
|
- Start with {$aspectText}
|
|
- Expand subject with Smart Fill
|
|
- Apply {$application} lighting defaults
|
|
- Inject Camera Physics (Sensor/Film Stock characteristics)
|
|
- Finish with Lens Physics (Optical characteristics)
|
|
|
|
OUTPUT FORMAT:
|
|
[Aspect Ratio Prose] + [Visual Subject] + [Sensory Atmosphere & Light] + [Camera Physics] + [Lens Physics].
|
|
|
|
STRICT OUTPUT FORMAT: Return ONLY the final visual description text. Do not use Markdown formatting. Do not include conversational filler like 'Here is your prompt' or 'Sure'.";
|
|
|
|
try {
|
|
// Call Gemini API
|
|
$apiUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent?key=' . GEMINI_API_KEY;
|
|
|
|
$requestData = [
|
|
'contents' => [
|
|
[
|
|
'parts' => [
|
|
['text' => $enhancementPrompt]
|
|
]
|
|
]
|
|
],
|
|
'generationConfig' => [
|
|
'temperature' => 0.7,
|
|
'topK' => 40,
|
|
'topP' => 0.95,
|
|
]
|
|
];
|
|
|
|
$ch = curl_init($apiUrl);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData));
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode !== 200) {
|
|
throw new Exception("Gemini API error: HTTP $httpCode - $response");
|
|
}
|
|
|
|
$result = json_decode($response, true);
|
|
|
|
if (!isset($result['candidates'][0]['content']['parts'][0]['text'])) {
|
|
throw new Exception('Invalid response from Gemini API');
|
|
}
|
|
|
|
$enhancedPrompt = trim($result['candidates'][0]['content']['parts'][0]['text']);
|
|
|
|
// Log to webhook
|
|
try {
|
|
$userEmail = $authStatus['user']['preferred_username'] ?? $authStatus['user']['email'] ?? 'anonymous@nano-banana-pro.com';
|
|
$webhookSettings = [
|
|
'sceneDescription' => $sceneDescription,
|
|
'camera' => $camera,
|
|
'lens' => $lens,
|
|
'application' => $application,
|
|
'aspectRatio' => $aspectRatio,
|
|
'creativeFreedom' => $creativeFreedom
|
|
];
|
|
|
|
logPromptEnhancement($sceneDescription, $enhancedPrompt, $webhookSettings, $userEmail);
|
|
} catch (Exception $e) {
|
|
// Don't fail if webhook fails
|
|
error_log("Webhook logging failed in enhance_prompt: " . $e->getMessage());
|
|
}
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'enhancedPrompt' => $enhancedPrompt
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
}
|