nano-pro/enhance_prompt.php
michael 8289e264eb Remove output token limit from prompt enhancement API
Removes the maxOutputTokens: 1024 limit that was causing enhanced
prompts to be truncated.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:24:20 -06:00

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()
]);
}