Skip to content

Streamer

Castis Streamer serves DASH and HLS manifests and segments from VOD files or live .stream playlists. PlayTelly runs two streamer instances: streamer_bkk and streamer_ntb.

Compose

streamer_bkk:
  build: ./cdn/streamer
  platform: linux/amd64
  container_name: streamer_bkk
  depends_on:
    seaweedfs:
      condition: service_healthy
  networks:
    - internal
    - cdn_net
  ports:
    - "18080:18080"   # streaming
    - "18081:18081"   # api
  volumes:
    - ./cdn/streamer-bkk/streamer.yml:/config/streamer.yml:ro
    - ./cdn/streamer-bkk/doc-root:/data/doc-root
    - ./cdn/streamer-bkk/stream-root:/data/stream-root
    - ./cdn/streamer-bkk/streamer-db:/data/streamerdb
    - ./cdn/streamer-bkk/logs:/var/log/castis/streamer

streamer_ntb uses the same image with ports 19080/19081.

Volume Reference

Host path Container path Purpose
streamer.yml /config/streamer.yml Config (read-only)
doc-root/ /data/doc-root/ Local VOD files — checked before http-remote
stream-root/ /data/stream-root/ .stream loop playlist files
streamer-db/ /data/streamerdb/ Internal state DB (mdbx) — persist across restarts
logs/ /var/log/castis/streamer/ Log output

Key Config

listen-addresses:
  - address: :18080

api-listen-addresses:
  - address: :18081
    accept-url-pattern: .*

doc-roots:
  - dir: /data/doc-root

stream-root: /data/stream-root
local-db-dir: /data/streamerdb

http-remote:
  url: http://seaweedfs:8333/playtelly   # S3 bucket prefix baked in
  default-read-size: 2m

chunk:
  vod:
    chunk-duration: 3s
  live:
    chunk-duration: 3s
    max-chunk-count: 20
    playlist-chunk-count: 8

SeaweedFS Integration via http-remote

Streamer's content lookup order per request:

doc-root (local disk) → http-remote (SeaweedFS) → 404

http-remote.url is set to http://seaweedfs:8333/playtelly — the /playtelly bucket prefix is baked into the URL so client-facing paths don't include it:

# client requests
GET /ads/materials/jet.mp4/fmp4.noll_manifest.mpd

# streamer fetches internally
http://seaweedfs:8333/playtelly/ads/materials/jet.mp4

SeaweedFS must have an anonymous identity with Read and List actions in seaweedfs_s3.json for unauthenticated reads from Streamer:

{
  "name": "anonymous",
  "credentials": [],
  "actions": ["Read", "List"]
}

Providers

The first path segment is matched against defined providers. If no provider matches, global chunk config is used. PlayTelly does not define explicit providers — all paths fall through to global defaults.

API

# version
curl http://localhost:18081/api/version

# current config
curl http://localhost:18081/api/config

# traffic stats
curl http://localhost:18081/api/traffic

Manifest URL Pattern

http://streamer_bkk:18080/<path>/<file>.mp4/fmp4.noll_manifest.mpd   # DASH
http://streamer_bkk:18080/<path>/<file>.mp4/fmp4.noll_playlist.m3u8  # HLS