From b141dd23d7c0a4c0ae31ae8a8698c3c82276f4d6 Mon Sep 17 00:00:00 2001 From: EtienneLescot <215859519+EtienneLescot@users.noreply.github.com> Date: Sat, 20 Jun 2026 06:15:19 +0000 Subject: [PATCH 1/4] Add export preview diagnostics --- src/components/video-editor/VideoEditor.tsx | 56 +++++++++++++++++++ src/components/video-editor/VideoPlayback.tsx | 39 ++++++++++++- 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index 445a09060..1d5c92c3d 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -174,6 +174,31 @@ function buildSaveDiagnosticMessage(formatLabel: "GIF" | "Video", reason?: strin return `${formatLabel} export save failed${reason ? `\nReason: ${reason}` : ""}`; } +function getPreviewVideoDiagnostics(video: HTMLVideoElement | null) { + if (!video) { + return { present: false }; + } + + return { + present: true, + src: video.currentSrc || video.src, + readyState: video.readyState, + networkState: video.networkState, + error: video.error + ? { + code: video.error.code, + message: video.error.message, + } + : null, + currentTime: Number.isFinite(video.currentTime) ? video.currentTime : null, + duration: Number.isFinite(video.duration) ? video.duration : null, + paused: video.paused, + ended: video.ended, + videoWidth: video.videoWidth, + videoHeight: video.videoHeight, + }; +} + const CAPTION_WORD_CHOICES = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] as const; export default function VideoEditor() { @@ -1855,6 +1880,31 @@ export default function VideoEditor() { setExportError(null); setExportedFilePath(null); + const previewBeforeExport = getPreviewVideoDiagnostics(video); + console.info("[VideoEditor] export started", { + format: settings.format, + sourcePath: videoSourcePath ?? videoPath, + videoPath, + webcamVideoPath, + preview: previewBeforeExport, + settings: { + exportQuality: settings.quality || exportQuality, + aspectRatio, + padding, + borderRadius, + shadowIntensity, + showBlur, + motionBlurAmount, + cropRegion, + zoomRegions: zoomRegions.length, + trimRegions: trimRegions.length, + speedRegions: speedRegions.length, + annotations: annotationRegions.length, + effectiveShowCursor, + cursorSize, + }, + }); + try { const wasPlaying = isPlaying; if (wasPlaying) { @@ -2080,6 +2130,12 @@ export default function VideoEditor() { toast.error(t("errors.exportFailedWithError", { error: message })); } } finally { + console.info("[VideoEditor] export finished", { + sourcePath: videoSourcePath ?? videoPath, + videoPath, + previewBefore: previewBeforeExport, + previewAfter: getPreviewVideoDiagnostics(videoPlaybackRef.current?.video ?? null), + }); setIsExporting(false); exporterRef.current = null; // Reset so the next export can reopen the dialog (second export diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx index 1b4ad5263..fbb2767ae 100644 --- a/src/components/video-editor/VideoPlayback.tsx +++ b/src/components/video-editor/VideoPlayback.tsx @@ -215,6 +215,26 @@ function enableAllPreviewAudioTracks(video: HTMLVideoElement) { } } +function getVideoElementDiagnostics(video: HTMLVideoElement) { + return { + src: video.currentSrc || video.src, + readyState: video.readyState, + networkState: video.networkState, + error: video.error + ? { + code: video.error.code, + message: video.error.message, + } + : null, + currentTime: Number.isFinite(video.currentTime) ? video.currentTime : null, + duration: Number.isFinite(video.duration) ? video.duration : null, + paused: video.paused, + ended: video.ended, + videoWidth: video.videoWidth, + videoHeight: video.videoHeight, + }; +} + const VideoPlayback = forwardRef( ( { @@ -345,6 +365,16 @@ const VideoPlayback = forwardRef( const speedRegionsRef = useRef([]); const motionBlurAmountRef = useRef(motionBlurAmount); const cursorOverlayRef = useRef(null); + + const logPreviewVideoEvent = useCallback( + (event: React.SyntheticEvent) => { + console.info(`[VideoPlayback] preview video ${event.type}`, { + videoPath, + diagnostics: getVideoElementDiagnostics(event.currentTarget), + }); + }, + [videoPath], + ); const showCursorRef = useRef(showCursor); const cursorSizeRef = useRef(cursorSize); const cursorSmoothingRef = useRef(cursorSmoothing); @@ -2152,7 +2182,14 @@ const VideoPlayback = forwardRef( forceResolveDuration(e.currentTarget); } }} - onError={() => onError("Failed to load video")} + onEmptied={logPreviewVideoEvent} + onStalled={logPreviewVideoEvent} + onSuspend={logPreviewVideoEvent} + onAbort={logPreviewVideoEvent} + onError={(event) => { + logPreviewVideoEvent(event); + onError("Failed to load video"); + }} /> {supplementalAudioPath && (