CastCaster
Unified live streaming management platform.
Manage RTMP/HLS streaming with Nginx, per-channel FFmpeg tasks, and Docker-based deployment. Each channel spawns independent containers for relay, adaptive transcoding, snapshot, or test — isolated and scalable.
Quick Start
# Install and initialize
gem install castcaster
castcaster init
# Add a test channel
castcaster channel add --name demo
# Generate compose.yml and start
castcaster deploy
docker compose up -d
Open http://localhost:8080/channel/demo — click play to see timestamp video.
Source Types
# Test — internal test stream (default)
castcaster channel add --name demo
# Pull — relay from external RTMP source
castcaster channel add --name relay --source-type rtmp_pull --source rtmp://example.com/live/stream
# Pull + adaptive transcoding
castcaster channel add --name news \
--source-type rtmp_pull \
--source rtmp://example.com/live/stream \
--transcode 720p,480p
# Pull + snapshot
castcaster channel add --name camera \
--source-type http_pull \
--source http://example.com/stream \
--snapshot 5
# Push — external OBS/FFmpeg pushes to CastCaster
castcaster channel add --name mychannel --source-type rtmp_push
# OBS: rtmp://host:1935/live/mychannel
Architecture
Browser───:80 ──→ Traefik (optional) ──→ nginx :8080
│ ├── /hls/live/* → HLS segments
│ ├── /api/* → proxy → webui:8081
│ ├── / → proxy → webui:8081
│ └── RTMP :1935 → RTMP ingest
│
└── :443 (HTTPS, via Let's Encrypt)
FFmpeg containers (per channel):
test-<name> → teststream.sh (internal test pattern)
relay-<name> → relay.sh (RTMP/HTTP pull relay)
adaptive-<name>→ adaptive.sh (multi-bitrate transcode)
snapshot-<name>→ snapshot.sh (periodic thumbnail)
Requirements
- Ruby >= 3.0
- Docker + Docker Compose (v2)
Docker Images
| Image | Source | Purpose |
|---|---|---|
ghcr.io/lax/castcaster-nginx |
Local build | Nginx (RTMP + HLS + proxy) |
ghcr.io/lax/castcaster-webui |
Local build | Web management UI |
ghcr.io/lax/castcaster-ffmpeg |
Local build | FFmpeg relay/transcode/snapshot |
traefik:v3.0 |
Docker Hub | Reverse proxy + SSL (optional) |
Commands
init
Initialize project in current directory.
castcaster init
Creates: castcaster.yml, castcaster.token, channels/, hls/, logs/, data/.
channel add
Default is test — generates a timestamp video with zero external dependencies.
# Test — internal test stream
castcaster channel add --name demo
# Pull — relay from external RTMP source
castcaster channel add --name relay \
--source-type rtmp_pull \
--source rtmp://example.com/live/stream
# Pull — relay from HTTP source
castcaster channel add --name radio \
--source-type http_pull \
--source http://example.com/stream
# Pull + adaptive transcoding
castcaster channel add --name news \
--source-type http_pull \
--source http://example.com/stream \
--transcode 720p,480p,360p
# Pull + snapshot
castcaster channel add --name camera \
--source-type http_pull \
--source http://example.com/stream \
--snapshot 5
# Push — external OBS/FFmpeg pushes to CastCaster
castcaster channel add --name mychannel --source-type rtmp_push
# OBS: rtmp://host:1935/live/mychannel
channel list / start / stop / rm / update
castcaster channel list
castcaster channel start news
castcaster channel stop news
castcaster channel rm radio
castcaster channel update news --source-type rtmp_pull --source rtmp://example.com/new
config
Preview generated nginx config.
castcaster config
deploy
Generate compose.yml (and optional Traefik config).
castcaster deploy # Docker Compose (default)
castcaster deploy --with-traefik # + Traefik SSL
castcaster deploy --mode swarm # Docker Swarm
doctor
Check system environment.
Ruby ruby 3.4.1
Docker Docker version 28.4.0
Compose Docker Compose version v2.39.3
nginx available
ffmpeg available
webui available
config.yml ok (engine: nginx-rtmp)
Channel Tasks
Each channel spawns independent containers based on config:
| Task | Container Name | Trigger | Description |
|---|---|---|---|
| Test | castcaster-test-<name> |
test (default) |
Internal timestamp video |
| Relay | castcaster-relay-<name> |
rtmp_pull / http_pull / srt |
Relay external source → nginx |
| Adaptive | castcaster-adaptive-<name> |
--transcode |
Multi-bitrate transcoding (replaces relay) |
| Snapshot | castcaster-snapshot-<name> |
--snapshot |
Periodic thumbnail capture |
| (none) | — | rtmp_push |
OBS/FFmpeg pushes directly, no container |
Containers are tagged with Docker labels:
labels:
"castcaster/channel": "news"
"castcaster/task": "adaptive"
Transcode Presets
| Profile | Bitrate | Resolution | Audio |
|---|---|---|---|
| 360p | 512k | 640×360 | 64k |
| 480p | 1024k | 854×480 | 96k |
| 576p | 1248k | 1024×576 | 96k |
| 720p | 2048k | 1280×720 | 128k |
| 1080p | 3000k | 1920×1080 | 128k |
Web Management UI
http://localhost:8080
- Dashboard — channel list with task status
- Channel page — hls.js player, RTMP/HLS connection info, click-to-copy
- REST API —
GET /api/channels,GET /api/status
Note: Start/stop actions are managed via CLI (
castcaster channel start/stop) for security reasons.
Configuration
# castcaster.yml
engine: nginx-rtmp
hls_fragment: 6
hls_window: 60
domain: stream.example.com # for Traefik SSL
acme_email: admin@example.com
enable_traefik: false
Deployment Modes
Docker Compose (default)
castcaster deploy
docker compose up -d
Docker Compose + Traefik
castcaster deploy --with-traefik
docker compose up -d
Traefik provides Let’s Encrypt HTTPS, sits in front of nginx.
Docker Swarm
castcaster deploy --mode swarm
docker stack deploy -c docker-stack.yml castcaster
Development
| Branch | Description |
|---|---|
dev |
Active development |
main |
Product release branch |
Docker-based development (recommended)
Only Docker needed — no Ruby installation required:
# Build CLI image
make cli-build
# Create and start a test project
make dev TARGET=/tmp/my-project
# View logs
make dev-logs TARGET=/tmp/my-project
# Stop all services
make dev-down TARGET=/tmp/my-project
# Run tests (unit + integration) in container
make test
# Quick syntax check in container
make syntax
Build from source (Ruby only)
git clone https://github.com/Lax/castcaster.git
cd castcaster
gem build castcaster.gemspec
gem install castcaster-*.gem
Test
make test # Run all tests in Docker container
make syntax # Ruby syntax check in Docker container
make check # Full: syntax + test + gem build
Or with Ruby locally:
rake test # Run all tests (unit)
rake syntax # Ruby syntax check
rake # Default: syntax + test
Project structure
castcaster/
├── lib/castcaster/ ← Ruby source
│ ├── cli.rb ← CLI commands (Thor)
│ ├── channel.rb ← Channel model + CRUD
│ ├── channel_cli.rb ← Channel subcommands
│ ├── config.rb ← Configuration load/save
│ ├── deploy.rb ← Deployment generator
│ ├── deploy/ ← Compose/Swarm deployers
│ ├── engines/ ← Streaming engine configs
│ ├── ffmpeg_profiles.rb ← Transcode presets
│ └── version.rb ← Version constant
├── templates/ ← ERB/Tera templates
│ ├── nginx-rtmp/ ← Nginx config template
│ └── deploy/ ← Deployment templates
├── docker/ ← Docker image sources
│ ├── cli/ ← CLI tool container
│ ├── nginx/
│ ├── ffmpeg/
│ └── webui/
├── bin/ ← CLI entry point
├── test/ ← Minitest suite
├── examples/README.md ← Example documentation
└── examples/clock-demo/ ← CLI-generated project with clock source
License
MIT
Homepage: https://castcaster.mib.cc