import { useEffect, useState } from 'react' import { api } from '../api' import { useJob, ProgressBox, ErrorBox } from '../hooks' const PRESETS = ['bold-center-karaoke', 'clean-lower-third', 'minimal', 'typewriter', 'punch'] export default function RenderStep({ reelData, refreshReel, setStep, projectId, reelId, selectReel, refreshProject }) { const job = useJob() // Translate this reel into another language → a new sibling reel. const tjob = useJob() const [langs, setLangs] = useState([]) const [targetLang, setTargetLang] = useState('es') useEffect(() => { api.get('/api/translate/languages').then((d) => setLangs(d.languages || [])).catch(() => {}) }, []) const translate = async () => { try { const result = await tjob.start(`/api/projects/${projectId}/reels/${reelId}/translate`, { target_lang: targetLang }) if (refreshProject) await refreshProject() if (selectReel && result?.reel) { selectReel(result.reel.id); setStep(4) } // → Media: pick a voice in that language } catch { /* shown */ } } // Default to ONE variant that matches the editor (WYSIWYG); add more for A/B. const editPreset = reelData?.overlays?.caption_preset || PRESETS[0] const editCaptions = reelData?.overlays?.captions_on !== false const [specs, setSpecs] = useState([ { name: 'As edited', caption_preset: editPreset, captions: editCaptions, voice: true, clip_offset: 0 }, ]) const lines = reelData?.voice?.lines?.length || 0 // segments + captions + final per variant — rough progress out of total steps const totalSteps = specs.length * (lines + 2) const pct = job.running ? Math.min(95, Math.round((job.progress.length / Math.max(totalSteps, 1)) * 100)) : 0 const start = async () => { try { await job.start(`/api/projects/${projectId}/reels/${reelId}/render`, { variants: specs }) await refreshReel() setStep(7) } catch { /* shown */ } } return (
Renders {specs.length} draft variants — different clip picks (from the alternates) and caption styles — to compare side by side.
{specs.map((s, i) => { const upd = (patch) => setSpecs(specs.map((x, j) => (j === i ? { ...x, ...patch } : x))) const captionsOn = s.captions !== false const voiceOn = s.voice !== false return (Turn off Captions for clips-only, or Voice for a music-only / silent cut. Overlays from the Effects step always render.
Creates a new reel with the script translated (visuals stay the same). Pick a matching voice on the Media step, then render — captions come out native.
{tjob.running &&