Skip to content

Distribution

The distribution domain manages CDN infrastructure nodes — Castis Streamer nodes, cproxy edge caches, and the colorbars UDP broadcaster. It also tracks the topology between them.

API base: /api/distribution/
Pages: /streamers, /streamers/:id, /streamers/new, /streamers/:id/edit, /caches, /caches/:id, /caches/new, /caches/:id/edit


Concepts

Streamer — a Castis Streamer node that ingests UDP/file sources and serves HLS/DASH
Cache — a cproxy edge cache node that sits in front of streamers
Origin key — a named routing slot on cproxy (e.g. food, ads) with a URL pattern
host — internal Docker DNS name used for CoreAPI → node communication (e.g. streamer_bkk)
publicHost — browser-accessible address used to build playback URLs (e.g. localhost)
Sync — pushing DB state to cproxy runtime config via PUT /api/config/origins

Node topology

Channel → ChannelOrigin → Streamer → CacheOriginStreamer → CacheOriginKey → Cache (cproxy)

Testing Distribution

Streamers — /streamers

Navigate to http://localhost:15173/streamers.

  • Table lists all registered streamer nodes with host, ports, GPU flag, and status
  • Ping — calls GET /api/ping on the node and updates status to online/offline
  • Edit — opens edit form
  • Click row → streamer detail page

Streamer list Streamer list with ping button and status indicators


Streamer detail — /streamers/:id

Shows: - Node info (host, publicHost, ports, GPU, last pinged) - Channels — all channels whose origins include this streamer - Cache assignments — all cproxy origin keys this streamer feeds into

Streamer detail Streamer detail showing hosted channels and cache assignments


Register a new streamer — /streamers/new

Fields: - Name — unique display name (e.g. streamer-bkk) - Host — Docker internal service name (e.g. streamer_bkk) — used for CoreAPI → Streamer API calls - Public host — browser-accessible hostname (e.g. localhost) — used to build playback URLs - HTTP port — streaming port (host-mapped for local nodes, e.g. 18080) - API port — management API port (e.g. 18081) - GPU — toggle if node has NVIDIA GPU for NVENC transcoding

host vs publicHost

For local Docker compose nodes: host = streamer_bkk, publicHost = localhost.
For staging on-prem nodes: host == publicHost = stg-onprem-main.cdn.3bbtv.com.


Caches — /caches

Navigate to http://localhost:15173/caches.

  • Table lists all cproxy nodes with host, ports, number of origin keys, and status
  • Ping — calls GET /api/version on cproxy and updates status
  • Click row → cache detail page

Cache list Cache list with origin key count


Cache detail — /caches/:id

Shows node info and the Origin Keys section for managing cproxy routing.

Cache detail Cache detail with origin keys and sync button

Add an origin key

  1. Click + Add key
  2. Fill in:
  3. Key name — routing slot name (e.g. food)
  4. URL pattern — regex matching incoming paths (e.g. ^/food/.*$)
  5. Rewrite match — strip prefix before forwarding (e.g. ^/food/(.*)$)
  6. Rewrite replace — replacement (e.g. /$1)
  7. TTL — cache duration (e.g. 1s)
  8. Priority — order in origins array (lower = matched first)
  9. Click Create key

Assign streamers to a key

Within each key row:

  1. Click + Add streamer
  2. Enter the streamer ID (find it at /streamers)
  3. Click Add
  4. First added = priority 0 (primary), second = priority 1 (failover)

To remove a streamer from a key, click next to the streamer name.

Sync to cproxy

After adding keys and assigning streamers, click ⚡ Sync to cproxy.

This calls POST /caches/:id/keys/sync which: 1. Reads all CacheOriginKey rows for this cache from DB 2. Builds the cproxy origins array JSON 3. Calls PUT /api/config/origins on cproxy 4. cproxy applies the config and writes it back to cproxy.yml on disk

The placeholder origin is replaced entirely. Config survives container restarts.


Full distribution test flow

# 1. Verify streamers are seeded
curl -s http://localhost:3000/api/v1/distribution/streamers | jq '.data[] | {id, name, status}'

# 2. Ping streamer-bkk (id=5)
curl -s -X POST http://localhost:3000/api/v1/distribution/streamers/5/ping | jq .

# 3. Check cproxy starts with placeholder
curl -s http://localhost:28081/api/config | jq '.origins[] | .key'
# → "placeholder"

# 4. Go to /caches/1 in UI
#    → Add key "food" with pattern ^/food/.*$
#    → Assign streamer-bkk (id=5) as primary
#    → Assign streamer-ntb (id=6) as failover
#    → Click ⚡ Sync to cproxy

# 5. Verify cproxy config updated
curl -s http://localhost:28081/api/config | jq '.origins[] | {key, urlPattern, originUrls}'

# 6. Test routing through cproxy
#    (requires a stream or VOD file to exist on the streamer)
curl -I http://localhost:28080/food/kitchen.mp4

# 7. Check streamer topology
curl -s http://localhost:3000/api/v1/distribution/streamers/5/channels | jq .
curl -s http://localhost:3000/api/v1/distribution/streamers/5/caches | jq .

Colorbars — UDP broadcast simulator

The colorbars container at http://localhost:9999 runs ffmpeg subprocesses that broadcast SMPTE colorbars as MPEG-TS over UDP multicast. Use it to simulate a live UDP signal for channel creation and probe testing.

# create a colorbar stream
curl -X POST http://localhost:3000/api/v1/distribution/colorbars/streams \
  -H "Content-Type: application/json" \
  -d '{"id":"test1","multicastIp":"239.0.0.8","port":4444}'

# start broadcasting
curl -X POST http://localhost:3000/api/v1/distribution/colorbars/streams/test1/start

# probe from streamer-bkk — should detect signal
curl -X POST http://localhost:3000/api/v1/distribution/streamers/5/probe \
  -H "Content-Type: application/json" \
  -d '{"udp":"239.0.0.8","port":4444}'

# stop
curl -X POST http://localhost:3000/api/v1/distribution/colorbars/streams/test1/stop

Port constraint

Each colorbar stream must use a unique port. Two streams sharing a port — even on different multicast IPs — will interfere because Castis Streamer binds on port when joining a multicast group.


Key API Endpoints

GET/POST   /api/distribution/streamers
GET/PUT    /api/distribution/streamers/:id
POST       /api/distribution/streamers/:id/ping
POST       /api/distribution/streamers/:id/probe
GET        /api/distribution/streamers/:id/channels
GET        /api/distribution/streamers/:id/caches

GET/POST   /api/distribution/caches
GET/PUT    /api/distribution/caches/:id
POST       /api/distribution/caches/:id/ping
GET/POST   /api/distribution/caches/:id/keys
PUT/DELETE /api/distribution/caches/:id/keys/:keyId
POST       /api/distribution/caches/:id/keys/:keyId/streamers
DELETE     /api/distribution/caches/:id/keys/:keyId/streamers/:streamerId
POST       /api/distribution/caches/:id/keys/sync