Skip to content

About

Professional gstreamer based SMPTE 2110 ready tv broadcast channel in the box

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

55 Commits

Folders and files

Repository files navigation

Pipeline Controller

Professional GStreamer-based broadcast playout system (channel-in-a-box) for Linux – with an HTML5 web interface, oGraf graphics engine, and plugin system.

Node.js GStreamer Platform oGraf License


📺 What is Pipeline Controller?

Pipeline Controller is a complete broadcast playout system built on the open-source framework GStreamer. It enables professional on-air operations through a modern, fully browser-based web interface — designed for 24/7 channel-in-a-box operations. image

Features at a glance

  • 🎬 dynamic configureable amount of independent media players (MXF, MP4, MOV, TS, …)
  • 🎚️ Master pipeline with compositor, video switcher, and audio mixing
  • 🔊 Flexible audio routing with multiple groups, channel matrices, and 5.1 upmix
  • 📊 EBU R128 loudness normalization per audio group
  • ✨ oGraf HTML5 graphics engine (EBU standard) via Puppeteer/Chromium with templates
  • 📋 Playlist engine with transitions (cut, v-fade, cut-fade, fade-cut, X-fade) and event children
  • 🧩 Asset Panel for one-click commercial breaks with auto-return (interrupt / break / live modes)
  • ⏱️ Counter Strip showing all time-critical events of the current hour at a glance
  • 🎙️ Voiceover engine with fade-in/out and program ducking
  • 🔌 Plugin system running in isolated worker threads (crash-safe playout)
  • 🔐 Optional Bearer-token authentication with role-based access (admin/editor/grafiker/viewer)
  • 🌐 Full REST API, SSE event stream, and HTTPS support
  • 🕐 PTP clock support (IEEE 1588 / SMPTE 2110) and DST-safe scheduling
  • 🌍 Bilingual UI (English / German) with light/dark mode
  • 📺 Multi-channel supervisor — run several independent channels/playlists per host (e.g. a main channel + a sign-language variant), each with its own data dir/port, with a central dashboard
  • 🔗 ChannelBus cross-channel triggers — send NEXT/NEXT_LIVE/JUMP/CUT commands between channels (or hosts), including playlist-item-bound trigger children with frame-accurate pre-roll
  • 🔲 DVE / Squeeze — squeeze the program/live video into a positioned box (or squeeze an image/oGraf overlay over full-screen video), with green-screen auto-detection and chroma-key transparency for frame graphics
  • 📤 Additional outputs — any number of extra downconverted network outputs (RTMP/SRT/UDP/file) or DeckLink SDI/HDMI hardware sinks, independent of the main program path
  • 📡 DMF/MXL live sources — EBU/AMWA Media eXchange Layer shared-memory flows as live sources (real mxlsrc/mxlsink GStreamer plugin), with in-UI feed discovery/selection
  • 📺 SCTE-35 splice cue generator — generate SCTE-35 splice_insert/splice_null as MPEG-TS/UDP, triggered by playlist events, classification (commercial/promo), block_start/block_end events, or manual cue from the UI
  • ⚠️ Transition timing validation — automatic warnings when clips are too short for configured crossfade/fade transitions (🔀⚠ badge on playlist event + toast in editor)
  • 🔇 Audio Preset Resilience — automatic fallback when a clip has fewer audio channels than the selected preset requires: static pre-cue check (before playout) and live EBU-silence detection (during playout, hot-swap without interruption). Global fallback chain + optional per-event override, both configurable via an interactive drag-and-drop chip builder in the UI
  • 🔀 Per-Track Audio Silence Fallback — when a specific audio group (e.g. 5.1 surround) is detected silent while a fallback group (e.g. stereo program) carries signal, only that group's routing matrix is hot-patched without affecting other groups. Automatic up-/downmix (LoRo / LtRt / sum) when channel counts differ. Restores to the original preset matrix when audio returns
  • 🎛️ Stream Deck WebHID — direct hardware button surface control from the browser (Chrome/Edge, no drivers needed). Fully dynamic pages for playlist control, live source switching, asset playback, oGraf take/takeout, SCTE-35 cues, and branding selection. Plugin-extensible: any plugin can register its own Stream Deck page

🚀 Quick Start

Option 1: Installer Package (recommended for production / remote installs)

Native Node.js installation — no AppImage required:

# On a target machine: download & install
tar -xzf PipelineController-1.0.1.tar.gz
cd PipelineController-1.0.1
bash install.sh          # ⚠️ never with sudo!

# Start
bash ~/pipeline-controller/start.sh
# or as systemd user-service (if enabled during install)
systemctl --user start pipeline-controller

The installer verifies Node.js ≥ 18, all required GStreamer plugins (intervideosrc, interaudiosrc, compositor, …), installs missing dependencies via apt-get, sets up runtime directories, and configures settings.json paths correctly for the target machine.

Option 2: AppImage

chmod +x PipelineController-x86_64.AppImage

