Streamline: custom video pipelines with Cloudflare Stream and Workers¶
Summary¶
Cloudflare released Streamline, an open-source developer playground that demonstrates how to build custom (bespoke) video pipelines on the Cloudflare Developer Platform by composing lower-level primitives — Containers (long-lived media processing), Durable Objects (orchestration + preview relay), and Workers (control signaling + monitoring) — around the managed Cloudflare Stream product. The design pulls RTMPS or HLS input from Stream, applies FFmpeg-based operations (overlay, subtitle burn-in, filter, encode), and publishes the result back as a livestream or hosted video, with a low-latency WebSocket preview path. The headline architectural lesson is a control-plane / data-plane split: a media-processing session's lifecycle is decoupled from the request that started it — the Container keeps processing even after the controlling Worker disconnects — which is the right shape for minutes-to-hours media jobs that must outlive any single HTTP request.
Key takeaways¶
- Primitive composition over a monolith. Streamline deliberately splits into a Media Engine (media I/O + processing, hosted in a Container) and a controlling Application (creates, configures, observes, stops sessions, built on Workers). The Media Engine is itself split into a Controller (a Go HTTP control harness) and a Processor (currently FFmpeg, treated as an internal implementation detail not exposed in the user-facing API). (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers)
- Request-independent session lifecycle. "Video streams can run for minutes or hours, so the media process needs a lifecycle independent of the request that started it." The controlling Worker can disconnect and reconnect safely while the Container keeps processing — a canonical control/data-plane shape where control signaling (Worker) and the long-running data path (Container media engine) scale and fail independently. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers)
- Container never sleeps mid-pipeline, but is bounded. Cloudflare Containers
auto-sleep after an idle interval, which is wrong for an in-flight pipeline.
Streamline overrides the
onActivityExpired()callback to renew the activity timeout while a relay session is live and onlydestroy()the container once expired — but it also enforces a maximum session duration so a session is always eventually closed and can't run indefinitely without external control. This is a TTL-bounded resource with activity-based renewal. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers) - Durable Object as orchestrator + preview relay. The Orchestrator is
implemented by a Durable Object that
coordinates the session, the Container lifecycle, and the preview relay. The
Container publishes fMP4 fragments over an outbound WebSocket to the DO,
which forwards them to a relay reachable at
/relay/viewover a client WebSocket. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers) - Multi-protocol media I/O. The Media Engine can pull RTMPS playback from
a Stream Live input and publish RTMPS to another; pull a Cloudflare Stream
HLS manifest + segments to use hosted videos as input; accept
application-supplied input (e.g. a webcam, via
session.ingest(chunk)); and publish preview video over an outbound WebSocket as fMP4. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers) - Session-based API as an abstraction boundary. Streamline exports
@cloudflare/streamline/client(a high-level session API —sessions.create(),sessions.resume(id),start(config),ingest(chunk),annotation(png),metrics(),stop()) over the low-level Go HTTP server + DO interface, "so the system is as agnostic as possible to who or what is controlling the session." Controllers can be a browser app, an agent, or an embedded system. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers) - Declarative pipeline config.
session.start(config)takes a JSON object:{ input, pipeline: [ops], output }. Supported ops are a fixed set —filter(blur/saturation/brightness/flip),overlay(static image or a live-updatable PNGannotation),subtitle(burn-in, incl. HLS closed captions),encode(codec/preset/bitrate/resolution/fps/gop). Operation order is fixed by the engine regardless of array order. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers) - Security designed in, not bolted on. Owner deployment is private behind Workers Access integration; the Worker verifies the Access session and binds the active session to the verified principal; only one session runs at a time and a different principal cannot stop/replace it. Stream Live Input (RTMPS) keys are treated as secrets — stored in Worker secrets or write-only DO storage, never returned by the settings API or placed in browser storage. The controlling app refers to inputs/outputs by a named profile; the Worker resolves the profile before contacting the container, so RTMPS keys never leak to the controlling application. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers)
- Two-credential preview auth with staged rollout. The preview stream uses a Cloudflare Access service token (authenticates the container workload to the publisher endpoint, injected by the container's outbound Worker and never enters container memory) plus a random per-session capability (authorizes publishing only for the currently-active relay). The initial deploy uses a temporary path-specific Access Bypass, then after a successful smoke test the rollout replaces Bypass with Service Auth — a staged auth cutover. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers)
- Client-side backpressure on the preview path. "A production MediaSource
player must queue fragments while
SourceBuffer.updatingis true." The browser consumer must buffer incoming fMP4 fragments rather than appending blindly — a concrete backpressure instance at the media-playback edge. (Source: sources/2026-10-02-cloudflare-streamline-custom-video-pipelines-with-cloudflare-stream-and-workers)
Architecture extracted¶
Controlling Application (Workers) Media Engine (Container)
┌─────────────────────────────┐ ┌──────────────────────────┐
│ UI / agent / embedded client │ │ Controller (Go HTTP srv) │
│ @cloudflare/streamline/client│──control(API)──▶│ → ops │
│ │ │ Processor (FFmpeg) │
│ Orchestrator = Durable Object│◀── fMP4 WS ─────│ filter/overlay/ │
│ session + container │ (preview) │ subtitle/encode │
│ lifecycle + preview relay │ └──────────┬───────────────┘
└──────────────┬───────────────┘ │
/relay/view (client WS) RTMPS/HLS in ◀┘ RTMPS/WS out
▼ ▼
browser MediaSource Cloudflare Stream (Live)
- Control plane: Worker (control signaling, monitoring, Access verification, profile → RTMPS-key resolution) + Durable Object (session + container lifecycle
- preview relay). Data plane: the Container media engine moving RTMPS/HLS/ WebSocket media bytes.
- Input modes:
rtmp/rtmps(from a Stream Live input),hls(a Stream videomanifest/video.m3u8),webcam(application-ingested chunks viasession.ingest()). - Output modes:
rtmp/rtmps(to a Stream Live input for broadcast/record),websocket(fMP4 preview via the DO relay). - Local vs remote: in local dev the Container is a local Docker instance, the DO is not used, there is a single unauthenticated user, and preview connects directly to a localhost WebSocket. In remote deployment the DO orchestrates and Access enforces identity.
Operational numbers / details¶
- Supported pipeline operations: 4 (
filter,overlay,subtitle,encode), applied in a fixed engine-defined order. - Preview fragment format: fMP4; delivered over WebSocket via the DO relay at
/relay/view. - Example encode params in the post:
h264, presetsfast/veryfast,1500kbitrate,1280x720,30 fps,gop: 60. - Public playground limits (per the post): one container identity per verified user, one active session per user, plus global admission control, concurrency, media, and session limits; no user can replace another's session.
- Known bottleneck: "Streamline uses Container CPU for media processing, which introduces a bottleneck at higher qualities or frame-rates."
Caveats¶
- Developer-playground / reference architecture, not a managed product. This is an open-source demonstration of how to compose primitives, explicitly modular so the media engine "could be replaced with dedicated encoding products in the future." No production SLOs, throughput numbers, concurrency ceilings, or latency distributions are disclosed.
- CPU-bound processing is the named scaling limit; no GPU/hardware acceleration today. Forward work named (not shipped): computer-vision pipelines, hardware-accelerated media processing, realtime next-gen protocols (WebRTC, MoQ), and native video encode/decode primitives in Workers.
- The owner deployment's singleton, single-active-session security model is explicitly not the model for a public multi-user service — the post calls this out directly; the public playground uses a different per-user model.
- FFmpeg as the processor is "an internal implementation detail rather than part of the user-facing API" — the public contract is the op set, not FFmpeg flags.
Source¶
- Original: https://blog.cloudflare.com/streamline/
- Raw markdown:
raw/cloudflare/2026-10-02-streamline-custom-video-pipelines-with-cloudflare-stream-and-2464ff1b.md
Related¶
- systems/cloudflare-streamline — the subject system
- systems/cloudflare-stream — the managed video product Streamline composes with
- systems/cloudflare-containers — long-lived media-engine runtime
- systems/cloudflare-durable-objects — orchestrator + preview relay
- systems/cloudflare-workers — control signaling + monitoring
- systems/cloudflare-websockets — fMP4 preview transport
- systems/ffmpeg — the (internal) media processor
- concepts/control-plane-data-plane-separation — the core architectural shape
- concepts/video-transcoding — the data-plane operation
- concepts/backpressure — MediaSource/SourceBuffer client-side queueing
- companies/cloudflare — operator