Generador de Showreel de Video en un Solo Archivo HTML
De Wikiprompt, la enciclopedia libre de prompts
Generador de Showreel de Video en un Solo Archivo HTML Un prompt integral para construir un generador de showreel de vídeo en un solo archivo HTML, que cubra guion gráfico, guion, secuencia visual, dirección de audio y funciones de lista de verificación de producción con persistencia de datos.
Contenido del PromptGuardar
🌐
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Showreel Studio · generator</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
:root {
--primary: #4f46e5;
--bg: #f8fafc;
--surface: #ffffff;
--text: #0f172a;
--muted: #64748b;
--border: #e2e8f0;
--shadow: 0 8px 20px rgba(0,0,0,0.04);
--radius: 20px;
--accent-soft: #eef2ff;
}
body.dark {
--bg: #0b1120;
--surface: #1e293b;
--text: #f1f5f9;
--muted: #94a3b8;
--border: #334155;
--shadow: 0 8px 20px rgba(0,0,0,0.5);
--accent-soft: #1e1b4b;
}
body {
background: var(--bg);
color: var(--text);
transition: background 0.2s, color 0.2s;
padding: 24px;
line-height: 1.5;
}
.app {
max-width: 1440px;
margin: 0 auto;
}
.topbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 28px;
flex-wrap: wrap;
gap: 12px;
}
.logo {
font-weight: 700;
font-size: 1.6rem;
letter-spacing: -0.02em;
display: flex;
align-items: center;
gap: 8px;
}
.logo span {
background: var(--primary, #4f46e5);
width: 12px;
height: 12px;
border-radius: 4px;
display: inline-block;
}
.controls {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
button, .btn {
background: var(--surface);
border: 1px solid var(--border);
color: var(--text);
padding: 8px 16px;
border-radius: 40px;
font-weight: 500;
font-size: 0.9rem;
cursor: pointer;
transition: 0.15s;
box-shadow: var(--shadow);
display: inline-flex;
align-items: center;
gap: 6px;
}
button:hover, .btn:hover {
background: var(--accent-soft);
border-color: var(--primary, #4f46e5);
}
button.primary {
background: var(--primary, #4f46e5);
border: 1px solid var(--primary, #4f46e5);
color: white;
}
button.primary:hover {
filter: brightness(1.1);
background: var(--primary, #4f46e5);
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 24px;
margin-top: 20px;
}
.card {
background: var(--surface);
border-radius: var(--radius);
padding: 20px;
box-shadow: var(--shadow);
border: 1px solid var(--border);
transition: 0.1s;
}
.card h3 {
font-size: 1.2rem;
font-weight: 600;
margin-bottom: 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.card h3 .badge {
font-size: 0.7rem;
background: var(--accent-soft);
padding: 4px 10px;
border-radius: 30px;
color: var(--muted);
font-weight: 500;
}
.field {
margin-bottom: 14px;
}
label {
font-size: 0.8rem;
font-weight: 500;
color: var(--muted);
display: block;
margin-bottom: 4px;
}
input, select, textarea {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 14px;
background: var(--bg);
color: var(--text);
font-size: 0.9rem;
}
textarea {
min-height: 70px;
resize: vertical;
}
.row {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.row > * {
flex: 1;
}
.scene-item {
background: var(--bg);
border-radius: 16px;
padding: 12px;
margin-bottom: 12px;
border-left: 4px solid var(--primary, #4f46e5);
}
.scene-item .scene-head {
display: flex;
justify-content: space-between;
font-weight: 600;
margin-bottom: 6px;
}
.scene-item .shot-type {
font-size: 0.75rem;
background: var(--accent-soft);
padding: 2px 8px;
border-radius: 30px;
}
.muted {
color: var(--muted);
font-size: 0.85rem;
}
.checklist-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 0;
border-bottom: 1px dashed var(--border);
}
.checklist-item input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: var(--primary, #4f46e5);
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.export-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-top: 12px;
}
.color-dot {
display: inline-block;
width: 18px;
height: 18px;
border-radius: 6px;
margin-right: 4px;
border: 1px solid #ffffff50;
}
.tag {
background: var(--accent-soft);
padding: 2px 10px;
border-radius: 30px;
font-size: 0.75rem;
}
.audio-row {
display: flex;
justify-content: space-between;
align-items: center;
background: var(--bg);
padding: 8px 12px;
border-radius: 12px;
margin-bottom: 8px;
}
.placeholder-img {
background: linear-gradient(145deg, var(--accent-soft), var(--border));
height: 60px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: var(--muted);
font-size: 0.8rem;
margin: 8px 0;
}
.export-block {
background: var(--bg);
padding: 12px;
border-radius: 16px;
font-family: monospace;
font-size: 0.8rem;
white-space: pre-wrap;
max-height: 200px;
overflow-y: auto;
}
.primary-color-input {
width: 40px;
height: 40px;
padding: 0;
border: 2px solid var(--border);
border-radius: 12px;
background: transparent;
cursor: pointer;
}
@media (max-width: 700px) {
body { padding: 12px; }
.grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="app" id="app">
<div class="topbar">
<div class="logo"><span></span> Showreel Studio</div>
<div class="controls">
<button id="darkModeToggle" class="btn">🌙 dark</button>
<input type="color" id="primaryColorPicker" value="#4f46e5" class="primary-color-input" title="primary color">
<button id="exportJsonBtn" class="btn">⬇️ export JSON</button>
<button id="importJsonBtn" class="btn">📂 import</button>
<input type="file" id="importFile" accept=".json" style="display:none">
<button id="exportReportBtn" class="btn primary">📄 export report</button>
</div>
</div>
<!-- brief + templates -->
<div class="grid">
<div class="card">
<h3>📋 project brief <small>template</small></h3>
<div class="row" style="margin-bottom:12px">
<select id="templateSelect">
<option value="product">🚀 product launch</option>
<option value="portfolio">🎨 portfolio</option>
<option value="promo">📣 promo</option>
<option value="edu">🎓 educational</option>
<option value="social">📱 social ad</option>
</select>
<button id="applyTemplateBtn" class="btn">apply</button>
</div>
<div class="field"><label>project name</label><input id="projectName" placeholder="My showreel"></div>
<div class="row">
<div class="field"><label>length</label><select id="videoLength"><option>15s</option><option>30s</option><option>60s+</option></select></div>
<div class="field"><label>tone</label><select id="toneSelect"><option>Professional</option><option>Casual</option><option>Dramatic</option><option>Educational</option></select></div>
</div>
<div class="field"><label>target audience</label><input id="audience" placeholder="e.g. startup founders"></div>
<div class="field"><label>key message</label><textarea id="keyMessage">innovative, fast, reliable</textarea></div>
<div class="field"><label>style references</label><input id="styleRef" placeholder="e.g. minimal, neon, documentary"></div>
<button id="saveBriefBtn" class="btn primary" style="width:100%">💾 save brief</button>
</div>
<!-- storyboard generator -->
<div class="card">
<h3>🎬 storyboard <small>auto</small></h3>
<div id="storyboardContainer"></div>
<div class="row" style="margin-top:8px">
<button id="generateStoryboardBtn" class="btn">✨ generate scenes</button>
<button id="exportStoryboardBtn" class="btn">🖼️ export</button>
</div>
<div class="muted" style="margin-top:8px">click scene to edit / upload ref</div>
</div>
<!-- script generator -->
<div class="card">
<h3>📝 script <small>auto</small></h3>
<div class="row">
<select id="scriptLength"><option>15s</option><option>30s</option><option>60s+</option></select>
<select id="scriptTone"><option>Professional</option><option>Casual</option><option>Dramatic</option><option>Humorous</option></select>
<select id="voiceover"><option>Male</option><option>Female</option><option>Neutral</option></select>
</div>
<button id="generateScriptBtn" class="btn" style="margin:10px 0">✍️ generate script</button>
<textarea id="scriptOutput" style="min-height:120px" placeholder="script will appear here..."></textarea>
<button id="exportScriptBtn" class="btn" style="margin-top:8px">📃 export text</button>
</div>
</div>
<!-- visual sequence + audio + checklist -->
<div class="grid">
<div class="card">
<h3>🎨 visual sequence</h3>
<div id="visualSequenceContainer"></div>
<button id="generateVisualBtn" class="btn">🎞️ generate visual plan</button>
<div class="muted" style="margin-top:8px">palette & overlays</div>
</div>
<div class="card">
<h3>🎧 audio direction</h3>
<div class="audio-row"><span>music mood</span><select id="musicMood"><option>Upbeat</option><option>Cinematic</option><option>Relaxed</option><option>Dramatic</option></select></div>
<div class="audio-row"><span>voiceover style</span><select id="voStyle"><option>Warm</option><option>Energetic</option><option>Deep</option></select></div>
<div class="audio-row"><span>voiceover vs music</span><input type="range" min="0" max="100" value="70" id="volBalance"> <span id="volLabel">70/30</span></div>
<button id="exportAudioBtn" class="btn">🎵 export audio notes</button>
</div>
<div class="card">
<h3>✅ production checklist</h3>
<div id="checklistContainer"></div>
<button id="addChecklistItemBtn" class="btn">+ add item</button>
<button id="exportChecklistBtn" class="btn" style="margin-left:8px">export</button>
</div>
</div>
<!-- final output preview -->
<div class="card" style="margin-top:24px">
<h3>📦 final showreel outline <small>preview</small></h3>
<div id="finalPreview" class="export-block"></div>
<div class="export-actions">
<button id="compileAllBtn" class="btn primary">🧩 compile all</button>
<button id="downloadReportBtn" class="btn">⬇️ download .txt</button>
</div>
</div>
</div>
<script>
(function() {
// ---------- state ----------
const state = {
brief: { name:'My showreel', length:'30s', tone:'Professional', audience:'creatives', message:'bold visuals', style:'minimal' },
storyboard: [],
script: 'This is a placeholder script. Click generate.',
visualPlan: [],
audio: { mood:'Upbeat', vo:'Warm', balance:70 },
checklist: ['Camera', 'Lens', 'Lighting', 'Audio recorder'],
dark: false,
primary: '#4f46e5'
};
const $ = id => document.getElementById(id);
const container = {
storyboard: $('storyboardContainer'),
visual: $('visualSequenceContainer'),
checklist: $('checklistContainer'),
final: $('finalPreview')
};
// -------- helpers ----------
function saveState() {
localStorage.setItem('showreelStudio', JSON.stringify(state));
}
function loadState() {
const saved = localStorage.getItem('showreelStudio');
if(saved) { try { Object.assign(state, JSON.parse(saved)); } catch(e){} }
}
function applyPrimary(color) {
document.documentElement.style.setProperty('--primary', color);
state.primary = color;
saveState();
}
function applyDark(dark) {
document.body.classList.toggle('dark', dark);
state.dark = dark;
saveState();
}
// -------- render functions ------
function renderStoryboard() {
if(!state.storyboard.length) {
container.storyboard.innerHTML = `<div class="muted">no scenes yet - click generate</div>`;
return;
}
let html = '';
state.storyboard.forEach((s, idx) => {
html += `<div class="scene-item" data-idx="${idx}">
<div class="scene-head"><span>${idx+1}. ${s.shotType}</span><span class="shot">${s.duration}</span></div>
<div>${s.description}</div>
<div class="muted">overlay: ${s.overlay || 'none'}</div>
<div class="placeholder-img" style="background:var(--accent-soft);border-radius:12px;padding:6px;margin-top:6px;font-size:0.7rem">📁 ref: ${s.ref || 'upload'}</div>
</div>`;
});
container.storyboard.innerHTML = html;
}
function renderVisual() {
if(!state.visualPlan.length) {
container.visual.innerHTML = `<div class="muted">no visual plan yet</div>`;
return;
}
let html = '';
state.visualPlan.forEach(v => {
html += `<div class="scene-item"><strong>${v.scene}</strong> · ${v.visuals} <br> <span class="tag">${v.palette}</span> <span class="tag">${v.overlay}</span></div>`;
});
container.visual.innerHTML = html;
}
function renderChecklist() {
container.checklist.innerHTML = '';
state.checklist.forEach((item, i) => {
const div = document.createElement('div');
div.className = 'checklist-item';
div.innerHTML = `<input type="checkbox" data-idx="${i}" ${item.done ? 'checked' : ''}> <span>${item.text}</span> <button class="btn" data-del="${i}" style="margin-left:auto;padding:2px 8px">✕</button>`;
container.checklist.appendChild(div);
});
}
function renderFinalPreview() {
const s = state;
const scenes = s.storyboard.map(sc => `${sc.shotType} - ${sc.description}`).join('\n');
container.finalPreview.textContent =
`🎬 SHOWREEL OUTLINE
Project: ${s.project.name} | ${s.project.length} | ${s.project.tone}
Audience: ${s.project.audience}
Message: ${s.project.keyMessage}
STORYBOARD:
${scenes || 'no scenes'}
SCRIPT:
${s.script}
VISUAL PLAN:
${s.visualPlan.map(v=>`${v.scene}: ${v.visuals} (${v.palette})`).join('\n')}
AUDIO: mood=${s.audio.mood} | vo=${s.audio.voStyle} | balance=${s.audio.balance}
CHECKLIST:
${s.checklist.map(c=>`[${c.done?'✓':' '}] ${c.text}`).join('\n')}
`;
}
// ---------- generation ----------
function generateStoryboard() {
const brief = state.project;
const scenes = [];
const types = ['Wide', 'Medium', 'Close-up'];
const desc = ['establishing shot', 'action sequence', 'detail close-up', 'interview', 'product reveal'];
const dur = brief.length === '15s' ? '2s' : brief.length === '30s' ? '3s' : '5s';
for(let i=0; i<4; i++) {
scenes.push({
shotType: types[i%3],
description: `${desc[Math.floor(Math.random()*desc.length]} - ${brief.style}`,
overlay: i===2 ? 'text: key message' : 'none',
duration: dur,
ref: ''
});
}
state.storyboard = scenes;
renderStoryboard(); saveState();
}
function generateScript() {
const len = $('scriptLength').value;
const tone = $('scriptTone').value;
const vo = $('voiceover').value;
const msg = state.project.keyMessage || 'your message';
let script = '';
if(len === '15s') script = `[HOOK] attention grabber... ${msg}. quick cut.`;
else if(len === '30s') script = `[HOOK] 5s. \n[BODY] introduce problem, solution. \n[CTA] visit site.`;
else script = `[HOOK] 10s. \n[BODY] key points... \n[CTA] subscribe.`;
script += `\n(tone: ${tone}, voice: ${vo})`;
state.script = script;
$('scriptOutput').value = script;
saveState(); renderFinal();
}
function generateVisual() {
const palettes = ['#0f172a #4f46e5', '#f59e0b #0ea5e9', '#dc2626 #facc15'];
const v = [];
for(let i=0;i<3;i++) {
v.push({ scne:`scene ${i+1}`, visuals:`stock: city timelapse`, palette: palettes[i], overay:`graphic ${i+1}` });
}
state.visualPlan = v; renderVisual(); saveState(); renderFinal();
}
function generateChecklist() {
state.checklist = [
{text:'camera & lenses', done:false},
{text:'microphone + recorder', done:false},
{text:'lighting kit', done:false},
{text:'talent release', done:false},
{text:'editing software', done:false}
];
renderChecklist(); saveState(); renderFinal();
}
// ------ event listeners ------
function init() {
loadState();
applyPrimary(state.primary);
applyDark(state.dark);
$('darkModeToggle').onclick = () => { state.dark = !state.dark; applyDark(state.dark); };
$('primaryColorPicker').value = state.primary;
$('primaryColorPicker').oninput = (e) => { applyPrimary(e.target.value); };
// template apply
$('applyTemplateBtn').onclick = () => {
const t = $('templateSelect').value;
if(t === 'product') { $('projectName').value = 'Product Launch'; $('keyMessage').value = 'innovative features'; }
else if(t === 'portfolio') { $('projectName').value = 'Portfolio 2025'; $('keyMessage').value = 'creative range'; }
else if(t === 'promo') { $('projectName').value = 'Promo'; $('keyMessage').value = 'limited offer'; }
else if(t === 'edu') { $('projectName').value = 'Learning'; $('keyMessage').value = 'easy to understand'; }
else { $('projectName').value = 'Social Ad'; $('keyMessage').value = 'join us'; }
saveBrief();
};
$('saveBriefBtn').onclick = saveBrief;
function saveBrief() {
state.project = {
name: $('projectName').value,
length: $('videoLength').value,
tone: $('toneSelect').value,
audience: $('audience').value,
keyMessage: $('keyMessage').value,
style: $('styleRef').value
};
saveState(); renderFinal();
}
// storyboard
$('generateStoryboardBtn').onclick = () => { generateStoryboard(); renderFinal(); };
$('exportStoryboardBtn').onclick = () => { alert('storyboard exported (simulated)'); };
// script
$('generateScriptBtn').onclick = () => { generateScript(); renderFinal(); };
$('exportScriptBtn').onclick = () => {
const blob = new Blob([state.script], {type:'text/plain'});
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'script.txt'; a.click();
};
// visual
$('generateVisualBtn').onclick = () => { generateVisual(); renderFinal(); };
// audio
$('exportAudioBtn').onclick = () => {
const notes = `Music mood: ${$('musicMood').value}\nVO style: ${$('voStyle').value}\nBalance: ${$('volBalance').value}`;
alert('audio notes:\n'+notes);
};
$('volBalance').oninput = (e) => { $('colorLabel').textContent = e.target.value + '/30'; };
// checklist
$('addChecklistItemBtn').onclick = () => {
const text = prompt('new checklist item');
if(text) { state.checklist.push({text, done:false}); renderChecklist(); saveState(); renderFinal(); }
};
container.checklist.addEventListener('click', (e) => {
const del = e.target.dataset.del;
if(del !== undefined) { state.checklist.splice(del,1); renderChecklist(); saveState(); renderFinal(); }
const cb = e.target.dataset.idx;
if(cb !== undefined) { state.checklist[c b].done = e.target.checked; saveState(); renderFinal(); }
});
// export / import
$('exportJsonBtn').onclick = () => {
const blob = new Blob([JSON.stringify(state, null, 2)], {type:'application/json'});
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'showreel-project.json'; a.click();
};
$('importJsonBtn').onclick = () => $('importFile').click();
$('importFile').onchange = (e) => {
const file = e.target.files[0]; if(!file) return;
const reader = new FileReader();
reader.onload = (ev) => { try { const parsed = JSON.parse(ev.target.result); Object.assign(state, parsed); renderAll(); saveState(); } catch(err) { alert('invalid JSON'); } };
reader.readAsText(file);
};
// compile & report
$('compileAllBtn').onclick = () => { renderFinal(); alert('compiled'); };
$('downloadReportBtn').onclick = () => {
const txt = container.finalPreview.textContent;
const blob = new Blob([txt], {type:'text/plain'});
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'showreel-outline.txt'; a.click();
};
// initial render
renderStoryboard(); renderVisual(); renderChecklist(); renderFinal();
$('scriptOutput').value = state.script;
saveState();
}
function saveAll() { renderStoryboard(); renderVisual(); renderChecklist(); renderFinal(); saveState(); }
document.addEventListener('DOMContentLoaded', init);
})();
</script>
</body>
</html>
Iniciá sesión para ver el prompt completo
Continuar con:
Al iniciar sesión, aceptás nuestros Términos de uso y Política de privacidad
Uso
Este prompt está diseñado para usarse con coding. Copiá el contenido de arriba y pegalo en tu herramienta de IA preferida.
Para mejores resultados, personalizá los marcadores (indicados con corchetes o mayúsculas) con tus requisitos específicos.
Referencias
- Categoría: Prompts de coding
- Fuente: https://x.com/eyishazyer/status/2073109278379171899
Discusión
0 comentarios