Videos
Videos are an automatic specialization of files stored in Cloudflare Stream, keyed 1:1 by file id.
Videos are an automatic specialization of files. Every video is backed by a regular file row — there is no separate video id. When you upload a file with a video/* MIME type, an event handler copies the bytes into Cloudflare Stream and inserts a 1
Storage model
Videos live in Cloudflare Stream, not in the workspace R2 bucket. The video row records:
fileId— the primary key, matches the file row idcfStreamUid— the Cloudflare Stream UID returned from the copy-from-URL callduration,width,height,size,metadatatranscodingStatus—queued,processing,ready, orerrorworkspaceId— the workspace the video belongs to
Creating a video
You don't create videos directly — just upload a file. On file.ready with a video/* MIME, the runtime emits video.provision_requested; a handler tells Cloudflare Stream to pull the bytes from a signed R2 URL, inserts the video side-table row (transcoding processing), and emits video.created. Transcoding then runs on Cloudflare's side asynchronously.
The API lazy-reconciles processing status against CF Stream on each GET /api/videos/:file_id call, so simply polling the video is enough — no separate status endpoint, no webhook to wire up. On the first terminal transition, the reconciler emits video.ready or video.error so downstream handlers can react.
Playback
Every video exposes two derived URLs at read time:
playbackUrl— an HLS manifest (.m3u8)thumbnailUrl— an auto-generated JPG thumbnail
The platform renders video with @cloudflare/stream-react — a thin <Stream> component that wraps the upstream Cloudflare Stream player and handles adaptive bitrate, buffering, and picture-in-picture for you.
Operations
GET /api/videos— list videos, filter byworkspace_idGET /api/videos/:file_id— retrieve a single video by file id (lazy-reconciles processing status)DELETE /api/videos/:file_id— delete the video side table row and cascade into the underlying file
All three operations are also available via the CLI ( aeontel video list/get/delete), the MCP server ( list_videos, get_video, delete_video), and the React hooks ( useListVideos, useRetrieveVideo, useDeleteVideo). There is no create_video — upload a file with a video/* MIME and the video row is created automatically.