Notice: ZSCTE Media is not free software. It is a proprietary commercial product developed and owned by Itassist Broadcast Solutions. Unauthorized reproduction, distribution, or modification is strictly prohibited. See the License section for details.
- Overview
- Key Features
- System Requirements
- Architecture
- Installation
- Modules & Screens
- API Reference
- SCTE-35 Integration
- ffplayout Integration
- Production Deployment
- Troubleshooting
- License
- Support
ZSCTE Media is an enterprise-grade broadcast management platform that provides a unified dashboard for live stream orchestration, SCTE-35 ad break signaling, server-side ad insertion (SSAI), and 24/7 playout scheduling.
Built on Next.js 16, FFmpeg, nginx-rtmp, and ffplayout, it enables broadcasters to:
- Ingest live RTMP/SRT streams and redistribute them to HLS/DASH
- Generate and inject SCTE-35 splice insertion signals in real time
- Schedule ad breaks (pre-roll, mid-roll, post-roll) with precise timing
- Manage ad campaigns, creatives, and VAST-based ad decisioning
- Monitor stream health, viewer analytics, and infrastructure status
- Control 24/7 playout schedules via ffplayout integration
- RTMP Ingest — Accept live RTMP feeds via nginx-rtmp
- FFmpeg Transcoding — Configurable video/audio codec, bitrate, resolution, GOP, ABR ladder
- Multi-Protocol Output — Distribute to SRT, RTMP, HLS, DASH simultaneously
- ABR Profiles — Define adaptive bitrate ladders with per-profile encoding settings
- Real-Time Control — Start, stop, restart, and monitor each stream from the dashboard
- Signal Generator — Create SCTE-35 splice_insert and time_signal messages via UI
- Signal Parser — Decode SCTE-35 from Base64, Hex, Integer, JSON, XML, and raw binary
- Format Converter — Convert between all SCTE-35 representation formats
- Live Injection — Inject ad break markers into running FFmpeg streams in real time
- HLS Cue Tags — Automatic
#EXT-X-CUE-OUT/#EXT-X-CUE-INtag insertion in HLS manifests - Scheduled Breaks — Schedule ad breaks by time, interval, or on-demand
- Break Types — Pre-roll, mid-roll, post-roll, time signal, and splice null support
- Ad Campaign Management — Create and manage ad campaigns with budgets and priorities
- Creative Library — Manage video ad assets with metadata (duration, resolution, bitrate)
- SSAI Pipeline — Server-side ad insertion workflow with VAST 3.0 support
- VAST Parser — Parse and validate VAST XML documents
- VAST Decision Engine — Ad selection logic with campaign priority and fill strategies
- Event Tracking — Impression, click, quartile, completion, and skip event logging
- Dashboard Overview — At-a-glance stream status, active alerts, and key metrics
- Stream Metrics — Real-time bitrate, FPS, resolution, packet loss, jitter, latency
- Ad Analytics — Campaign impressions, clicks, CTR, completion rates
- Infrastructure Monitoring — Server health, SSL certificate status, RTMP statistics
- Topology View — Visual representation of the broadcast signal flow
- Channel Management — Create and configure playout channels
- Playlist Scheduling — Build and manage date-based playlists
- Playout Control — Start, stop, restart, skip, and seek within playout
- Process Control — Monitor FFmpeg process stats, CPU, memory, and network I/O
- File Browser — Browse media files on the ffplayout server
- System Stats — Real-time system resource utilization
- Glassmorphism Design — Modern, polished UI with frosted-glass effects
- Dark / Light Mode — System-aware theme switching
- Responsive Layout — Fully responsive from mobile to ultrawide
- Collapsible Sidebar — Space-efficient navigation with icon-only mode
- Keyboard Shortcuts —
Ctrl+Bto toggle sidebar
| Component | Requirement |
|---|---|
| OS | Linux, macOS, or Windows with WSL2 |
| CPU | 2 cores |
| RAM | 4 GB |
| Disk | 10 GB free |
| Node.js | — (Bun runtime used instead) |
| Bun | >= 1.0 |
| FFmpeg | >= 6.0 (with libx264, libfdk-aac) |
| Docker | >= 24.0 (for containerized deployment) |
| Component | Requirement |
|---|---|
| OS | Ubuntu 22.04 LTS / Debian 12+ |
| CPU | 8+ cores (2+ per concurrent stream) |
| RAM | 16 GB |
| Disk | 50+ GB SSD (for media storage and HLS/DASH segments) |
| Network | 100 Mbps+ symmetric (depends on stream count and bitrate) |
| FFmpeg | >= 6.0 with --enable-libx264 --enable-libfdk-aac --enable-openssl |
| Docker | >= 24.0 with Docker Compose v2 |
| Domain | Valid domain with DNS A record (for Let's Encrypt SSL) |
┌─────────────────────────────────────────────────────────────────┐
│ ZSCTE Media Platform │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Next.js 16 App (Port 3000) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ Dashboard │ │ Streams │ │ Ad Ops │ │ Analytics │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ SCTE-35 │ │ SSAI │ │ ffplayout│ │ Infrastructure│ │ │
│ │ │ Tools │ │ Pipeline │ │ Scheduler│ │ Monitor │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ │
│ └───────────────────────┬──────────────────────────────────┘ │
│ │ REST API │
│ ┌───────────────────────┼──────────────────────────────────┐ │
│ │ SQLite (Prisma ORM) │ │
│ └───────────────────────┼──────────────────────────────────┘ │
│ │ │
├──────────────────────────┼──────────────────────────────────────┤
│ │ │
│ ┌──────────┐ ┌─────────┴────────┐ ┌───────────────────────┐ │
│ │ nginx │ │ Stream Worker │ │ SCTE-35 Service │ │
│ │ :80/443 │ │ (Bun :3010) │ │ (Python :3020) │ │
│ │ RTMP │ │ FFmpeg process │ │ threefive parser │ │
│ │ :1935 │ │ management │ │ / encoder │ │
│ └──────────┘ └──────────────────┘ └───────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
| Service | Port | Description |
|---|---|---|
| App (Next.js) | 3000 | Web UI, REST API, dashboard |
| Stream Worker | 3010 | FFmpeg process manager, SCTE-35 injection |
| SCTE-35 Service | 3020 | Python threefive-based parse/encode service |
| nginx | 80 / 443 | Reverse proxy, SSL termination, static file serving |
| nginx-rtmp | 1935 | RTMP ingest server |
| RTMP Stats | 8080 | RTMP stream statistics endpoint |
| ffplayout | 8787 | 24/7 playout engine (optional, external) |
Docker Compose is the recommended way to deploy ZSCTE Media in production. It orchestrates all four services (App, Worker, nginx, SCTE-35) with proper networking, health checks, and volume management.
# Clone the repository
git clone <repository-url>
cd zscte-media
# Copy environment configuration
cp .env.example .env
# Edit .env — set your domain and email for SSL
nano .envFor testing and evaluation, the nginx image includes self-signed certificates:
# Build and start all services
docker compose up -d --build
# Verify all services are healthy
docker compose psThe platform will be available at:
- Web UI:
https://localhost(accept self-signed cert warning) - Direct HTTP:
http://localhost:3000 - RTMP Ingest:
rtmp://localhost/live/<stream_key> - RTMP Stats:
http://localhost:8080/stat
For production with a real domain and trusted SSL certificates:
# 1. Set your domain and email in .env
DOMAIN=broadcast.yourcompany.com
EMAIL=admin@yourcompany.com
# 2. Run the Let's Encrypt initialization script
./init-letsencrypt.sh
# 3. Start with production overrides
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build# Check service health
docker compose ps
# View app logs
docker compose logs -f app
# View worker logs
docker compose logs -f worker
# Check RTMP stats
curl http://localhost:8080/statPush a test stream using FFmpeg:
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=25 \
-f lavfi -i sine=frequency=440:sample_rate=44100 \
-c:v libx264 -preset ultrafast -tune zerolatency -b:v 2500k \
-c:a aac -b:a 128k -f flv rtmp://localhost/live/test# Stop all services
docker compose down
# Stop and remove volumes (resets database)
docker compose down -v
# Rebuild a single service
docker compose up -d --build worker
# View real-time logs for all services
docker compose logs -f
# Scale worker (requires external load balancing)
docker compose up -d --scale worker=2- Bun >= 1.0 — Install Bun
- FFmpeg >= 6.0 with libx264 and aac support
- Git
# 1. Clone the repository
git clone <repository-url>
cd zscte-media
# 2. Install dependencies
bun install
# 3. Set up the database
bun run db:push
# 4. Start the Next.js development server
bun run dev
# 5. (Optional) Start the stream worker in a separate terminal
cd mini-services/stream-worker
bun install
bun run dev
# 6. (Optional) Start the SCTE-35 service in a separate terminal
cd mini-services/scte35-service
pip install -r requirements.txt
python main.pyThe application will be available at http://localhost:3000.
| Command | Description |
|---|---|
bun run dev |
Start Next.js dev server on port 3000 |
bun run lint |
Run ESLint code quality checks |
bun run db:push |
Push Prisma schema changes to SQLite |
bun run db:generate |
Regenerate Prisma client |
bun run db:migrate |
Run Prisma migrations |
bun run db:reset |
Reset database (destroys all data) |
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_API_URL |
https://localhost |
Public URL of the application |
NODE_ENV |
production |
Node environment (development or production) |
WORKER_URL |
http://worker:3010 |
Internal URL of the FFmpeg stream worker |
MAX_STREAMS |
4 |
Maximum concurrent streams the worker handles |
LOG_LEVEL |
info |
Worker log level: debug, info, warn, error |
DATABASE_URL |
file:/app/db/custom.db |
SQLite database file path |
DOMAIN |
your-domain.com |
Production domain for nginx and SSL |
EMAIL |
admin@your-domain.com |
Email for Let's Encrypt notifications |
SSL_CERT_PATH |
/etc/nginx/certs/cert.pem |
SSL certificate file path |
SSL_KEY_PATH |
/etc/nginx/certs/key.pem |
SSL private key file path |
| Screen | Description |
|---|---|
| Dashboard | Real-time overview of active streams, recent ad breaks, system health, and quick actions |
| Streams | Create, configure, start, stop, and monitor live stream configurations with full FFmpeg parameter control |
| Live Player | Embedded HLS/DASH video player for monitoring live output |
| Analytics | Charts and metrics for stream quality, ad performance, and viewer engagement |
| Screen | Description |
|---|---|
| Ad Breaks | Schedule and manage SCTE-35 ad break insertion (pre-roll, mid-roll, post-roll, time signal) |
| Ad Inventory | Campaign and creative management with budget tracking, priority settings, and fill strategies |
| SSAI Pipeline | Server-side ad insertion workflow with VAST 3.0 ad decisioning and event tracking |
| Screen | Description |
|---|---|
| SCTE-35 Tools | Generate, parse, and convert SCTE-35 signals in all formats (Base64, Hex, XML, JSON, HLS tags, FFmpeg commands) |
| ABR Profiles | Define and manage adaptive bitrate encoding profiles (360p, 480p, 720p, 1080p, 4K) |
| Media Library | Browse and manage media assets |
| Playout Scheduler | Connect to ffplayout instances, manage channels, playlists, and 24/7 automated playout |
| Screen | Description |
|---|---|
| AI Detection | AI-powered content analysis and scene detection |
| Topology | Visual signal flow diagram showing the broadcast pipeline from ingest to distribution |
| Infrastructure | Server health monitoring, SSL certificate tracking, RTMP statistics, and nginx status |
The platform exposes a REST API at /api/ for all operations. Key endpoints:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/streams |
List all stream configurations |
| POST | /api/streams |
Create a new stream configuration |
| GET | /api/streams/:id |
Get stream details |
| PUT | /api/streams/:id |
Update stream configuration |
| DELETE | /api/streams/:id |
Delete a stream |
| POST | /api/streams/:id/start |
Start the FFmpeg stream |
| POST | /api/streams/:id/stop |
Stop the stream |
| POST | /api/streams/:id/restart |
Restart the stream |
| POST | /api/streams/:id/inject |
Inject an SCTE-35 marker |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/ad-breaks |
List ad break schedules |
| POST | /api/ad-breaks |
Create an ad break schedule |
| GET | /api/ad-breaks/:id |
Get ad break details |
| PUT | /api/ad-breaks/:id |
Update ad break schedule |
| DELETE | /api/ad-breaks/:id |
Delete an ad break |
| POST | /api/ad-breaks/:id/fire |
Manually fire an ad break now |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/scte35/parse |
Parse SCTE-35 signal from any format |
| POST | /api/scte35/encode |
Encode SCTE-35 splice insertion |
| POST | /api/scte35/convert |
Convert between SCTE-35 formats |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/vast/parse |
Parse VAST XML document |
| POST | /api/vast/decision |
Get ad decision from VAST |
| POST | /api/vast/generate |
Generate VAST XML response |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/ffplayout/connection |
Save/test ffplayout connection |
| GET | /api/ffplayout/channels |
List ffplayout channels |
| POST | /api/ffplayout/channels |
Create a channel |
| GET/PUT | /api/ffplayout/channels/:id |
Get/update channel config |
| GET/PUT | /api/ffplayout/channels/:id/playout |
Get/set playout configuration |
| GET/POST | /api/ffplayout/channels/:id/playlist |
Manage date-based playlists |
| POST | /api/ffplayout/channels/:id/control |
Playout control (start/stop/next/back) |
| GET | /api/ffplayout/channels/:id/system |
System resource stats |
| GET | /api/ffplayout/channels/:id/files |
Browse media files |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/ssl/status |
SSL certificate status and expiry |
| GET | /api/rtmp/stats |
RTMP server statistics |
| GET | /api/worker/health |
Stream worker health check |
| GET/POST | /api/metrics/* |
Stream metrics collection and summary |
ZSCTE Media provides a complete SCTE-35 toolchain for live broadcast ad signaling:
- Splice Insert —
splice_insert()for program ad break boundaries - Time Signal —
time_signal()for segmentation descriptors - Splice Null —
splice_null()for bandwidth padding - Segmentation Descriptors — Content identification, provider ad ID, segmentation type IDs
- MPEG-TS Binary — Raw SCTE-35 table for transport stream insertion
- Base64 — URL-safe encoded binary
- Hex — Hexadecimal representation
- JSON — Human-readable structured representation
- XML — XML-encoded SCTE-35
- HLS Tags —
#EXT-X-CUE-OUT,#EXT-X-CUE-IN,#EXT-X-CUE-OUT-CONT - FFmpeg Commands — Ready-to-use FFmpeg command-line for marker insertion
- Real-Time — Inject markers into a running FFmpeg process via the worker API
- Scheduled — Automatically fire ad breaks at configured times or intervals
- Manual — One-click ad break firing from the dashboard
ZSCTE Media integrates with ffplayout for 24/7 automated playout scheduling.
- Install and configure ffplayout on your server
- In ZSCTE Media, navigate to Playout Scheduler → Connection tab
- Enter the ffplayout server URL (default:
http://127.0.0.1:8787) - Enter the ffplayout username and password
- Click Test Connection to verify
- Click Save Configuration
- Multi-Channel — Manage multiple ffplayout channels from one dashboard
- Playlist Management — Build playlists per day with drag-and-drop reordering
- Live Control — Start, stop, skip to next/previous item, seek
- Volume Control — Adjust playout audio volume
- Process Monitoring — Real-time FFmpeg process stats
- File Browser — Browse the ffplayout server's media library
- System Stats — Monitor CPU, memory, network, and disk usage
- Set
DOMAINandEMAILin.env - Run
./init-letsencrypt.shfor trusted SSL - Use
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d - Configure firewall: open ports 80, 443, 1935
- Set up log rotation (configured in docker-compose.prod.yml)
- Configure database backups (volume
app_db) - Set
MAX_STREAMSbased on available CPU cores - Review nginx security headers in
nginx/security-headers.conf - Enable
NEXTAUTH_SECRETfor authentication
| Concurrent Streams | Recommended CPU | Recommended RAM |
|---|---|---|
| 1–2 | 4 cores | 8 GB |
| 3–4 | 8 cores | 16 GB |
| 5–8 | 16 cores | 32 GB |
| 8+ | 32+ cores | 64 GB |
Each concurrent stream spawns a dedicated FFmpeg process. H.264 encoding is CPU-intensive — plan 2 CPU cores per 1080p stream as a baseline.
# Backup SQLite database
docker cp scte35-app:/app/db/custom.db ./backup-$(date +%Y%m%d).db
# Restore database
docker cp ./backup-20250101.db scte35-app:/app/db/custom.db
docker compose restart app- Verify FFmpeg is installed:
ffmpeg -version - Check the worker is running:
curl http://localhost:3010/api/health - Review worker logs:
docker compose logs worker - Ensure the source RTMP URL is reachable
- Check
MAX_STREAMSlimit in.env
- Verify
hlsTagModeis set toscte35_pidorcue_tagsin stream config - Check the SCTE-35 service is running:
curl http://localhost:3020/api/health - Review the ad break schedule status (should be
fired, notfailed) - Inspect HLS manifest for
#EXT-X-CUE-OUTtags
- For self-signed: the browser will show a warning — this is expected for testing
- For Let's Encrypt: ensure port 80 is open and DNS points to your server
- Re-run
./init-letsencrypt.shif certificates expired - Check nginx logs:
docker compose logs nginx
- Verify ffplayout is running on the configured port (default: 8787)
- Check firewall allows traffic between ZSCTE Media and ffplayout
- Verify credentials are correct
- Check ffplayout logs for authentication errors
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, React 19) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS 4, Glassmorphism theme |
| UI Components | shadcn/ui (New York style) + Lucide Icons |
| Database | SQLite via Prisma ORM |
| Stream Processing | FFmpeg (via Bun subprocess) |
| RTMP Server | nginx-rtmp-module |
| SCTE-35 | Custom TypeScript parser/encoder + Python threefive |
| Playout | ffplayout (external) |
| Charts | Recharts |
| Animations | Framer Motion |
| Notifications | Sonner (toast) |
| Runtime | Bun |
| Containerization | Docker + Docker Compose |
| Reverse Proxy | Caddy (development) / nginx (production) |
ZSCTE Media is a proprietary commercial software product developed and owned by Itassist Broadcast Solutions.
- This software is NOT open source and is NOT free software.
- Unauthorized copying, distribution, modification, reverse engineering, or sale of this software is strictly prohibited.
- No license is granted to modify, adapt, or create derivative works.
- The source code is provided only for authorized deployment and maintenance by licensed customers.
- A valid license from Itassist Broadcast Solutions is required to deploy and use this software in any environment.
- Licensed users may deploy the software on their own infrastructure for the purposes specified in their license agreement.
- All intellectual property rights, including patents, copyrights, trade secrets, and trademarks, remain the exclusive property of Itassist Broadcast Solutions.
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. IN NO EVENT SHALL ITASSIST BROADCAST SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For licensing inquiries, contact: Itassist Broadcast Solutions
For technical support, feature requests, and licensing:
- Organization: Itassist Broadcast Solutions
- Product: ZSCTE Media — Enterprise RTMP + SCTE-35 Platform
ZSCTE Media — A Product of Itassist Broadcast Solutions
Enterprise-grade broadcast infrastructure for the modern streaming era.