[Stream] Add support for serving videos locally + watermark/caption upload support#13234
Conversation
|
UnknownError: ProviderInitError |
|
@natewong1313 Bonk workflow failed. Check the logs for details. View workflow run · To retry, trigger Bonk again. |
|
Codeowners approval required for this PR:
Show detailed file reviewers
|
481e59d to
7f2ace4
Compare
🦋 Changeset detectedLatest commit: 40306e2 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
7f2ace4 to
3b72f47
Compare
create-cloudflare
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-pool-workers
@cloudflare/workers-editor-shared
wrangler
commit: |
3b72f47 to
3ff6dd6
Compare
|
Moving this to draft as it looks like it's not yet ready for review. |
aa52d8a to
edcd5ed
Compare
This comment was marked as resolved.
This comment was marked as resolved.
edcd5ed to
e562cba
Compare
|
Good, Now let me think about whether there are any actual logic bugs or issues remaining:
Let me now check if there are any issues with missing the The code is well-structured. Let me verify one last thing that caught my eye — the This is fine in test code, and After a thorough review, I don't see any actionable issues (logic bugs, security issues, backward compatibility violations, or incorrect API behavior) that haven't already been flagged by previous reviews. The previous bonk review's suggestion was already incorporated into the code. All other review findings were resolved. LGTM |
…eview URLs Instead of baking the loopback server address into a static MF_STREAM_DEV_SERVER_URL binding and relaying /cdn-cgi/mf/stream/ requests through the loopback back into workerd, the stream binding worker now queries the loopback for the user-facing runtime entry URL at request time via a new /core/entry-url route. This is architecturally cleaner because: - The loopback server is used for its intended purpose (letting workerd workers query Node.js for runtime state) rather than as a reverse proxy for user-facing content. - Preview URLs now correctly point at the user-facing entry worker port (e.g. http://127.0.0.1:8787) instead of the internal loopback port. - Requests to preview URLs are handled directly by the entry worker without any relay hop. - Works correctly even with port 0 (auto-assign) since the URL is resolved at runtime, not config time.
Add a publicUrl option to Miniflare's shared config that consumers (Wrangler, Vite plugin) use to provide the stable, externally-reachable URL of the proxy server in front of Miniflare. This URL outlives workerd runtime restarts, making stream video preview URLs durable for the entire dev session. - Miniflare: publicUrl threaded through CoreSharedOptionsSchema -> PluginServicesOptions -> stream plugin -> MF_STREAM_PUBLIC_URL binding - Wrangler: constructs publicUrl from dev server config (hostname, port, secure) in convertToConfigBundle - Vite plugin: constructs publicUrl from Vite's resolved server config in both dev and preview modes - Binding worker prefers the static publicUrl when set, falls back to the /core/entry-url loopback route for direct Miniflare usage
…d add stream publicUrl tests
…public-url loopback route The stream binding now always fetches the public URL from Miniflare's /core/public-url loopback route instead of reading a static binding. This allows the Vite plugin to update publicUrl after the server starts listening (e.g. when the port is bumped) without restarting workerd. - Add Miniflare.publicUrl public field and /core/public-url loopback route - Remove MF_STREAM_PUBLIC_URL binding from stream plugin - Simplify getEntryUrl() in binding.worker.ts to always use loopback - Add post-listen handler in vite plugin dev/preview to update publicUrl - Extract buildPublicUrl() helper for shared URL construction logic - Fix playground port-bump test to pass (was test.fails)
In practice this should never happen as the event that triggers this code always provides a fully filled out `server` object AFAICT.
…t-bump test On Vite 6/7 on Linux, the default host may resolve to ::1 (IPv6), which doesn't conflict with a 0.0.0.0 (IPv4) blocker. Explicitly setting host: "127.0.0.1" on both sides guarantees the port conflict across all platforms and Vite versions.
d46326b to
40306e2
Compare
|
lgtm from the Stream side |
This PR adds local video serving support to the Stream binding, allowing users to fetch uploaded video blobs via preview URLs. It also adds support for caption and watermark uploads.
Architecture
The local Stream binding runs as three workerd services:
object.worker.ts) -- a Durable Object that stores video metadata in SQLite and video/watermark/caption blobs in blob storagebinding.worker.ts) -- aWorkerEntrypointthat exposes the Stream RPC API (upload,video().details(),videos.list(), etc.) and afetch()handler for serving video blobsVideo serving flow
When a user uploads a video via the binding, the returned
StreamVideoobject includes apreviewURL pointing at the user-facing server (e.g.http://localhost:8787/cdn-cgi/mf/stream/<id>/watch).When a browser or user code fetches this URL:
entry.worker.ts) matches the/cdn-cgi/mf/stream/prefix and dispatches to the stream binding service viastreamService.fetch(request)binding.worker.ts) parses the video ID from the URL, retrieves the blob from the Durable Object, and returns it as avideo/mp4responsePreview URL construction
The binding worker needs to construct full, externally-reachable preview URLs but runs inside workerd with no direct knowledge of the user-facing port. Preview URLs must also be stable across workerd runtime restarts (which happen on every code/config change during dev).
This is solved via a
/core/public-urlloopback route combined with apublicUrlconfig option on Miniflare:/core/public-urlloopback route that returns the configuredpublicUrl, falling back to the runtime entry URL if not set.publicUrlis also exposed as a mutable public field on theMiniflareinstance so it can be updated after construction (without restarting workerd).http://localhost:8787), constructed from the dev server config (hostname, port, secure) inLocalRuntimeController.miniflare.publicUrlafter the server starts listening so preview URLs reflect the actual port (handling Vite's port-bump behaviour when the configured port is taken).At request time, the binding worker fetches the loopback route to resolve the current public URL. Because this is a loopback request (not a static env binding), it always reflects the latest value — even after Vite bumps the port or workerd restarts.
To keep URL construction correct and consistent across consumers, Miniflare now exports two helper functions:
buildPublicUrl({ hostname, port, secure })— builds a client-reachable URL string for a local server.getLocallyAccessibleHost(host)— normalises a hostname for use in a client-reachable URL: maps wildcard listen addresses (0.0.0.0,::,*) to127.0.0.1, brackets IPv6 addresses (e.g.::1→[::1],fe80::1→[fe80::1]), and leaves hostnames and IPv4 addresses unchanged.Both Wrangler and the Vite plugin use
buildPublicUrlto construct thepublicUrlthey pass to Miniflare, so wildcard/IPv6 listen addresses produce valid, reachable URLs without any consumer having to re-implement the logic.A picture of a cute animal (not mandatory, but encouraged)