# IMPORTANT: extract the AppImage (do not run it directly!)
./PipelineController-x86_64.AppImage --appimage-extract
cd squashfs-root
./AppRun

⚠️ Important: The AppImage must be extracted — the oGraf graphics engine (Puppeteer/Chromium) requires access to the real filesystem and cannot run from a FUSE-mounted AppImage.

Option 3: From source

# Node.js ≥ 18 required
nvm install 20 && nvm use 20

sudo apt install build-essential libgstreamer1.0-dev \
  libgstreamer-plugins-base1.0-dev \
  gstreamer1.0-{tools,plugins-base,plugins-good,plugins-bad,plugins-ugly,libav,x,alsa,gl} \
  pulseaudio

npm install
node server.js

Then open in your browser: http://localhost:3000

Option 4: Multi-channel (several playlists on one host)

node supervisor.js channels.json

Opens a dashboard at http://localhost:3099 listing all configured channels, each running as its own isolated server.js process (own port, own data dir). See Multi-Channel Operation in the manual.


📋 System Requirements

Component Requirement
Operating System Linux x86_64, kernel ≥ 5.4 (Debian 12 / Ubuntu 22.04 recommended)
Node.js ≥ 18
GStreamer ≥ 1.22 (with plugins-bad for intervideosrc, compositor, …)
X11 display Required for ximagesink (use fakesink for headless)
Audio PulseAudio (recommended) or ALSA
Python 3 Only required for the Marina Sync plugin
RAM ≥ 2 GB (4 GB recommended)

🏗️ Architecture

┌─────────────────────────────────────────────────────────────┐
│              Web UI (HTML5 SPA · DE / EN)                   │
└──────────────────────────┬──────────────────────────────────┘
                           │ REST + SSE  (HTTP / HTTPS)
┌──────────────────────────▼──────────────────────────────────┐
│              Node.js Server (server.js)                     │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Playlist Engine  │ Graphics Engine │  Voiceover    │   │
│  │  Audio Router     │ Plugin Host     │  Media Lib    │   │
│  │  Auth + Roles     │ User Log        │  Asset Engine │   │
│  └─────────────────────────────────────────────────────┘   │
└──────────────────────────┬──────────────────────────────────┘
                           │ gst-kit (native bindings)
┌──────────────────────────▼──────────────────────────────────┐
│  GStreamer Pipelines                                        │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌────────────┐ │
│  │ Player 1 │  │ Player 2 │  │ Player 3 │→│  Master    │ │
│  └──────────┘  └──────────┘  └──────────┘  │  Pipeline  │ │
│                                              │ (Compositor)│ │
│  ┌──────────────────┐                       │ + Switcher │ │
│  │ oGraf (Chromium) │──────────────────────→│ + AudioMix │ │
│  └──────────────────┘                       └─────┬──────┘ │
└──────────────────────────────────────────────────┼──────────┘
                                                   ▼
                                    Video Sink + Audio Sinks

Master Pipeline (actual GStreamer element graph)

Auto-generated graph of the running master pipeline (compositor, video switcher, audio mixer/router, sinks):

Pipeline element graph


🎨 oGraf Graphics Engine

Pipeline Controller is built on the EBU oGraf standard for HTML5 broadcast graphics.

Playlist Variables

Graphics can pull live data from the playlist using a powerful variable syntax — automatically resolved when the graphic appears on screen:

{{next[class(movie)]:title}}                  → next movie's title
{{next[title(News)]:starttime|unixms}}        → countdown target as Unix ms
{{current:classifcolor}}                      → dynamic accent color
{{next2[class(movie)]:starttime|HH:MM}}       → 2nd next movie's start time

Numeric formats (unix, unixms, countdown, countdownms) return real JS numbers — perfect for template fields of type integer or number. An interactive {{…}}-builder is available in the UI for every text/number field.

See the manual for the full syntax.


🔌 Plugin System

Plugins run in isolated worker threads — a plugin crash has no impact on the running playout.

Plugin Description Default
📁 File Transfer Manager Automatic FTP/FTPS/local transfer & cache management ✅ enabled
🎛️ Broadcast Controller Control external routers (SW-P-08, EVS Cerebrum, HTTP, TCP) disabled
📺 SCTE-35 Cue Generator Generate SCTE-35 splice cues as MPEG-TS/UDP from playlist events, classifications, or manual trigger disabled
🛥️ Marina Sync Auto-sync playlist from Pebble Beach Marina (.mpl watchfolder, on-air resume) disabled
📡 SNMP Monitor Monitor broadcast devices via SNMP v1/v2c/v3 disabled
💬 Subtitle FAB Live subtitle control via FAB Subtitle Server disabled

Custom plugins can be developed in just a few lines of code – see plugin development in the manual.


🔐 User Management

Optional role-based access control with Bearer tokens. Disabled by default — enable it under Settings → Users when the system is reachable from untrusted networks.

