skill
Movie Maker
UnreviewedRecord narrated walkthroughs of your Gallia project with screen + mic capture, silence detection, smart playback that skips dead air, timeline markers, and a full video library with thumbnails.
<!DOCTYPE html>
<html lang="en">
<head><script>(function(){var n=0;function show(p,m){var el=document.createElement('div');el.style.cssText='position:fixed;left:0;right:0;background:#e04040;color:#fff;padding:6px 12px;z-index:'+(99999-n)+';font:13px/1.4 monospace;white-space:pre-wrap;border-bottom:1px solid #b02020;top:'+n*30+'px';el.textContent=p+m;document.body.appendChild(el);n++}window.onerror=function(msg,src,line){show('ERROR '+(src||'').split('/').pop()+':'+line+' \u2014 ',msg)};window.addEventListener('unhandledrejection',function(e){show('REJECT \u2014 ',e.reason&&e.reason.message||e.reason||'unknown')})})()</script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Movie Maker — Library</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0d1117; color: #e6edf3;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
height: 100vh; display: flex; flex-direction: column; overflow: hidden;
}
.tab-bar {
display: flex; border-bottom: 1px solid #21262d; background: #161b22; flex-shrink: 0;
}
.tab-bar button {
padding: 10px 24px; background: none; border: none; color: #8b949e;
font-size: 13px; font-weight: 500; cursor: pointer; position: relative;
font-family: inherit;
}
.tab-bar button.active { color: #e6edf3; }
.tab-bar button.active::after {
content: ''; position: absolute; bottom: 0; left: 0; right: 0;
height: 2px; background: #00b8b0; border-radius: 1px 1px 0 0;
}
.library-header {
display: flex; align-items: center; justify-content: space-between;
padding: 16px 20px; border-bottom: 1px solid #21262d; flex-shrink: 0;
}
.library-header h2 { font-size: 16px; font-weight: 600; }
.library-header span { color: #8b949e; font-size: 13px; }
.video-grid {
display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px; padding: 20px; overflow-y: auto; flex: 1;
}
.video-card {
background: #161b22; border: 1px solid #21262d; border-radius: 8px;
overflow: hidden; transition: border-color 0.15s;
}
.video-card:hover { border-color: #30363d; }
.video-thumb {
width: 100%; aspect-ratio: 16/9; background: #0d1117; position: relative;
cursor: pointer; overflow: hidden;
}
.video-thumb canvas { width: 100%; height: 100%; }
.thumb-duration {
position: absolute; bottom: 6px; right: 6px;
background: rgba(0,0,0,0.8); color: #fff; font-size: 11px;
padding: 2px 6px; border-radius: 3px; font-variant-numeric: tabular-nums;
}
.thumb-play {
position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
width: 44px; height: 44px; background: rgba(0,0,0,0.6); border-radius: 50%;
display: flex; align-items: center; justify-content: center;
opacity: 0; transition: opacity 0.15s;
}
.video-thumb:hover .thumb-play { opacity: 1; }
.video-info { padding: 12px; }
.video-title {
font-size: 14px; font-weight: 600; margin-bottom: 4px;
background: none; border: none; color: #e6edf3; width: 100%;
font-family: inherit; outline: none;
}
.video-meta { color: #8b949e; font-size: 12px; display: flex; gap: 12px; margin-bottom: 6px; }
.video-silence { font-size: 12px; margin-bottom: 8px; }
.video-actions { display: flex; gap: 8px; }
.btn-sm {
padding: 5px 12px; font-size: 11px; border-radius: 5px; border: none;
font-family: inherit; font-weight: 500; cursor: pointer;
display: inline-flex; align-items: center; gap: 5px;
}
.btn-play { background: #238636; color: #fff; }
.btn-link { background: #21262d; color: #e6edf3; border: 1px solid #30363d; }
.btn-del { background: #21262d; color: #f85149; border: 1px solid #30363d; }
.demo-note {
position: fixed; bottom: 8px; right: 12px; color: #484f58; font-size: 10px;
}
</style>
</head>
<body>
<div class="tab-bar">
<button>Record</button>
<button class="active">Library</button>
<button>Scripts</button>
</div>
<div class="library-header">
<h2>Video Library</h2>
<span>3 recordings</span>
</div>
<div class="video-grid" id="grid"></div>
<div class="demo-note">Demo — simulated data</div>
<script>
const videos = [
{ title: 'PCB Review — Rev B', duration: 347000, size: 24500000, date: '2026-03-02',
silences: [{startMs:12000,endMs:18000},{startMs:45000,endMs:52000},{startMs:120000,endMs:135000},{startMs:210000,endMs:218000}],
color1: '#1a3a4a', color2: '#0d2636' },
{ title: '3D Model Walkthrough', duration: 182000, size: 12800000, date: '2026-03-01',
silences: [{startMs:8000,endMs:14000},{startMs:90000,endMs:96000}],
color1: '#2a1a3a', color2: '#1a0d2d' },
{ title: 'Schematic Annotation Demo', duration: 95000, size: 6700000, date: '2026-02-28',
silences: [],
color1: '#1a3a2a', color2: '#0d2d1a' }
];
function fmt(ms) {
const s = Math.floor(ms / 1000);
const m = Math.floor(s / 60);
const sec = s % 60;
return m + ':' + String(sec).padStart(2, '0');
}
function fmtSize(b) {
return (b / 1048576).toFixed(1) + ' MB';
}
const grid = document.getElementById('grid');
videos.forEach(v => {
const totalSilence = v.silences.reduce((s, r) => s + (r.endMs - r.startMs), 0);
const talkMs = v.duration - totalSilence;
let silenceHtml;
if (v.silences.length > 0) {
silenceHtml = `<span style="color:#d29922;">${v.silences.length} silence${v.silences.length>1?'s':''} (${fmt(totalSilence)} dead air, ${fmt(talkMs)} talking)</span>`;
} else {
silenceHtml = `<span style="color:#3fb950;">${fmt(talkMs)} talking, no dead air</span>`;
}
const card = document.createElement('div');
card.className = 'video-card';
card.innerHTML = `
<div class="video-thumb">
<canvas width="320" height="180" id="c-${v.title.replace(/\s/g,'')}"></canvas>
<span class="thumb-duration">${fmt(v.duration)}</span>
<div class="thumb-play">
<svg width="20" height="20" viewBox="0 0 24 24" fill="#fff"><polygon points="8,5 19,12 8,19"/></svg>
</div>
</div>
<div class="video-info">
<div class="video-title">${v.title}</div>
<div class="video-meta">
<span>${v.date}</span>
<span>${fmtSize(v.size)}</span>
<span>${fmt(v.duration)}</span>
</div>
<div class="video-silence">${silenceHtml}</div>
<div class="video-actions">
<button class="btn-sm btn-play">▶ Play</button>
<button class="btn-sm btn-link">Copy Link</button>
<button class="btn-sm btn-del">Delete</button>
</div>
</div>
`;
grid.appendChild(card);
// Draw a fake thumbnail
const canvas = card.querySelector('canvas');
const ctx = canvas.getContext('2d');
const grd = ctx.createLinearGradient(0, 0, 320, 180);
grd.addColorStop(0, v.color1);
grd.addColorStop(1, v.color2);
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 320, 180);
// Add some fake UI elements
ctx.fillStyle = '#30363d';
ctx.fillRect(0, 0, 320, 24);
ctx.fillStyle = '#8b949e';
ctx.font = '10px sans-serif';
ctx.fillText('Gallia Viewer', 8, 16);
// Simulate content area
ctx.strokeStyle = '#21262d';
ctx.lineWidth = 1;
for (let i = 40; i < 160; i += 20) {
ctx.beginPath();
ctx.moveTo(20, i);
ctx.lineTo(300, i);
ctx.stroke();
}
ctx.fillStyle = '#00b8b0';
ctx.globalAlpha = 0.3;
ctx.fillRect(60, 50, 200, 80);
ctx.globalAlpha = 1;
});
</script>
</body>
</html>