Cloudflare.Stream reference
LiveInput
Section titled “LiveInput”Source:
src/Cloudflare/Stream/LiveInput.ts
A Cloudflare Stream live input — an ingest endpoint (RTMPS/SRT/WebRTC) that accepts live video and optionally records it as a Stream video.
Live inputs are identified by an auto-assigned uid; every prop is
mutable in place via Cloudflare’s PUT endpoint, so the resource is
never replaced. Deleting a live input does not delete videos already
recorded from it.
Requires the Stream subscription to be enabled on the account.
LiveInput: Creating a live input
Section titled “LiveInput: Creating a live input”Basic live input
const input = yield* Cloudflare.Stream.LiveInput("Broadcast", {});Live input with automatic recording
const input = yield* Cloudflare.Stream.LiveInput("Broadcast", { meta: { name: "town-hall" }, recording: { mode: "automatic", timeoutSeconds: 10, }, deleteRecordingAfterDays: 30,});LiveInput: Managing a live input
Section titled “LiveInput: Managing a live input”const input = yield* Cloudflare.Stream.LiveInput("Broadcast", { enabled: false,});LiveInputOutput
Section titled “LiveInputOutput”Source:
src/Cloudflare/Stream/LiveInputOutput.ts
A Cloudflare Stream live input output — restreams (simulcasts) live
video received by a LiveInput to another RTMP(S) destination
such as YouTube Live or Twitch.
The destination (url + streamKey) is immutable: Cloudflare’s update
endpoint only toggles enabled, so changing the destination replaces
the output. Toggling enabled updates the output in place.
Requires the Stream subscription to be enabled on the account.
LiveInputOutput: Creating an output
Section titled “LiveInputOutput: Creating an output”const input = yield* Cloudflare.Stream.LiveInput("Broadcast", {});
const youtube = yield* Cloudflare.Stream.LiveInputOutput("YouTube", { liveInputId: input.liveInputId, url: "rtmps://a.rtmps.youtube.com/live2", streamKey: youtubeStreamKey,});LiveInputOutput: Managing an output
Section titled “LiveInputOutput: Managing an output”const youtube = yield* Cloudflare.Stream.LiveInputOutput("YouTube", { liveInputId: input.liveInputId, url: "rtmps://a.rtmps.youtube.com/live2", streamKey: youtubeStreamKey, enabled: false,});SigningKey
Section titled “SigningKey”Source:
src/Cloudflare/Stream/SigningKey.ts
A Cloudflare Stream signing key — an RSA key pair used to sign viewer playback tokens for videos that require signed URLs.
The key material (pem/jwk) is returned by Cloudflare only at
creation time; it is persisted as redacted attributes in state and
can never be re-read from the API. If the key is deleted out-of-band,
reconcile creates a brand-new key with new material — anything derived
from the old key (signed tokens) must be re-derived from the new
attributes.
Requires the Stream subscription to be enabled on the account.
SigningKey: Creating a signing key
Section titled “SigningKey: Creating a signing key”const key = yield* Cloudflare.Stream.SigningKey("PlaybackKey", {});
// key.pem / key.jwk are Redacted<string> — use them server-side to// sign playback tokens for videos with requireSignedURLs enabled.const pem = key.pem;Stream
Section titled “Stream”Source:
src/Cloudflare/Stream/Stream.ts
A Cloudflare Stream binding for managing videos, captions, downloads and watermarks from Workers — a Worker-only binding with no backing cloud resource.
Stream is a single value that is at once the Binding.Service tag, the
callable that produces a StreamBinding, and the type. Declare it on a
Worker’s env (it flows through InferEnv → the runtime StreamBinding
handle) or yield* it inside an Effect-native Worker to attach the binding
and obtain the StreamClient.
In alchemy dev the binding is emulated locally: uploads land in a local
video store and each video’s preview URL is served unmodified at
{devUrl}/cdn-cgi/mf/stream/<id>/watch. The local store performs no
transcoding (the hlsPlaybackUrl/dashPlaybackUrl point at a placeholder
host), no signed URLs, and createDirectUpload is unsupported. Pipe the
binding through Alchemy.remote() to proxy to the real Stream service
instead.
Stream: Effect-style Worker (recommended)
Section titled “Stream: Effect-style Worker (recommended)”import * as Effect from "effect/Effect";
Cloudflare.Worker( "StreamWorker", { main: import.meta.url }, Effect.gen(function* () { const stream = yield* Cloudflare.Stream.Stream("STREAM");
return { fetch: Effect.gen(function* () { const video = yield* stream.upload("https://example.com/video.mp4"); const details = yield* stream.video(video.id).details(); return yield* HttpServerResponse.json(details); }), }; }).pipe(Effect.provide(Cloudflare.Stream.StreamBinding)),);Stream: Worker binding metadata
Section titled “Stream: Worker binding metadata”export const Worker = Cloudflare.Worker("Worker", { main: "./src/worker.ts", env: { STREAM: Cloudflare.Stream.Stream() },});
export type WorkerEnv = Cloudflare.InferEnv<typeof Worker>;// { STREAM: StreamBinding }Stream: Local development
Section titled “Stream: Local development”// Default: videos land in the local video store under `alchemy dev`.// Alchemy.remote() opts the binding into the real Stream service// instead — in an Effect-native Worker:const stream = yield* Cloudflare.Stream.Stream("STREAM").pipe(Alchemy.remote());
// or declared on an async Worker's env:env: { STREAM: Cloudflare.Stream.Stream("STREAM").pipe(Alchemy.remote()) }Watermark
Section titled “Watermark”Source:
src/Cloudflare/Stream/Watermark.ts
A Cloudflare Stream watermark profile — a PNG image stamped onto videos at upload time.
Watermark profiles are create-only: Cloudflare exposes no update endpoint, so every prop change triggers a replacement (a new profile is created and the old one deleted). The image is downloaded by Cloudflare from the given URL at creation time.
Requires the Stream subscription to be enabled on the account.
Watermark: Creating a watermark
Section titled “Watermark: Creating a watermark”Default watermark from an image URL
const watermark = yield* Cloudflare.Stream.Watermark("Logo", { url: "https://example.com/logo.png",});Centered semi-transparent watermark
const watermark = yield* Cloudflare.Stream.Watermark("Logo", { url: "https://example.com/logo.png", position: "center", opacity: 0.5, scale: 0.3,});Webhook
Section titled “Webhook”Source:
src/Cloudflare/Stream/Webhook.ts
The Cloudflare Stream webhook — an account-level singleton that receives notifications when videos finish processing or live inputs connect/disconnect.
Each account has at most one Stream webhook, so creating this
resource takes over the account’s webhook slot; an existing webhook
configured outside Alchemy is only adopted when --adopt is set.
Destroying the resource deletes the webhook configuration.
Requires the Stream subscription to be enabled on the account.
Webhook: Configuring the webhook
Section titled “Webhook: Configuring the webhook”const webhook = yield* Cloudflare.Stream.Webhook("Notifications", { notificationUrl: "https://example.com/hooks/stream",});
// Verify the Webhook-Signature header with the HMAC secret:const secret = webhook.secret; // Redacted<string>