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