Role Access
admin Full access — user management, all settings, plugins
editor Playlist control, media library, plugin management
grafiker Graphics only (oGraf templates, take/out, hotkeys)
viewer Read-only — live state, SSE stream, no actions

All login, logout, and write operations are logged to a JSONL audit log (configurable path). Passwords are stored as SHA-256 hashes.


📡 REST API & SSE

Full control via HTTP — for example:

# Start the master pipeline
curl -X POST http://localhost:3000/api/master/start

# Cue a clip
curl -X POST http://localhost:3000/api/player/1/cue \
  -H "Content-Type: application/json" \
  -d '{"file":"news.mxf","som":"00:00:00:00","eom":"00:05:30:00"}'

# Show a graphic
curl -X POST http://localhost:3000/api/grafik/show \
  -H "Content-Type: application/json" \
  -d '{"template":"lower-third","data":{"headline":"Max Mustermann"}}'

Real-time updates via Server-Sent Events:

const es = new EventSource('http://localhost:3000/events');
es.addEventListener('audio-level', e => {
  const { levels } = JSON.parse(e.data);
  // levels: { "pgm-stereo": { rms: -18.5, peak: -14.2 }, ... }
});

Full API reference: Manual → REST API


🔒 HTTPS / TLS (optional)

Enable HTTPS as a parallel server port via settings.json or environment variables:

HTTPS_KEY=/path/to/key.pem \
HTTPS_CERT=/path/to/cert.pem \
HTTPS_PORT=3443 \
node server.js

The plain HTTP port stays active in parallel (useful for local access).


📁 Project Structure

pipeline-controller/
├── server.js               # Main server (one process = one channel)
├── supervisor.js           # Multi-channel supervisor + dashboard
├── channels.json           # Multi-channel config (id/dataDir/port per channel)
├── ui.html                 # Web interface (SPA)
├── settings.json           # Settings (auto-generated)
├── audio_config.json       # Audio groups + presets + clock
├── plugins.json            # Plugin configurations
├── users.json              # Users (SHA-256 password hashes)
├── lib/                    # Backend modules
│   ├── MasterPipeline.js
│   ├── PlayerPipeline.js
│   ├── AudioRouter.js
│   ├── PlaylistEngine.js
│   ├── GrafixEngine.js
│   ├── VoiceoverEngine.js
│   ├── ChannelBus.js       # Cross-channel/cross-host trigger bus
│   ├── OutputEngine.js     # Additional downconvert/Cleanfeed/DeckLink outputs
│   ├── GreenZoneDetect.js  # Green-screen box detection + chroma-key transparency
│   ├── MxlSource.js        # DMF/MXL flow discovery (mxl-info wrapper)
│   └── ...
├── releases/               # Build artifacts (AppImage, tar.gz) — git-ignored, distributed via GitHub Releases
├── plugins/                # Plugin system
│   ├── broadcast-controller/
│   ├── file-transfer-manager/
│   ├── marina-sync/
│   ├── scte35/
│   └── ...
├── scripts/
│   └── install-mxl.sh      # Builds libmxl + gst-mxl-rs (mxlsrc/mxlsink) from source
├── env/mxl.env              # DMF/MXL plugin paths (auto-generated by install-mxl.sh)
├── templates/grafik/       # oGraf templates
├── media/                  # Media files
├── playlists/              # Saved playlists
├── images/                 # Still images
├── channelbranding/        # Branding overlays
└── asrun/                  # As-run logs (daily, txt)

📚 Documentation


🛠️ Tech Stack

Component Version License
GStreamer 1.22+ LGPL 2.0+
Node.js 18+ MIT
Puppeteer 24+ Apache 2.0
gst-kit 0.2.5+ MIT
basic-ftp latest MIT
EBU oGraf v1 Open Standard

⚠️ Note on Codecs

gst-plugins-bad and gst-plugins-ugly include decoders for partly license-restricted formats (H.264, MPEG-2, AC-3, DTS). For commercial use with these codecs, licensing fees may apply. For testing and non-commercial use, the open-source implementations may be used freely.


🐛 Bug Reports & Feature Requests

Please file issues via GitHub Issues. For bug reports, please include:

  • Linux distribution & version
  • GStreamer version (gst-launch-1.0 --version)
  • Node.js version (node --version)
  • Output of GST_DEBUG=*:2 node server.js 2> gst_debug.log
  • Relevant parts of settings.json (paths, video/audio sinks)

📄 License

The foundation (GStreamer, Node.js, Chromium, npm packages) is open source. The application-specific code is released under the terms defined in the LICENSE file.


Screenshots

Playlist Event Editor:
image

Player Section:
image

Ograf Editor: image

Manual Record:
image

Assets:
image

Pipeline Controller
Broadcast Playout System · GStreamer 1.22+ · Node.js 18+ · EBU oGraf
24/7 channel-in-a-box · Linux · Open-Source-based

About

Professional gstreamer based SMPTE 2110 ready tv broadcast channel in the box

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages