Rend is the video platform for developers: one API call to upload, one playback URL that starts fast. Encoding, storage, delivery, signed playback, analytics, player packages, and SDKs are handled by one open-source stack.
Rend currently serves generated HLS from Tigris-backed origin through Rend-controlled playback URLs, so playback can start without exposing private storage URLs. The bare-metal edge path remains in the repo, but it is dormant in production until regional coverage makes it worthwhile.
Rend is built around startup latency, especially the first request for a video that has not already been watched and cached everywhere.
- Minimize time to first frame, not just server response time.
- Generate a small opener during media processing so real frames can be served before the full HLS ladder is ready.
- Serve generated HLS from Tigris-backed origin by default while the bare-metal edge path stays dormant until regional coverage makes it worthwhile again.
- Keep playback credentials server-controlled: signed playback is validated before private origin artifacts are streamed, without exposing storage URLs.
- Measure the path with readiness and benchmark scripts covering upload response time, upload-to-playable timings, playback bootstrap latency, origin TTFB, optional edge cache behavior, and telemetry visibility.
apps/site/- Next.js app for the public site, docs, dashboard, auth, billing, and player-facing routes.services/rend-api/- Rust API/control plane for uploads, asset state, media jobs, playback bootstrap, Tigris-origin playback, optional edge registry, telemetry ingest, and billing hooks.services/rend-edge/- Rust playback edge for signed playback validation, cache warm/purge, origin-backed cache fill/coalescing, and playback telemetry flushing. This code is currently dormant in production unlessREND_PLAYBACK_MODE=edgeis explicitly enabled.rend-media-worker- therend-apibinary running asworker media; claims queued media jobs and writes playback artifacts withffmpeg/ffprobe.packages/player/- React/HLS player package.packages/sdk/- generated TypeScript public API client.migrations/andclickhouse/- Postgres and ClickHouse schema.compose.yml- local Postgres, Redis, MinIO, ClickHouse, API, worker, and edge stack.
The local stack currently covers upload, queued media processing, source and playback artifact storage, HLS/openers/thumbnails, signed playback bootstrap, Tigris-origin playback, optional edge cache warm/purge/coalescing, API keys, dashboard asset management, billing checks, and a generated public SDK.
- Bun
>=1.3.6 - Node.js
>=20 - Rust
1.93 - Docker with Compose
ffmpegandffprobewhen running the media worker outside Docker
Some smoke scripts also expect common CLI tools such as curl and jq.
cp .env.local.example .env.local
bun install
bun devbun dev validates the local env, starts the Docker backend, and runs the site.
The default local URLs are:
- Site: http://localhost:3000
- API: http://127.0.0.1:4000
- Edge: http://127.0.0.1:4100
- MinIO console: http://127.0.0.1:9101
Useful local commands:
bun run dev:site # site only, assuming backend is already up
bun run backend:docker:build # rebuild local backend images
bun run backend:docker:up # start backend stack and wait for health
bun run backend:down # stop local stackTo run the Rust services on the host instead of the Docker service containers, keep the local dependencies running and start each service in its own terminal:
bun run backend:api
bun run backend:media-worker
bun run backend:edgeCommon checks:
bun run env:local
bun run typecheck
bun run --cwd apps/site test
cargo fmt --all -- --check
cargo check --workspace
cargo test --workspace
bun run openapi:check
bun run openapi:contract
bun run openapi:sdk-testRepresentative end-to-end checks:
bun run backend:docker:smoke
bun run backend:smoke:async-media
bun run backend:smoke:playback-bootstrap
bun run backend:smoke:playback-telemetry
bun run backend:smoke:delete-purge
bun run sdk:integration-smoke
bun run e2e:site-assetsSee package.json for the full script list.
The public API contract lives at
docs/openapi/rend-public-api.openapi.json.
The generated TypeScript client lives in packages/sdk/.
bun run openapi:lint
bun run openapi:generate
bun run openapi:checkdocs/env/profiles.md- local vs production env loading and validation.docs/deployment-v1.md- service topology, Docker targets, and production env surface.docs/edge-host-runbook-v1.md- edge host operations.docs/billing-autumn-v1.md- Autumn billing model and launch checks.docs/launch-gate-v1.md- public V1 launch gate modes, artifacts, and triage.docs/release-images-v1.md- release image build and verification flow.
For production-profile validation:
cp .env.production.example .env.production.local
bun run env:production
bun run verify:production-localFor a public V1 candidate:
bun run launch:gateThe Rust server workspace is AGPL-3.0-or-later. The player and SDK packages are MIT.