// workflows/index.js — Dee Ferdinand Video Studio
// Fixed: black frames, cutoff, timing gaps, exit animation ban, autoAlpha
// Audio: no muted on video, research-backed data-volume levels
// Music: ElevenLabs lo-fi upbeat (primary) → YuE (fallback) → silence
const FONTS = ``;
const GSAP = ``;
const GRAIN = `
`;
function mediaEl(m, start, dur, tIdx, vol) {
if (!m) return '';
if (m.mime?.startsWith('video/')) {
// NO muted — subject voice must come through. Framework controls via data-volume.
return `
`;
}
return `` ;
}
// ── TESTIMONIAL 30s 9:16 ──────────────────────────────────────────────────────────
// Timing: each scene overlaps the previous by 0.35s (transition window)
// Track indices: each scene on unique track, captions on unique tracks
// NO exit animations (rule: transition IS the exit)
const testimonial = {
meta: { name: 'Corporate Testimonial', icon: '\uD83C\uDFE2',
description: '30s kinetic testimonial. 9:16. ElevenLabs lo-fi music.',
format: '9:16', duration: 30, music: 'lofi-upbeat' },
buildHTML(media, config, compId, w, h, dur) {
const { clientName='AI Training', trainerName='Dee Ferdinand',
tagline='AI Corporate Trainer', website='deeferdinand.com' } = config;
const vids = media.filter(m => m.mime?.startsWith('video/'));
const imgs = media.filter(m => m.mime?.startsWith('image/'));
const pick = (i) => media[i % Math.max(media.length,1)] || media[0];
const img = (i) => imgs[i % Math.max(imgs.length,1)] || pick(i);
const mVid = vids[0] || null;
const yr = new Date().getFullYear();
// Strict scene timing: NO gaps, transitions overlap by 0.35s on DIFFERENT tracks
// S1: 0-4s S2: 3.65-8s (T1 at 3.65) S3: 7.65-16.5s (T2 at 7.65)
// S4a: 15.85-18.5s S4b: 18.2-21s S4c: 20.7-23.2s
// S5: 22.85-28.5s (T3 at 22.85) S6: 28.2-30.5s
// All captions on own tracks, gap from scene start: 0.2s
return `
${FONTS}${GSAP}