From 9c9b1beeb5d83c2549511ff7e2b5d65e19acdd52 Mon Sep 17 00:00:00 2001 From: Prasanth Sasikumar Date: Sat, 11 Jul 2026 22:32:18 -0400 Subject: [PATCH] fix(remotion): correct file:// slash count for POSIX absolute paths resolveAsset() built `file:///` + a POSIX absolute path (which already starts with /), yielding `file:////Users/...` (four slashes). Split the branch: POSIX paths get `file://` + path (three slashes total), Windows drive paths keep the explicit extra slash. Same fix across the five compositions that share resolveAsset(). Co-Authored-By: Claude Opus 4.8 (1M context) (cherry picked from commit 226a52d1e9b56b9da8b94e8e95ef6b753666abb0) --- remotion-composer/src/CinematicRenderer.tsx | 10 +++++++++- remotion-composer/src/CollageBurst.tsx | 10 +++++++++- remotion-composer/src/Explainer.tsx | 10 +++++++++- remotion-composer/src/LyricOverlay.tsx | 10 +++++++++- remotion-composer/src/TitledVideo.tsx | 10 +++++++++- remotion-composer/src/components/ScreenshotScene.tsx | 10 +++++++++- 6 files changed, 54 insertions(+), 6 deletions(-) diff --git a/remotion-composer/src/CinematicRenderer.tsx b/remotion-composer/src/CinematicRenderer.tsx index b7c81e25..f3c27412 100644 --- a/remotion-composer/src/CinematicRenderer.tsx +++ b/remotion-composer/src/CinematicRenderer.tsx @@ -19,7 +19,15 @@ function resolveAsset(src: string): string { } const clean = src.replace(/^file:\/\/\/?/, ""); if (clean.startsWith("/") || /^[A-Za-z]:[/\\]/.test(clean)) { - return `file:///${clean.replace(/\\/g, "/")}`; + const posix = clean.replace(/\\/g, "/"); + // POSIX absolute paths already have a leading "/" — file:// + posix + // gives exactly three slashes. Windows drive paths (C:/...) need the + // extra slash added explicitly. Do not merge these branches — adding + // "file:///" unconditionally double-slashes POSIX paths (file:////...). + if (posix.startsWith("/")) { + return `file://${posix}`; + } + return `file:///${posix}`; } return staticFile(clean); } diff --git a/remotion-composer/src/CollageBurst.tsx b/remotion-composer/src/CollageBurst.tsx index 3bba2132..b0400095 100644 --- a/remotion-composer/src/CollageBurst.tsx +++ b/remotion-composer/src/CollageBurst.tsx @@ -26,7 +26,15 @@ function resolveAsset(src: string): string { if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("data:")) return src; const clean = src.replace(/^file:\/\/\/?/, ""); if (clean.startsWith("/") || /^[A-Za-z]:[\\/]/.test(clean)) { - return `file:///${clean.replace(/\\/g, "/")}`; + const posix = clean.replace(/\\/g, "/"); + // POSIX absolute paths already have a leading "/" — file:// + posix + // gives exactly three slashes. Windows drive paths (C:/...) need the + // extra slash added explicitly. Do not merge these branches — adding + // "file:///" unconditionally double-slashes POSIX paths (file:////...). + if (posix.startsWith("/")) { + return `file://${posix}`; + } + return `file:///${posix}`; } return staticFile(clean); } diff --git a/remotion-composer/src/Explainer.tsx b/remotion-composer/src/Explainer.tsx index fb55dde6..cf7ae03f 100644 --- a/remotion-composer/src/Explainer.tsx +++ b/remotion-composer/src/Explainer.tsx @@ -22,7 +22,15 @@ function resolveAsset(src: string): string { // Absolute paths (Unix: /foo, Windows: C:\foo or C:/foo) — convert to file:// URI // staticFile() only accepts relative paths within public/, so absolute paths must bypass it if (clean.startsWith("/") || /^[A-Za-z]:[\\/]/.test(clean)) { - return `file:///${clean.replace(/\\/g, "/")}`; + const posix = clean.replace(/\\/g, "/"); + // POSIX absolute paths already have a leading "/" — file:// + posix + // gives exactly three slashes. Windows drive paths (C:/...) need the + // extra slash added explicitly. Do not merge these branches — adding + // "file:///" unconditionally double-slashes POSIX paths (file:////...). + if (posix.startsWith("/")) { + return `file://${posix}`; + } + return `file:///${posix}`; } return staticFile(clean); } diff --git a/remotion-composer/src/LyricOverlay.tsx b/remotion-composer/src/LyricOverlay.tsx index 24605f57..4896cf1e 100644 --- a/remotion-composer/src/LyricOverlay.tsx +++ b/remotion-composer/src/LyricOverlay.tsx @@ -19,7 +19,15 @@ function resolveAsset(src: string): string { if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("data:")) return src; const clean = src.replace(/^file:\/\/\/?/, ""); if (clean.startsWith("/") || /^[A-Za-z]:[\\/]/.test(clean)) { - return `file:///${clean.replace(/\\/g, "/")}`; + const posix = clean.replace(/\\/g, "/"); + // POSIX absolute paths already have a leading "/" — file:// + posix + // gives exactly three slashes. Windows drive paths (C:/...) need the + // extra slash added explicitly. Do not merge these branches — adding + // "file:///" unconditionally double-slashes POSIX paths (file:////...). + if (posix.startsWith("/")) { + return `file://${posix}`; + } + return `file:///${posix}`; } return staticFile(clean); } diff --git a/remotion-composer/src/TitledVideo.tsx b/remotion-composer/src/TitledVideo.tsx index baaa0b8a..0129271c 100644 --- a/remotion-composer/src/TitledVideo.tsx +++ b/remotion-composer/src/TitledVideo.tsx @@ -46,7 +46,15 @@ function resolveAsset(src: string): string { } const clean = src.replace(/^file:\/\/\/?/, ""); if (clean.startsWith("/") || /^[A-Za-z]:[\\/]/.test(clean)) { - return `file:///${clean.replace(/\\/g, "/")}`; + const posix = clean.replace(/\\/g, "/"); + // POSIX absolute paths already have a leading "/" — file:// + posix + // gives exactly three slashes. Windows drive paths (C:/...) need the + // extra slash added explicitly. Do not merge these branches — adding + // "file:///" unconditionally double-slashes POSIX paths (file:////...). + if (posix.startsWith("/")) { + return `file://${posix}`; + } + return `file:///${posix}`; } return staticFile(clean); } diff --git a/remotion-composer/src/components/ScreenshotScene.tsx b/remotion-composer/src/components/ScreenshotScene.tsx index 89cbc3ff..777f0f19 100644 --- a/remotion-composer/src/components/ScreenshotScene.tsx +++ b/remotion-composer/src/components/ScreenshotScene.tsx @@ -90,7 +90,15 @@ function resolveAsset(src: string): string { } const clean = src.replace(/^file:\/\/\/?/, ""); if (clean.startsWith("/") || /^[A-Za-z]:[\\/]/.test(clean)) { - return `file:///${clean.replace(/\\/g, "/")}`; + const posix = clean.replace(/\\/g, "/"); + // POSIX absolute paths already have a leading "/" — file:// + posix + // gives exactly three slashes. Windows drive paths (C:/...) need the + // extra slash added explicitly. Do not merge these branches — adding + // "file:///" unconditionally double-slashes POSIX paths (file:////...). + if (posix.startsWith("/")) { + return `file://${posix}`; + } + return `file:///${posix}`; } return staticFile(clean); }