Skip to main content
A playout is the computed, time-stamped list of media items that ErsatzTV will play on a channel. It is the concrete product of resolving a schedule against your media library: when ErsatzTV builds a playout, it walks through schedule items, expands collections into individual media items, assigns precise start and finish timestamps to each, and stores the result as a sequence of PlayoutItem records. The streaming engine reads these records in real time to decide what to transcode and deliver to viewers.

The Role of a Playout

Channels and schedules do not interact directly. The playout is the joining entity between them. A Channel has a List<Playout> — meaning one channel can have multiple active playouts simultaneously — and each playout references both the channel and the schedule that drives it.
Having multiple playouts on a single channel is useful in advanced configurations — for example, when combining a primary schedule playout with an on-demand playout that can be triggered independently.

Schedule Kinds

The ScheduleKind property (PlayoutScheduleKind) identifies which type of schedule is powering this playout: For Classic schedules, the schedule definition lives in the database. For Sequential, Scripted, and ExternalJson schedules, it lives in a file on disk referenced by ScheduleFile.

Playout Items

Each PlayoutItem represents one media item placed at a specific point in time in the playout:

The Playout Anchor

The PlayoutAnchor is ErsatzTV’s bookmark into the current state of the playout build. It tracks: The anchor is persisted to the database so that incremental playout builds can resume from the correct position rather than rebuilding from the beginning every time.

Playout Build Process

ErsatzTV builds playouts as a background service. The build process:
1

Resolve the Schedule

ErsatzTV reads the schedule definition — from the database for Classic schedules, or from the file system for YAML/Scripted/ExternalJson. For Block schedules, it evaluates which templates apply to the current date based on day-of-week, day-of-month, and date range rules.
2

Enumerate Collections

Each schedule item’s collection, multi-collection, smart collection, playlist, or search query is resolved into a concrete ordered list of media items. Playback order (Chronological, Shuffle, SeasonEpisode, etc.) is applied at this step.
3

Place Items on the Timeline

Items are assigned Start and Finish timestamps. Fixed-time slots snap items to clock times; dynamic (flood/back-to-back) items are placed end-to-end. Filler items are inserted to fill gaps.
4

Persist the Playout

The resulting PlayoutItem records are written to the database. Gaps (PlayoutGap) are recorded for any spans of time in the playout that have no coverage. The PlayoutBuildStatus record is updated with the build result and timestamp.
Playouts are typically extended automatically as the current time approaches the end of the existing built window. The DailyRebuildTime property (TimeSpan?) can be set to force a full playout rebuild at a specific time of day — useful for Block schedules where each day’s programming is determined by template matching.

Playout Build Status

The PlayoutBuildStatus entity tracks the outcome of the most recent build for each playout: If Success is false, check the Message for details about what went wrong — common causes include missing media files, empty collections, or invalid schedule configurations.

Playout History

For Block schedules, ErsatzTV maintains a PlayoutHistory table that records which item from each collection was most recently played in each block:
Playout history is maintained exclusively for Block schedules. It enables ErsatzTV to resume playback of each block’s collection from the correct position after a daily rebuild or playout reset, preserving your channel’s continuity across rebuilds.

Playout Seed

The Seed property (int) is a random seed stored on the playout. It is used to initialize shuffle and random operations during playout builds, ensuring that a given playout always produces the same random ordering when rebuilt with the same seed. You can change the seed to produce a different shuffle sequence.

Playout Templates (Block Schedules)

For Block schedule playouts, the Templates collection holds PlayoutTemplate entries that map programming templates to calendar conditions: ErsatzTV evaluates templates in index order and selects the first matching template for each day.

Playout Offset

The EPG display times for a playout’s items can be shifted by configuring PlayoutOffset (TimeSpan?) on the channel — not the playout itself. This channel-level setting is applied when generating XMLTV guide data, allowing the displayed program times to be offset from the actual playout timestamps. See Channels for details on setting this property.

On-Demand Playouts

When a channel’s PlayoutMode is set to OnDemand, the playout behaves differently from a continuous channel:
  • Items are added to the playout queue when a viewer requests content
  • After a viewer finishes watching an item, that item is automatically removed from the playout
  • The OnDemandCheckpoint (DateTimeOffset?) property tracks the last-acknowledged position for resuming on-demand playback
On-demand channels are useful for creating watch-on-request channels where content plays when a viewer tunes in, rather than running a fixed live schedule.

Fill Group Indices

The FillGroupIndices collection (List<PlayoutScheduleItemFillGroupIndex>) tracks the current position within each schedule item’s filler group. This enables ErsatzTV to continue cycling through filler content correctly across playout rebuild boundaries, rather than restarting from the first filler item each time.

Alternate Schedules on Playouts

For Classic schedule playouts, ProgramScheduleAlternates allows override schedules to be evaluated before the primary schedule. Alternate schedules can target specific days of the week, date ranges, or other conditions — enabling seasonal or special-event programming without creating a separate playout for each variant.

Resetting a Playout

You can force a full playout rebuild via the API. Resetting discards all existing PlayoutItem records and rebuilds the timeline from scratch:
Resetting a playout will discard the current playout anchor and all scheduled items. The channel may briefly display the fallback filler or go dark while the new playout is being built. For Block schedule playouts, history is preserved across resets so that playback resumes from the correct collection position.
For full API reference, see Channels API.

Gaps

When the playout builder cannot fill a span of time — because a collection is empty, a file is missing, or filler runs out — it records a PlayoutGap:
Gaps represent dead air. The channel’s FallbackFiller (if configured) is the last line of defense against gaps. Monitor the build status and any recorded gaps after a rebuild to diagnose scheduling or library issues.