Skip to content

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 MulticastingestUrl 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:/// LoopingestConfig 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