Skip to content

@remotion/studio: Fix staticFile() assets after server restarts - #11962

Merged
samohovets merged 4 commits into
mainfrom
studio-staticfile
Oct 5, 2026
Merged

samohovets merged 4 commits into
mainfrom
studio-staticfile

Conversation

@samohovets

@samohovets samohovets commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Summary

Fix Studio assets failing to load after the server is stopped and started again.

  • Derive the static asset namespace from the project root and public folder so asset paths remain stable across restarts and remain scoped to the same project/folder.
  • Keep output namespaces random per startup, since output routes serve files from the project root.
  • Pass the output namespace explicitly through the HTML bootstrap instead of deriving it from the static asset namespace. Bundled and Browser Studios pass null because they do not have an output server.
  • Reuse the random per-start output namespace as an asset query version. This preserves the previous implicit cache-busting behavior when restarting and reloading Studio to recover from replaced files or stale browser/media caches, while old asset URLs remain valid. It does not automatically refresh an already-open browser.
  • Keep listed asset sources and staticFile() fallbacks consistent. Exclude query versions from serialized file tokens and handle versioned, encoded URLs in both watch APIs, deletion, and timeline asset links.

Closes #11895

Verification

  • bun run build
  • bun run stylecheck
  • 39 existing focused tests passed across Core, Studio Shared, Studio Server, and Studio for the initial URL-survival change.
  • Follow-up: 56 existing focused tests passed across Core, Studio Server, and Studio for serialization, asset URLs, timeline links, and static-file operations.
  • During implementation, a real Studio restart check confirmed that encoded asset URLs survive restarts, output namespaces rotate and remain usable, and changing the public folder rejects the old asset URL.
  • A real replacement/restart check confirmed that only the asset query version rotates, both old and new URLs serve replacement bytes, listed and fallback URLs agree, serialized tokens exclude the query version, and both watch APIs and deletion accept versioned URLs with encoded filenames.

No new tests or dependencies were added; the existing HTML test fixture was updated for the new bootstrap input.

@vercel

vercel Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
bugs Ready Ready Preview Oct 5, 2026 12:42pm UTC
remotion Ready Ready Preview Oct 5, 2026 12:42pm UTC

Request Review

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Deterministic static namespace — packages/studio-server/src/start-studio.ts:131 now derives staticHash from a truncated SHA-256 of [remotionRoot, publicDir] instead of a per-startup random value. staticFile() URLs therefore survive a Studio restart, and because both inputs are absolute paths they stay scoped to the same project/public folder (a moved project or changed publicDir gets a new namespace and the old URL 404s via the existing staticHashPrefix guard).
  • Independent output namespace — outputHash remains random per startup (output routes serve relative to the project root, so an immutable predictable prefix would be undesirable) and is threaded explicitly through handleRoutes → handleFallback → BundlerInternals.indexHtml (packages/studio-server/src/routes.ts, packages/studio-shared/src/studio-html.ts), replacing the old staticBase.replace('static', 'outputs') inference.
  • Explicit client base — window.remotion_outputsBase is emitted by the HTML bootstrap, declared in packages/core/src/index.ts:74, and read directly in packages/studio/src/helpers/get-asset-metadata.ts:8 (?? ''). The null branches for the bundled and Browser Studio paths carry no output server, and Browser Studio already produced an empty base because its staticHash is '', so those call sites are behavior-preserving.

Cross-checks performed: all four indexHtml/studioHtml call sites pass the new required field; indexHtml is only surfaced through BundlerInternals, so requiring outputHash is not a public-API break; and no code still derives the outputs base from remotion_staticBase.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash | 𝕏

@samohovets

Copy link
Copy Markdown
Member Author

Verified the caching concern for the common workflow: replace a public asset on disk under the same filename, then refresh the Studio tab.

  • Images: Ran the existing static-file-restart.test.mts Studio end-to-end test in Chromium. It passed: after replacing the image and restarting Studio, an ordinary page reload displayed the replacement at the same asset URL.
  • Videos: Ran a separate diagnostic in installed Google Chrome using the actual Studio serveStatic handler. Replaced a red H.264 MP4 with a blue MP4 under the same filename, without restarting the server, then performed an ordinary page reload. The rendered pixel changed from [254, 0, 0, 255] to [0, 0, 255, 255], with the asset URL unchanged.

No stale-cache regression was reproduced for replace-file → refresh in these checks. This verification does not cover reconnecting an already-open tab without refreshing, or all browser engines.

@samohovets
samohovets merged commit 6a8c73f into main Oct 5, 2026
31 of 33 checks passed
@samohovets
samohovets deleted the studio-staticfile branch October 5, 2026 12:58

This branch was successfully deployed

2 active deployments
Preview – remotion — ca374b28 Deployed Oct 5, 2026 by vercel[bot]
Preview – bugs — ca374b28 Deployed Oct 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio: staticFile() assets don't survive the server restart

1 participant