Playback Domain
Manages live streaming channels and their origin configurations. A channel represents a named stream that can be distributed across one or more Castis Streamer nodes (origins). Each origin handles its own ingest and transcoding independently.
Handles:
- Channel CRUD
- Multi-origin fan-out (one channel → multiple streamer nodes)
- Live stream ingest config (UDP multicast, pl:///)
- Transcoding profile assignment per channel
- Playback URL generation per origin
- VOD playback (planned)
- CDN source type (planned)
Data Model
A Channel holds the global config. Each ChannelOrigin represents one streamer node assignment with its own ingest URL, stream ID, and generated playback URL.
erDiagram
Channel ||--o{ ChannelOrigin : "has many"
ChannelOrigin }o--|| Streamer : "targets"
Channel {
int id
int sid
string name
string quality
string sourceType
json ingestConfig
json transcodeConfig
}
ChannelOrigin {
int id
int channelId
int streamerId
string ingestUrl
string streamId
string playbackUrl
string status
}
Channel Creation Flow
sequenceDiagram
participant Client
participant CoreAPI
participant PostgreSQL
participant Streamer
Client->>CoreAPI: POST /channels
CoreAPI->>CoreAPI: Validate request
CoreAPI->>CoreAPI: BuildStreamID from name
CoreAPI->>PostgreSQL: Save Channel record
loop For each origin
CoreAPI->>PostgreSQL: Lookup Streamer by ID
CoreAPI->>CoreAPI: BuildPayload (merge ingest + transcode)
CoreAPI->>Streamer: POST /api/streams/:streamId
Streamer-->>CoreAPI: 200/201/500
CoreAPI->>PostgreSQL: Save ChannelOrigin + PlaybackURL
end
CoreAPI-->>Client: 201 { success, data, failures[] }
Partial success
If some origins succeed and others fail, the channel is still created. Failures are reported in the failures array in the response. Only if all origins fail is the channel rolled back and a 502 returned.
Streamer status 500
The Castis Streamer API returns 500 when a stream already exists. CoreAPI treats this as non-fatal and considers the origin active.
Stream ID Generation
Channel names are slugified into stream IDs:
"BBC World" → "bbc_world.stream" "CNN HD" → "cnn_hd.stream"
The stream ID is shared across all origins of the same channel.
Ingest Config
Two source types are supported via ingestConfig:
UDP Multicast — ingestUrl is merged with ingestConfig at payload build time:
{
"ingestConfig": {
"chunkDuration": "4000ms",
"fragmentDuration": "200ms",
"forceClean": true,
"netTimeout": "500ms"
},
"origins": [
{ "streamerId": 1, "ingestUrl": "udp://239.0.21.41:5000?fifo_size=1000000&overrun_nonfatal=1" }
]
}
pl:/// Loop — ingestConfig already contains the url field, ingestUrl in origins is ignored:
{
"ingestConfig": {
"url": "pl:///myloop"
}
}
Changelog
| Date | Author | Change |
|---|---|---|
| 2026-06-01 | Shida | Migrated StreamerClient to use StreamerNode, removed import cycle |
| 2026-05-28 | Shida | Multi-origin fan-out with partial failure handling |
| 2026-05-25 | Shida | BuildPayload — unified UDP and pl:/// ingest paths |
| 2026-05-22 | Shida | Initial channel CRUD and ChannelOrigin model |