ProjectsVideo infrastructure

Serverless video platform

Uploads, encoding, captions and signed playback with no servers to run

Example design

  1. 01Ask to uploadThe app asks the Worker for an upload URL. The Worker checks that this user may upload, and how much.
  2. 02Upload URLThe Worker asks Stream for a one-time direct upload URL with a maximum duration set for this user.
  3. 03Pending videoThe video is recorded in D1 as pending, with its owner and the limits that applied.
  4. 04UploadThe browser uploads straight to Stream over tus, which resumes after a dropped connection. The file never passes through the Worker.
  5. 05Webhook: readyWhen encoding finishes, Stream calls the Worker's webhook. The Worker checks the signature and asks Stream to generate captions.
  6. 06Mark readyD1 now says the video is ready. The app reads state from its own database and never polls Stream.
  7. 07PlayA viewer opens the video. The Worker checks access and returns a signed playback token that expires.
  8. 08Stream with tokenThe player fetches adaptive HLS or DASH from Stream. A copied link stops working when the token expires.
  9. ifAn upload goes over the limitThe upload URL carries a maximum duration, so Stream rejects a file that is longer than the user's allowance. The Worker never has to inspect the file.

The problem

A product team needs video in their app: some users upload, everyone else watches. Built on servers, that means an upload service, a transcoding farm, storage, a CDN contract and a player, with someone on call for all of it. Cloudflare Stream handles the encoding, storage and delivery. That leaves the work specific to the product: who can upload, who can watch, and what happens to a video between upload and publication.

What it uses

Stream
Encoding, storage, adaptive delivery, the player, and generated captions
Workers
The API: upload URLs, webhook handling, access checks and playback tokens
D1
Video records, ownership and state

The decisions, and why

Upload pathDirect creator upload over tus
Large files go from the browser to Stream. The Worker only issues a URL, so it handles no video bytes and has nothing to scale.
Upload limitMaximum duration per upload URL
Stream bills by minutes stored and minutes delivered, so the duration limit on each upload is also a cost limit.
Playback accessSigned tokens with a short expiry
Private videos need a token that the Worker issues after checking access. Public videos can skip this.
CaptionsGenerated, then reviewed
Stream generates captions in 12 languages. Anything published outside the company should be checked by a person first.
Source of truthD1, updated by webhook
The app answers every question about a video from its own database, which the webhook keeps current.

Limits to plan around

  • Caption generation covers 12 languages: Czech, Dutch, English, French, German, Italian, Japanese, Korean, Polish, Portuguese, Russian and Spanish.
  • A video has to finish encoding before captions can be generated, so captions arrive a little after the video is playable.

What you get

  • Worker API with upload, webhook and playback routes
  • D1 schema for videos, owners and limits
  • Player integration with signed playback
  • Caption generation and a review step
  • Tests for the access rules and the webhook
  • Runbook covering limits, costs and failure cases

Related product

Playback Signal: quality of experience telemetry from the player out.

Read about Playback Signal

Talk about your video project

Tell us what you are building, or what is not working in the platform you have.

Registered office
VI Data Services Ltd
128 City Road, London, EC1V 2NX, United Kingdom
Telephone

020 8058 7616

Company number

17420568
Registered in England and Wales