|
|
<!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> |