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 ofDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ErsatzTV/legacy/llms.txt
Use this file to discover all available pages before exploring further.
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. AChannel 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.
Schedule Kinds
TheScheduleKind property (PlayoutScheduleKind) identifies which type of schedule is powering this playout:
| Kind | Value | Source of Truth |
|---|---|---|
None | 0 | No schedule assigned; the playout is empty. |
Classic | 1 | A ProgramSchedule object (referenced by ProgramScheduleId). |
Block | 2 | Block templates and decos, resolved via Templates. |
Sequential | 3 | A YAML file at the path in ScheduleFile. |
Scripted | 4 | A Python script at the path in ScheduleFile. |
ExternalJson | 20 | A JSON document at the path in ScheduleFile. |
ScheduleFile.
Playout Items
EachPlayoutItem represents one media item placed at a specific point in time in the playout:
| Property | Description |
|---|---|
MediaItemId | The database ID of the media item to play. |
Start / Finish | UTC timestamps defining when the item begins and ends. |
GuideStart / GuideFinish | Optional override timestamps used in EPG output, allowing guide data to differ from actual playout times. |
CustomTitle | An optional title override displayed in the EPG instead of the media item’s real title. |
FillerKind | Whether this item is primary content or a specific filler type (pre-roll, mid-roll, post-roll, tail, fallback). |
InPoint / OutPoint | Trim points within the media file — used when scheduling a chapter or a clipped segment. |
ChapterTitle | When playing a specific chapter, the title of that chapter. |
GuideGroup | Groups multiple items that should appear as a single entry in the EPG (e.g., a movie split across a commercial break). |
BlockKey / CollectionKey | String keys identifying which block and collection this item belongs to — used for history tracking. |
The Playout Anchor
ThePlayoutAnchor is ErsatzTV’s bookmark into the current state of the playout build. It tracks:
| Property | Description |
|---|---|
NextStart | The UTC DateTime at which the next item should be placed. |
ScheduleItemsEnumeratorState | The current position within the schedule item list. |
MultipleRemaining | For Multiple-mode items, how many more items remain in the current slot. |
DurationFinish | For Duration-mode items, the UTC time at which the duration budget is exhausted. |
InFlood | Whether the build is currently in a flood-fill phase. |
InDurationFiller | Whether the build is currently filling with duration filler. |
NextGuideGroup | Counter for assigning guide group IDs to items. |
NextInstructionIndex | Used by Block and Scripted schedules to track position within instruction sequences. |
Playout Build Process
ErsatzTV builds playouts as a background service. The build process: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.
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.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.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
ThePlayoutBuildStatus entity tracks the outcome of the most recent build for each playout:
| Property | Description |
|---|---|
LastBuild | The timestamp of the most recent build attempt. |
Success | Whether the build completed successfully. |
Message | An error or informational message from the build, if any. |
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 aPlayoutHistory 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
TheSeed 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, theTemplates collection holds PlayoutTemplate entries that map programming templates to calendar conditions:
| Property | Description |
|---|---|
TemplateId | The Block template to use. |
DecoTemplateId | An optional Deco template to layer over the block. |
DaysOfWeek | Which days of the week this template applies to. |
DaysOfMonth | Which days of the month this template applies to. |
MonthsOfYear | Which months of the year this template applies to. |
LimitToDateRange | When true, restricts the template to the specified date range. |
StartMonth | Month component of the range start date (int). |
StartDay | Day component of the range start date (int). |
StartYear | Optional year component of the range start date (int?). |
EndMonth | Month component of the range end date (int). |
EndDay | Day component of the range end date (int). |
EndYear | Optional year component of the range end date (int?). |
Playout Offset
The EPG display times for a playout’s items can be shifted by configuringPlayoutOffset (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’sPlayoutMode 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
Fill Group Indices
TheFillGroupIndices 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 existingPlayoutItem records and rebuilds the timeline from scratch:
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 aPlayoutGap:
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.