| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>Veo3 JSON Prompt Generator Pro — Smart Mode</title> |
| <link rel="preconnect" href="https://fonts.googleapis.com"> |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet"> |
| <style> |
| :root { |
| --primary-color-start: #4F46E5; |
| --primary-color-end: #8B5CF6; |
| --background-color: #f8f9fc; |
| --container-bg: #ffffff; |
| --text-color: #1f2937; |
| --label-color: #374151; |
| --border-color: #d1d5db; |
| --shadow-color: rgba(0, 0, 0, 0.08); |
| } |
| |
| * { box-sizing: border-box; } |
| |
| body { |
| font-family: 'Poppins', sans-serif; |
| background-color: var(--background-color); |
| color: var(--text-color); |
| margin: 0; |
| padding: 1rem; |
| display: flex; |
| justify-content: center; |
| align-items: flex-start; |
| min-height: 100vh; |
| } |
| |
| .container { |
| width: 100%; |
| max-width: 820px; |
| background-color: var(--container-bg); |
| padding: 2rem; |
| border-radius: 16px; |
| box-shadow: 0 10px 30px var(--shadow-color); |
| border: 1px solid #e5e7eb; |
| } |
| |
| @media (max-width: 600px) { .container { padding: 1.25rem; } } |
| |
| h1 { |
| font-size: 2rem; font-weight: 700; margin: 0 0 .75rem 0; text-align: center; |
| background: linear-gradient(90deg, var(--primary-color-start), var(--primary-color-end)); |
| -webkit-background-clip: text; -webkit-text-fill-color: transparent; |
| } |
| |
| .subtitle { text-align:center; font-size:.9rem; color:#6b7280; margin-bottom: .75rem; } |
| |
| label { font-weight: 600; display:block; margin-top: 1rem; margin-bottom: .4rem; color: var(--label-color); font-size:.95rem; } |
| |
| select, textarea, input[type="text"] { |
| width: 100%; padding: .8rem 1rem; border-radius: 10px; border: 1px solid var(--border-color); |
| font-size: 1rem; font-family: 'Poppins', sans-serif; background: #f9fafb; transition: all .2s ease-in-out; |
| } |
| |
| |
| select:focus, |
| textarea:focus, |
| input[type="text"]:focus { |
| outline: none; |
| border-color: var(--primary-color-start); |
| box-shadow: 0 0 0 3px rgba(79,70,229,.15); |
| background: #fff; |
| } |
| |
| |
| select { |
| -webkit-appearance: none; |
| -moz-appearance: none; |
| appearance: none; |
| padding-right: 2.25rem; |
| background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path d="M6 8l4 4 4-4" stroke="%234F46E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'); |
| background-repeat: no-repeat; |
| background-position: right .75rem center; |
| background-size: 14px; |
| } |
| |
| |
| select::-ms-expand { display: none; } |
| |
| |
| select:disabled { opacity: .6; cursor: not-allowed; } |
| |
| .row { display:grid; grid-template-columns: 1fr 1fr; gap: .75rem 1rem; } |
| .row > div { width:100%; } |
| |
| |
| .toolbar { display:flex; gap:1rem; align-items:center; justify-content:center; flex-wrap: wrap; margin:.35rem 0 1rem; } |
| .toolbar .group { display:flex; gap:.5rem; align-items:center; } |
| .toolbar select { width: auto; min-width: 12ch; } |
| |
| .actions { display:grid; grid-template-columns: 1fr 1fr; gap:.75rem; margin-top:1.25rem; } |
| |
| button { |
| background-image: linear-gradient(90deg, var(--primary-color-start), var(--primary-color-end)); color:#fff; border:none; padding:.9rem 1.2rem; font-size:1.05rem; font-weight:700; border-radius:10px; cursor:pointer; width:100%; |
| transition: transform .18s ease, box-shadow .18s ease; box-shadow: 0 4px 15px rgba(0,0,0,.10); |
| } |
| button:hover { transform: translateY(-2px); box-shadow: 0 7px 20px rgba(0,0,0,.15); } |
| button.secondary { background:#111827; } |
| |
| pre { background:#0f172a; color:#e5e7eb; padding:1rem 1.25rem; white-space:pre-wrap; word-break:break-word; border-radius:12px; margin-top:1rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size:.92rem; line-height:1.6; border:1px solid #1f2937; } |
| |
| .note { font-size:.8rem; color:#6b7280; margin-top:.25rem; } |
| .dimmed { opacity:.55; } |
| |
| .toast { position: fixed; right: 16px; bottom: 16px; background: #111827; color: #fff; padding: 10px 12px; border-radius: 10px; opacity: 0; transform: translateY(10px); box-shadow: 0 8px 20px rgba(0,0,0,0.2); transition: opacity .2s ease, transform .2s ease; font-size: .9rem; z-index:1000; } |
| .toast.show { opacity:1; transform: translateY(0); } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <h1>🎬 Veo3 JSON Prompt Generator <span style="font-size: 1rem; font-weight: 400;">(Pro)</span></h1> |
| <div class="subtitle">Slect Options • Smart Mode • Copy‑ready JSON Prompt</div> |
|
|
| <div class="toolbar"> |
| <div class="group"> |
| <label for="qualityPreset" style="margin:0">Quality</label> |
| <select id="qualityPreset" aria-label="Quality Preset"> |
| <option value="pro" selected>Pro (default)</option> |
| <option value="draft">Draft / Fast</option> |
| <option value="cinematic">Cinematic</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="domain">🎯 Select Domain</label> |
| <select id="domain"> |
| <option value="education">Education</option> |
| <option value="advertisement" selected>Advertisement</option> |
| <option value="product_demo">Product Demo</option> |
| <option value="creator_pov">Creator POV</option> |
| </select> |
| </div> |
| <div> |
| <label for="characterType">🎭 Character / Product</label> |
| <select id="characterType"> |
| <optgroup label="Characters"> |
| <option>Pakistani Male</option> |
| <option selected>Pakistani Female</option> |
| <option>Arab Male</option> |
| <option>Arab Female</option> |
| <option>South Asian Coach</option> |
| <option>Young Creator (Female)</option> |
| <option>Young Creator (Male)</option> |
| </optgroup> |
| <optgroup label="Products"> |
| <option>Smartphone</option> |
| <option>Perfume</option> |
| <option>Luxury Car</option> |
| <option>Skincare Product</option> |
| </optgroup> |
| <option value="custom">🛠️ Custom Character or Product</option> |
| </select> |
| <div id="customCharacterTypeWrapper" style="display:none; margin-top:.5rem;"> |
| <input type="text" id="customCharacterType" placeholder="Enter custom character or product" /> |
| </div> |
| </div> |
| </div> |
|
|
| <div> |
| <label for="taskFocus">📆 Scene Title / Task Focus</label> |
| <select id="taskFocus"> |
| <option>Lesson Planning</option> |
| <option>Quiz Generator</option> |
| <option>Feedback Automation</option> |
| <option selected>Product Reveal</option> |
| <option>How It Works</option> |
| <option>From Chaos to Clarity</option> |
| <option>Before vs. After</option> |
| <option>Transformation Moment</option> |
| <option>A Day in the Life</option> |
| <option>Problem → Solution</option> |
| <option>Behind the Scenes</option> |
| <option>AI to the Rescue</option> |
| <option>Time-Saver Workflow</option> |
| <option value="custom">🛠️ Custom</option> |
| </select> |
| <div id="customTaskWrapper" style="display:none; margin-top:.5rem;"> |
| <input type="text" id="customTask" placeholder="Enter your custom task focus" /> |
| </div> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="variant">🎞️ Video Type / Variant</label> |
| <select id="variant"> |
| <option value="cinematic" selected>🎬 Cinematic</option> |
| <option value="POV">📸 POV</option> |
| <option value="meme">😂 Meme</option> |
| <option value="teaser">🎯 Teaser</option> |
| <option value="tutorial">📚 Tutorial</option> |
| <option value="BTS/documentary">🎥 Behind the Scenes</option> |
| <option value="montage">🌀 Montage</option> |
| <option value="product-hero">💡 Product Hero</option> |
| <option value="ASMR">🔊 ASMR</option> |
| <option value="drone-flythrough">🚁 Drone Flythrough</option> |
| <option value="timelapse">⏳ Timelapse</option> |
| <option value="kinetic-typography">🔠 Kinetic Typography</option> |
| <option value="stop-motion">🎞️ Stop Motion</option> |
| <option value="comedy-sketch">🤣 Comedy Sketch</option> |
| <option value="custom">✍️ Custom Variant</option> |
| </select> |
| <div id="customVariantWrapper" style="display:none; margin-top:.5rem;"> |
| <input type="text" id="customVariant" placeholder="Enter custom video type" /> |
| </div> |
| </div> |
| <div> |
| <label for="aspectRatio">🖼️ Aspect Ratio</label> |
| <select id="aspectRatio"> |
| <option>16:9</option> |
| <option selected>9:16</option> |
| <option>1:1</option> |
| </select> |
| <div class="note">Smart Mode: platforms auto‑map from aspect ratio</div> |
| </div> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="platform">🌐 Platform</label> |
| <select id="platform"> |
| <option value="tiktok">TikTok</option> |
| <option value="facebook_reels">Facebook Reels</option> |
| <option value="instagram_reels">Instagram Reels</option> |
| <option value="shorts">YouTube Shorts</option> |
| <option value="stories">Stories</option> |
| <option value="facebook">Facebook Feed</option> |
| <option value="x">X (Twitter)</option> |
| <option value="linkedin">LinkedIn</option> |
| <option value="snap">Snap Spotlight</option> |
| <option value="youtube">YouTube (Long)</option> |
| </select> |
| </div> |
| <div> |
| <label for="description">🧠 Narrative Structure</label> |
| <select id="description"> |
| <option>Setting → Action → Reveal</option> |
| <option>Reveal-first → Context</option> |
| <option>Problem → Build → Payoff</option> |
| <option>Before/After Transform</option> |
| <option>Countdown → Pop → Logo-out</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div id="lookPresetBlock" style="margin-top:.5rem;"> |
| <label style="display:flex; align-items:center; gap:8px; font-weight:600;"> |
| <input type="checkbox" id="useLookPreset" checked /> Enable Character Look Preset |
| </label> |
| <div id="lookPresetFields" class="row" style="margin-top:0.5rem;"> |
| <div> |
| <label for="skinTone">🧑🏽 Skin Tone</label> |
| <select id="skinTone"> |
| <option>light wheatish</option> |
| <option selected>wheatish</option> |
| <option>medium tan</option> |
| <option>warm brown</option> |
| <option>deep brown</option> |
| </select> |
| </div> |
| <div id="headCoverWrap"> |
| <label for="headCover">🧕 Head Covering (if applicable)</label> |
| <select id="headCover"> |
| <option value="auto" selected>Auto</option> |
| <option value="none">None</option> |
| <option value="dupatta">Dupatta (draped)</option> |
| <option value="hijab_wrap">Hijab (wrap)</option> |
| <option value="shayla">Shayla</option> |
| <option value="niqab">Niqab (eyes visible)</option> |
| </select> |
| </div> |
| </div> |
| <div class="note">Presets add culturally accurate wardrobe & grooming to JSON.</div> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="visualStyle">🎨 Visual Style</label> |
| <select id="visualStyle"> |
| <option>Photorealistic</option> |
| <option>Glossy Commercial</option> |
| <option selected>Cinematic / Filmic Grain</option> |
| <option>HDR High-Contrast</option> |
| <option>Low-Key Noir</option> |
| <option>High-Key Clean</option> |
| <option>Cyberpunk / Neon</option> |
| <option>Retro VHS</option> |
| <option>Natural Documentary</option> |
| <option>Hyper-Real Macro</option> |
| <option>Tilt-Shift</option> |
| <option>Stylized (Toon/Anime/Cel-Shade)</option> |
| </select> |
| </div> |
| <div> |
| <label for="camera">🎥 Camera & Motion (optional)</label> |
| <select id="camera"> |
| <option value="auto" selected>🎯 Auto Based on Scene</option> |
| <option value="dolly">Dolly</option> |
| <option value="slider">Slider</option> |
| <option value="handheld">Handheld (Micro Judder)</option> |
| <option value="crane">Crane / Jib</option> |
| <option value="rack-focus">Rack Focus</option> |
| <option value="360 orbit">360 Orbit</option> |
| <option value="fpv">FPV / Drone</option> |
| <option value="whip-pan">Whip Pan</option> |
| <option value="smash-zoom">Smash Zoom</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="background">🌆 Background Environment</label> |
| <select id="background"> |
| <option value="auto" selected>🎯 Auto Based on Task</option> |
| <option value="studio">Studio Cyclorama</option> |
| <option value="warehouse">Industrial Warehouse</option> |
| <option value="garage">Neon Garage</option> |
| <option value="showroom">Marble Showroom</option> |
| <option value="night_city">City Night Street</option> |
| <option value="forest">Misty Forest</option> |
| <option value="lab">Clean Lab</option> |
| </select> |
| </div> |
| <div> |
| <label for="lightingMood">💡 Lighting & Mood</label> |
| <select id="lightingMood"> |
| <option>Golden Hour Beams</option> |
| <option>Hard Rim / Silhouette</option> |
| <option selected>Soft Wrap Key</option> |
| <option>Top Light High-Contrast</option> |
| <option>Backlight + Haze</option> |
| <option>Neon Mix (Cyan / Magenta)</option> |
| <option>Strobe on Beats</option> |
| <option>Moonlight Blue</option> |
| <option>Neutral Daylight</option> |
| <option>🛠️ Auto Select</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="audioTrack">🎵 Background Music</label> |
| <select id="audioTrack"> |
| <option>Hybrid Orchestral</option> |
| <option>Trap</option> |
| <option>Hip-Hop</option> |
| <option>Synthwave</option> |
| <option>Techno</option> |
| <option>Glitch-hop</option> |
| <option selected>Cinematic Pulses</option> |
| </select> |
| </div> |
| <div> |
| <label for="sfx">🔊 Sound Effects (SFX)</label> |
| <select id="sfx"> |
| <option>Braaam</option> |
| <option selected>Whoosh / Riser</option> |
| <option>Strap Snap</option> |
| <option>Plastic Tear</option> |
| <option>Metallic Clinks</option> |
| <option>Angle-Grinder Sparks</option> |
| <option>Tire Chirp</option> |
| <option>Heartbeat Thump</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div id="voiceoverBlock" style="margin-top:.5rem;"> |
| <label style="display:flex; align-items:center; gap:8px; font-weight:600;"> |
| <input type="checkbox" id="useVoiceover" checked /> Enable Voiceover |
| </label> |
| <div id="voFields" class="row" style="margin-top:0.5rem;"> |
| <div> |
| <label for="voLanguage">🎙 Language</label> |
| <select id="voLanguage"> |
| <option value="ur-PK-roman" selected>Urdu (Roman Urdu)</option> |
| <option value="ur-PK">Urdu (Nastaliq)</option> |
| <option value="en-US">English (US)</option> |
| <option value="en-GB">English (UK)</option> |
| <option value="ar-Gulf">Arabic (Gulf)</option> |
| <option value="ar-Levant">Arabic (Levant)</option> |
| </select> |
| </div> |
| <div> |
| <label for="voGender">👤 Voice</label> |
| <select id="voGender"> |
| <option value="female" selected>Female</option> |
| <option value="male">Male</option> |
| <option value="youth">Youth</option> |
| </select> |
| </div> |
| <div> |
| <label for="voTone">🎚 Tone</label> |
| <select id="voTone"> |
| <option value="cinematic" selected>Cinematic</option> |
| <option value="friendly">Friendly</option> |
| <option value="authoritative">Authoritative</option> |
| <option value="educational">Educational</option> |
| <option value="inspirational">Inspirational</option> |
| <option value="playful">Playful</option> |
| </select> |
| </div> |
| <div> |
| <label for="voPace">⏱ Pace</label> |
| <select id="voPace"> |
| <option value="slow">Slow</option> |
| <option value="medium" selected>Medium</option> |
| <option value="fast">Fast</option> |
| </select> |
| </div> |
| </div> |
| <label for="voScript" style="margin-top:.5rem;">📝 Voiceover Script (optional)</label> |
| <textarea id="voScript" rows="3" placeholder="Write your VO script here... or leave empty to generate later"></textarea> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="colorPalette">🎨 Color Palette</label> |
| <select id="colorPalette"> |
| <option>Graphite / Obsidian / Silver</option> |
| <option selected>Amber / Gold / Copper</option> |
| <option>Steel Blue / Cyan / Teal</option> |
| <option>Neon Accents (Magenta / Cyan / Lime)</option> |
| <option>Monochrome</option> |
| <option>Duotone</option> |
| <option>Triadic (e.g. graphite + amber + red)</option> |
| </select> |
| </div> |
| <div> |
| <label for="hook">🚀 Hook / Opening Action</label> |
| <select id="hook"> |
| <option>Bolt Snap (Slow-mo)</option> |
| <option>Sparks Hit Lens</option> |
| <option>Seal Rip Recoil</option> |
| <option>Lights Power-on Cascade</option> |
| <option selected>Tarp Whip-Off</option> |
| <option>Confetti Pop</option> |
| <option>Macro Finger Press</option> |
| <option>Countdown Flash</option> |
| <option>Smash-Zoom Gag</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="row"> |
| <div> |
| <label for="finale">🎬 Finale / Closing Action</label> |
| <select id="finale"> |
| <option selected>Hero Push-in → Blackout</option> |
| <option>Butterfly Doors + 360 Orbit</option> |
| <option>Taillight Bloom → Logo-out</option> |
| <option>Freeze Frame + End Card</option> |
| <option>Speed-Ramp Drive-by</option> |
| <option>Reverse Reveal Cloth Fall</option> |
| </select> |
| </div> |
| <div> |
| <label for="keywords">🔑 Keywords (comma-separated)</label> |
| <textarea id="keywords" rows="2" placeholder="e.g., macro details, handheld realism, clean logo"></textarea> |
| </div> |
| </div> |
|
|
| <div> |
| <label for="negativePrompt">🚫 Negative Prompt (Exclude Things)</label> |
| <textarea id="negativePrompt" rows="3" placeholder="e.g., no logos, no text overlays, no watermark, no extra limbs"></textarea> |
| <div class="note">Smart Mode auto-adds clean negatives if left empty.</div> |
| </div> |
|
|
| <div class="actions"> |
| <button id="generateBtn" onclick="generatePrompt()">🚀 Generate Prompt</button> |
| <button class="secondary" id="copyBtn" onclick="copyToClipboard()">📋 Copy Prompt</button> |
| </div> |
|
|
| <pre id="output" aria-live="polite">{ /* Your JSON prompt will appear here */ }</pre> |
| </div> |
|
|
| <div id="toast" class="toast" role="status" aria-live="polite">Copied!</div> |
|
|
| <script> |
| |
| const $ = (id) => document.getElementById(id); |
| |
| function showToast(msg="Copied!"){ |
| const t = $("toast"); if(!t) return; t.textContent = msg; t.classList.add("show"); setTimeout(()=>t.classList.remove("show"), 1200); |
| } |
| |
| let _lastJSON = ""; |
| let _typeTimer = null; |
| |
| function typewriter(el, text, speed = 8){ |
| if (!el) return; |
| if (_typeTimer) { clearInterval(_typeTimer); _typeTimer = null; } |
| el.textContent = ""; |
| let i = 0; |
| _typeTimer = setInterval(()=>{ |
| el.textContent += text[i++] || ""; |
| if (i >= text.length) { clearInterval(_typeTimer); _typeTimer = null; } |
| }, speed); |
| } |
| |
| function copyToClipboard(){ |
| const text = _lastJSON || $("output").textContent || ""; |
| navigator.clipboard.writeText(text).then(()=>showToast("Copied!")); |
| } |
| |
| |
| if (typeof window.generatePrompt !== 'function') { |
| window.generatePrompt = function(){ }; |
| } |
| </script> |
|
|
| <script> |
| |
| const AR_TO_PLATFORMS = { |
| "9:16": ["tiktok","instagram_reels","facebook_reels","shorts","snap","stories"], |
| "16:9": ["youtube","facebook","x","linkedin"], |
| "1:1": ["instagram_feed","facebook"] |
| }; |
| |
| const AUTO_PRESETS = { |
| cinematic: { |
| camera: ["dolly","rack-focus","360 orbit"], |
| lighting: "Backlight + Haze", |
| bg: "showroom", |
| music: "Cinematic Pulses", |
| sfx: "Whoosh / Riser" |
| }, |
| "product-hero": { |
| camera: ["slider","macro"], |
| lighting: "Top Light High-Contrast", |
| bg: "studio", |
| music: "Hybrid Orchestral", |
| sfx: "Metallic Clinks" |
| }, |
| tutorial: { |
| camera: ["handheld","rack-focus"], |
| lighting: "Soft Wrap Key", |
| bg: "lab", |
| music: "Cinematic Pulses", |
| sfx: "Metallic Clinks" |
| }, |
| "BTS/documentary": { |
| camera: ["handheld"], |
| lighting: "Neutral Daylight", |
| bg: "warehouse", |
| music: "Cinematic Pulses", |
| sfx: "Whoosh / Riser" |
| }, |
| meme: { |
| camera: ["smash-zoom","whip-pan"], |
| lighting: "High-Key Clean", |
| bg: "auto", |
| music: "Trap", |
| sfx: "Whoosh / Riser" |
| } |
| }; |
| |
| const DOMAIN_HINTS = { |
| education: { lighting: "Neutral Daylight", bg: "lab" }, |
| advertisement:{ lighting: "Top Light High-Contrast", bg: "showroom" }, |
| product_demo:{ lighting: "High-Key Clean", bg: "studio" }, |
| creator_pov: { lighting: "Soft Wrap Key", bg: "night_city" } |
| }; |
| |
| const QUALITY_PRESET = { |
| draft: { fps: 24, grain: "off", denoise: "on", duration: "8–10s" }, |
| pro: { fps: 30, grain: "light",denoise: "auto",duration: "10–12s" }, |
| cinematic: { fps: 30, grain: "gentle filmic", denoise: "auto", duration: "12–14s" } |
| }; |
| |
| const el = (id)=>document.getElementById(id); |
| |
| const aspectEl = el("aspectRatio"); |
| const platEl = el("platform"); |
| const varEl = el("variant"); |
| const domEl = el("domain"); |
| const qualEl = el("qualityPreset") || { value:"pro" }; |
| |
| function syncPlatformsFromAspect() { |
| if (!aspectEl || !platEl) return; |
| const ar = aspectEl.value; |
| const rec = AR_TO_PLATFORMS[ar] || []; |
| platEl.dataset.recommended = JSON.stringify(rec); |
| |
| if (!platEl.value || !rec.includes(platEl.value)) { |
| platEl.value = rec[0] || platEl.value || "tiktok"; |
| } |
| } |
| |
| function setIfAuto(selectEl, val){ |
| if (!selectEl) return; |
| const cur = (selectEl.value||"").toLowerCase(); |
| if (cur === "auto" || cur === "🎯 auto based on scene".toLowerCase() || cur === "🛠️ auto select".toLowerCase() || cur === "") { |
| selectEl.value = val; |
| } |
| } |
| |
| function autoFromVariantAndDomain() { |
| const v = (varEl?.value || "cinematic").toLowerCase(); |
| const d = (domEl?.value || "advertisement").toLowerCase(); |
| const vAuto = AUTO_PRESETS[v] || {}; |
| const dAuto = DOMAIN_HINTS[d] || {}; |
| |
| const cameraEl = el("camera"); |
| const lightingEl = el("lightingMood"); |
| const bgEl = el("background"); |
| const musicEl = el("audioTrack"); |
| const sfxEl = el("sfx"); |
| |
| const cameraVal = Array.isArray(vAuto.camera) ? vAuto.camera[0] : vAuto.camera; |
| setIfAuto(cameraEl, cameraVal || "auto"); |
| setIfAuto(lightingEl, vAuto.lighting || dAuto.lighting || "🛠️ Auto Select"); |
| setIfAuto(bgEl, vAuto.bg || dAuto.bg || "auto"); |
| setIfAuto(musicEl, vAuto.music || "Cinematic Pulses"); |
| setIfAuto(sfxEl, vAuto.sfx || "Whoosh / Riser"); |
| } |
| |
| function cleanObj(obj){ |
| const isArr = Array.isArray(obj); |
| const acc = isArr ? [] : {}; |
| Object.entries(obj).forEach(([k,v])=>{ |
| if (v === undefined || v === null) return; |
| if (typeof v === 'string' && v.trim() === '') return; |
| if (typeof v === 'string' && /^(auto|🛠️ Auto Select|🎯 Auto Based on Scene)$/i.test(v.trim())) return; |
| if (Array.isArray(v) && v.length===0) return; |
| acc[k] = (v && typeof v === 'object' && !Array.isArray(v)) ? cleanObj(v) : v; |
| }); |
| return acc; |
| } |
| |
| const _oldGenerate = window.generatePrompt; |
| window.generatePrompt = function(){ |
| autoFromVariantAndDomain(); |
| syncPlatformsFromAspect(); |
| |
| const qp = QUALITY_PRESET[qualEl.value] || QUALITY_PRESET.pro; |
| |
| const variant = (el("variant")?.value === "custom" ? el("customVariant")?.value : el("variant")?.value) || "cinematic"; |
| const ar = el("aspectRatio")?.value || "16:9"; |
| const domain = el("domain")?.value || "advertisement"; |
| const scene = (el("taskFocus")?.value === "custom" ? el("customTask")?.value : el("taskFocus")?.value) || "Product Reveal"; |
| |
| const lookOn = el("useLookPreset")?.checked; |
| const voOn = el("useVoiceover")?.checked; |
| |
| let subjectLook = null; |
| if (lookOn) { |
| const type = (el("characterType")?.value === "custom" ? el("customCharacterType")?.value : el("characterType")?.value); |
| const tone = el("skinTone")?.value; |
| const hc = el("headCover")?.value; |
| subjectLook = { type, skin_tone: tone, head_cover: hc }; |
| } |
| |
| let voiceover = null; |
| if (voOn) { |
| voiceover = { |
| language: el("voLanguage")?.value, |
| voice: el("voGender")?.value, |
| tone: el("voTone")?.value, |
| pace: el("voPace")?.value, |
| script: (el("voScript")?.value || "").trim() |
| }; |
| } |
| |
| const camera = el("camera")?.value; |
| const lighting = el("lightingMood")?.value; |
| const bg = el("background")?.value; |
| const music = el("audioTrack")?.value; |
| const sfx = el("sfx")?.value; |
| |
| let platforms = []; |
| if (platEl?.dataset?.recommended){ |
| const rec = JSON.parse(platEl.dataset.recommended); |
| platforms = platEl.value ? [platEl.value] : rec; |
| } |
| |
| const negatives = (el("negativePrompt")?.value || "no logos, no text overlays, no watermark").trim(); |
| |
| const meta = { |
| aspect_ratio: ar, |
| duration: qp.duration, |
| fps: qp.fps, |
| grain: qp.grain, |
| denoise: qp.denoise, |
| platforms |
| }; |
| |
| const out = cleanObj({ |
| variant, |
| domain, |
| scene_title: scene, |
| meta, |
| subject_look: subjectLook, |
| visual_style: el("visualStyle")?.value || "Cinematic / Filmic Grain", |
| camera, |
| background: bg, |
| lighting, |
| music, |
| sfx, |
| color_palette: el("colorPalette")?.value, |
| hook: el("hook")?.value, |
| finale: el("finale")?.value, |
| voiceover, |
| keywords: (el("keywords")?.value||"").trim(), |
| negative_prompt: negatives |
| }); |
| |
| const pretty = JSON.stringify(out, null, 2); |
| _lastJSON = pretty; |
| typewriter(document.getElementById("output"), pretty, 6); |
| |
| if (typeof _oldGenerate === "function") { try { _oldGenerate(); } catch(e){} } |
| }; |
| |
| |
| aspectEl?.addEventListener("change", syncPlatformsFromAspect); |
| domEl?.addEventListener("change", ()=>{ autoFromVariantAndDomain(); }); |
| |
| |
| const taskFocus = el('taskFocus'); |
| const customTaskWrap = el('customTaskWrapper'); |
| taskFocus?.addEventListener('change', ()=>{ |
| customTaskWrap.style.display = taskFocus.value === 'custom' ? 'block' : 'none'; |
| }); |
| |
| |
| const characterType = el('characterType'); |
| const customCharacterWrap = el('customCharacterTypeWrapper'); |
| characterType?.addEventListener('change', () => { |
| customCharacterWrap.style.display = characterType.value === 'custom' ? 'block' : 'none'; |
| }); |
| |
| |
| const customVariantWrap = el('customVariantWrapper'); |
| varEl?.addEventListener("change", ()=>{ |
| autoFromVariantAndDomain(); |
| customVariantWrap.style.display = varEl.value === 'custom' ? 'block' : 'none'; |
| }); |
| |
| document.addEventListener("DOMContentLoaded", ()=>{ |
| autoFromVariantAndDomain(); |
| syncPlatformsFromAspect(); |
| generatePrompt(); |
| }); |
| </script> |
| </body> |
| </html> |