fix: 3 critical bugs — audio corruption, blob URLs, static duration

1. Audio/Video sync: During playback, let the browser handle media naturally
   and only force-seek when drift > 250ms. Prevents audio glitching caused
   by setting currentTime 30x/sec. When paused/scrubbing, sync precisely.

2. Blob URLs → Server uploads: All media uploads (BrandTabMedia, SceneFieldEditor,
   TemplateFieldInput) now POST to /api/upload and use persistent server URLs
   instead of blob: URLs that vanish on refresh.

3. Dynamic duration: Added useVideoDurations hook that probes actual video
   durations from uploaded form videos. getTemplateDuration and
   compileExpressToTimeline now accept videoDurations to override static
   durationSeconds for form-sourced scenes.
This commit is contained in:
2026-06-02 09:48:28 -05:00
parent 32505f95ce
commit a21675e5fc
9 changed files with 212 additions and 37 deletions
+20 -6
View File
@@ -131,9 +131,16 @@ export const BrandTabMedia: React.FC<BrandTabMediaProps> = ({ designMD, handleDe
compact
accept="audio/*"
label="Subir audio"
onFiles={(files) => {
const url = URL.createObjectURL(files[0]);
handleDesignChange('brandAudioUrl', url);
onFiles={async (files) => {
const formData = new FormData();
formData.append('file', files[0]);
try {
const res = await fetch('/api/upload', { method: 'POST', body: formData });
const data = await res.json();
if (data.url) handleDesignChange('brandAudioUrl', data.url);
} catch (err) {
console.error('Audio upload failed:', err);
}
}}
/>
</div>
@@ -231,9 +238,16 @@ const VideoUploadSimple: React.FC<{
compact
accept="video/*"
label="Subir archivo"
onFiles={(files) => {
const url = URL.createObjectURL(files[0]);
onUrlChange(url);
onFiles={async (files) => {
const formData = new FormData();
formData.append('file', files[0]);
try {
const res = await fetch('/api/upload', { method: 'POST', body: formData });
const data = await res.json();
if (data.url) onUrlChange(data.url);
} catch (err) {
console.error('Video upload failed:', err);
}
}}
/>
</div>