Releases: zshall/program-guide
Release list
TVS 6.3.0 (2026-07-31)
Update Notes - 6.3.0 (2026-07-30)
Hot on the heels of 6.2.0, this update adds a new XMLTV integration to the program guide system.
✨ New Features
- Added the ability to import program guide listings from an XMLTV file. This allows you to use 3rd party headends like ErsatzTV or Tunarr to display program info directly, without needing any special translation layer like we did in the past.
externalSources:
cableListings: # key for the external source; can be anything as long as it's unique and doesn't use spaces or special characters other than dashes
url: https://example.com/guide.xml # The URL to the XMLTV file. Can be a local file path or a remote URL.
type: xmltv
channels:
- number: 50
abbr: CBL
info:
cableListings:guide.channel.5 # This channel's guide data will be pulled from the XMLTV source named `cableListings` and the channel ID of the XMLTV `<programme>` elements would be `guide.channel.5`
video: https://example.com/stream.m3u8 # You'll still need to pair this up with the video stream, since XMLTV doesn't provide the content itself, just metadata about what's on.🔧 Bug Fixes
- Fixed bug in the guide where channel ranges weren't properly showing the last channel in the range.
TVS 6.2.0 (2026-07-29)
Update Notes - 6.2.0 (2026-07-29)
This week's update expands the power of community IFrame plugins by adding multiple new capabilities to the TVS IFrame API.
✨ New Features
- Added a new
deepIntegrationsection to theIFrameengine that will allow configuration file authors the ability to grant permission to IFrames to access different APIs. For security, IFrames can't access these new APIs unless your config file allows it since they allow the IFrame to control TVS and read its data. - Added a new
capabilitiesproperty in the IFrame API that tells the IFrame which APIs the config file has given it access to, so if an IFrame doesn't have all the permissions it can take advantage of it can either fall back gracefully or display an error asking for more permissions if it needs them. - Added a Channel Info API which allows IFrames to query listing data for all channels or the current channel and also to get a number of current or upcoming programs. This allows for plugins like a dynamic "coming up next" animation or a 3rd party program guide.
- Added a Termination API which allows for the IFrame to signal to TVS that it's done and that we should advance to the next content if we're running in a
loopengine or some other context that supports dynamic scheduled content. - Added two new example plugins: Listings API example and Up Next API example. You can study the source code of these and use 'em as a template to make your own plugins. The code of each is a single HTML file with no external library dependencies so you can view the source code easily.
- number: 48
abbr: UPNEXT
loop:
- iframe: # This is an example of a plugin that uses the channel info API to display which listings are up next for the current channel. The plugin is hosted on a separate server and is loaded into the TV using an IFrame.
src: https://gcpw.art/tvs/engines/up-next
deepIntegration:
channelInfo: current-channel # The plugin will receive updates whenever the current content changes and can request listing info for the current channel.
canRequestTermination: true # You can grant permission for the plugin to signal that it's done and the loop should advance to the next content. The IFrame plugin must support this or it'll have no effect.
- image: placeholders/random-placeholder.jpg
duration: 10
- number: 49
abbr: UPNEXT2
iframe: # This is an example of a plugin that uses the channel info API to display program listings for different channels. The plugin is hosted on a separate server and is loaded into the TV using an IFrame.
src: https://gcpw.art/tvs/engines/listings
options:
channelRange: # You can pass in options to the plugin to control how it behaves; take a look at the source code of the IFrame for how we receive and use them.
min: 1
max: 5
deepIntegration:
channelInfo: all-channels # The plugin will receive updates whenever the current content changes and can request listing info for all channels.🔧 Bug Fixes
- Fixed bug in bulletin editor where placeholder text was showing up in the data tab rather than the data we were trying to preview.
⚙️ Other Changes
- For those participating in the Television Simulator Studio alpha I've made some breaking changes regarding how guide data is delivered: the
info.seriesproperty has been removed and in its place we've added a new property:info.subtitle. This is because in XMLTV and other systems, TV Shows usetitleto meanseriesandsub-titleto mean the episode title. In movies however they usetitleto mean the movie title and might usesub-titleto be a movie tagline or something else but series isn't used.
TVS 6.1.0 (2026-07-22)
6.1.0 (2026-07-22)
This update is all about program guides; we've got a new guide theme available, a few new guide features and a bit of performance optimization.
✨ New Features
- Added new
1997theme to the program guide engine which is modeled after the PC Prevue guide. - Guides now refresh with current listings dynamically instead of needing to change channels to get the listings to update.
- Added
timezoneoption to theguideengine which allows you to specify a timezone for the program guide, which will let you display the current guide listings but in a different time zone than what you're currently in. This doesn't change what's currently on as there can only be one program airing per channel at a time, but will affect the current date and time display and the timeslot labels in the guide. - Added
currentTimeFormat,currentDateFormat, andcurrentTimeslotTimeFormatwhich allow you to customize how the time and date are displayed in program guides. They accept the same formatting strings as the character generator.
- number: 166
abbr: G97
name: Guide 1997
guide:
logo: placeholders/guide-header-1997.png # Logo to show at the top of the guide
theme: "1997"
# themeOptions:
# borderColor: blue # Optional. The border color of the guide in the guide header
# clockColor: red # Optional. The background color of the clock in the guide header
- number: 167
abbr: GTIMES
name: Guide timezones and time formatting example
guide:
timezone: America/Los_Angeles # Optional. You can specify a timezone for the guide to use. If not specified, the browser's timezone will be used. Use IANA timezones (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
currentTimeFormat: "hh:mm:ss 'PT'" # Optional. You can specify a time format for the current time in the guide header. If not specified, the default format will be used.
currentTimeslotTimeFormat: "hh:mm a" # Optional. You can specify a time format for the current timeslot in the guide header. If not specified, the default format will be used.⚙️ Other Changes
- Changed the way that the internal
marqueecomponent works under the hood to allow for partial CSS-driven animations for the guide table instead of scrolling one pixel per tick, which allows us to use hardware acceleration and have smoother animations. To make sure that the guide headers still do the push animation that the program guides are known for, we've got a second track for guide headers that are animated separately so that the sticky positioning still works as it did before, but with much less repainting. I've tested this on a Raspberry Pi 4 and things look smoother now (even on high-end machines we'd see a lot of stuttering before.)
TVS 6.0.1 (2026-07-18)
🔧 Bug Fixes
- Fixed bug with
feed-readerengine where text would overrun the screen horizontally if preformatted text was being displayed.
⚙️ Other Changes
- This is the first public release to be built using a new Gitea actions workflow as opposed to manually. I'm slowly incorporating more automation steps so that we can get things built and released more reliably and faster; a typical done-by-hand release would take an hour or two sometimes because I had to coordinate Docker, GitHub, the documentation site, Discord announcements and the demo site manually. This new build process takes care of Docker and GitHub so far.
TVS 6.0.0 (2026-07-14)
Update Notes - 6.0.0 (2026-07-14)
✨ New Features
Audio Routing
Component-level audio routing now lives under _component.audio.
- Add
srcto play a dedicated audio file or stream while the component is mounted. - Omit
srcif the component already has its own audio and you only want it to duck or mute other managed audio. - Use
group,priority, andinterruptsto control which lower-priority audio groups are muted or ducked.
backgroundAudio: placeholders/bgm-3.mp3
backgroundAudioOptions:
group: music
video:
provider: youtube
src: yXkIHyBfns8
_component:
audio:
group: voice
priority: 10
interrupts:
- groups:
- music
behavior: mutePower-On Channel
Added the ability to revert to a default channel whenever the TV's power state changes.
startup:
powerOnChannel: 1 # any time the power is turned off and back on again, jump to this channel.Hidden Channels
Added the ability to hide a channel. Hidden channels won't be displayed in guides and channel lists, but can be accessed directly via number inputs.
- number: 280
name: Hidden Channel
abbr: HIDE
hidden: true # Set a channel as `hidden` and it won't show up in the guide or channel lists.
color: redSubchannels
Added the ability to have subchannels; e.g. channels like 2.1 or 4.10. Subchannels are required to be in quotes when defined in the channel guide:
- number: "3.14"
name: Pi Channel
abbr: PI
image: placeholders/apple-pie.jpgSubchannels are not decimals. 1.1, 1.10 and 1.100 are three different channels:
- Channel 1, subchannel 1
- Channel 1, subchannel 10
- Channel 1, subchannel 100
Negative subchannels and subchannels on channel zero are not allowed. Subchannels are shown in the guide and channel listings after their primary channels.
Layout updates
The mix layout has been reworked to accept an array of components stacked on top of each other rather than just a and b components, and per-component options like mixMode and opacity are now in a _mix section instead of in the top level. Read the upgrade guide below to learn how to migrate. h-split and v-split also accept arrays now and you can specify a weight for each component now rather than one splitPercentage.
‼️ Breaking Changes
- The external listings feature of the program guide has been replaced with a new
infosystem. Theguide.externalListingsoption has been removed. - Channel
titleanddescriptionhave been removed in favor of theinfosystem. - The
video-gameengine has been moved out of TVS and into its own open source project mixlayout uses an array rather thanaandbcomponents. Options formixModeandopacityare now under_mix.modeand_mix.opacity.h-splitandv-splitlayouts use an array rather thanaandbcomponents.
🚚 Backwards Compatibility
To help ease the transition to the new version, limited backwards compatibility has been added. If your configuration file has a 5.x schema like this at the top:
# yaml-language-server: $schema=https://gcpw.art/tvs/schemas/5.11.0.jsonWe'll load your config file in compatibility mode, which will translate your config file on-the-fly to work around breaking changes. Some things like removed / moved engines (basic-text and video-game) will not load but channels that can be loaded with modifications will load.
When you're ready to upgrade from 5.x to 6.x you can follow the steps below:
Upgrade Guide 5.x -> 6.0
- Change the schema line to the 6.0 schema:
# yaml-language-server: $schema=https://gcpw.art/tvs/schemas/6.0.0.json- Replace any
basic-textengine usage withcharacter-generator. I've prepared a template that looks the same as basic-text's defaults that you can drop in:
- number: 1
name: Basic Text backwards compatibility
abbr: TEXT
character-generator:
src: placeholders/config-examples/bulletins/basic-text.json
lines:
line:
- text: First line of text # put your text here
- text: Second line of text- Replace any
video-gameengine usage with the newiframeversion. You can self-host it or use the hosted version:
- number: -1
iframe:
src: http://gcpw.art/tvs/engines/video-game # replace with your own server if self-hosting
options:
game: flappybird.nes # Required. The game library by default is from `retrobrews.github.io`. You can specify a game from there directly. Set to false to use a core that doesn't require a game.
core: fceumm # Required. The system to emulate.
# The video game engine doesn't support granular volume adjustment right now, but mute and unmute work.
# BREAKING CHANGE since v6.0.0: Only game controller inputs are accepted to free up reserved keyboard keys for future use.- Change usage of
mixfrom the old to new syntax:
- Use a list rather than
aandb mixMode:becomes_mix.modeopacity:becomes_mix.opacity
Old syntax:
- number: 133
name: Mix Layout
mix:
a:
opacity: 0.6
image: placeholders/example-program.webp
b:
mixMode: difference
generator: test-patternNew syntax:
- number: 133
name: Mix Layout
mix:
- image: placeholders/example-program.webp
_mix:
opacity: 0.6
- generator: test-pattern
_mix:
mode: difference- Change usage of
v-splitandh-splitfrom the old to new syntax:
Old syntax:
- number: 139
name: V-Split
v-split:
a:
color: red
b:
color: blueNew syntax:
- number: 139
name: V-Split
v-split:
- color: red
- color: bluesplitPercentage can continue to be used but only if you have two components. The new equivalent is _split.weight:
- number: 139
name: V-Split
v-split:
- color: red
- color: blue
_split:
weight: 2 # This component will take up two units of weight compared to the others. The default is to distribute each component equally (1 weight per component)
- color: green- Move channel
titleanddescriptiontoinfosection
Anywhere where you have a channel with title and description attributes, move these to the info section and replace description with summary.
Old syntax:
- number: 2
name: Welcome
abbr: WELCOME
title: Thanks for testing Television Simulator!
description: Welcome to TVS 6.0!New syntax:
- number: 2
name: Welcome
abbr: WELCOME
info:
title: Thanks for testing Television Simulator!
summary: Welcome to TVS 6.0!Thanks to all users and supporters!
Television Simulator 6.0 has been in development for about 9 months and has undergone 188 commits, 253 files changed, +26,049, -15,436 code lines changed, and 28 prereleases. Lots of features that haven't been documented previously are now documented and there's a new video tutorial on custom themes. Whether you are new to TVS or a long-time user, thanks for checking it out!
TVS 5.11.0-beta (2026-05-10)
Update Notes - 5.11.0 (2026-05-10)
✨ New Features
Added a new virtual video signal feature that works with all components. Think of it as the ability to define a resolution that all inner components will use.
Added a new _component property, present on all content engines, that allows you to define properties that can apply to any component. Currently we only use one property: dimensions (the virtual video signal).
- number: 270
name: Virtual Video Signals
abbr: VVS
generator:
type: test-pattern
_component:
dimensions:
width: 1280
height: 720
aspectRatioBehavior: contain🔧 Bug Fixes
- Fixed a bug with the validation schema where
volumewas incorrectly set as a required property for thegeneratorengine. - Fixed validation schema bug where
loopdidn't correctly inherit from the base component.
❗ Deprecation Notice
In version 6.0.0, interruptsBackgroundAudio will change; either being moved to _component or restructured in another way. That way all properties that apply to all components will be under _component.
TVS 5.10.0-beta (2026-04-24)
Update Notes - 5.10.0 (2026-04-24)
✨ New Features
This update has added a new Character Generator engine that can be used in many scenarios:
- Displaying news bulletins, weather and text ads
- Overlaying text over videos or images
- Adding a crawl / ticker to a channel
- Integrating with live data (given you supply it in the right format)
TVS 5.10 ships with a built-in character generator template editor which you can also try on the demo site.
This update also adds two new weather providers that work worldwide: wttr.in and weatherapi.com which requires an API key.
- number: 150
name: Weather demo
abbr: WX1
weather:
logo: placeholders/weather.png
provider: wttr.in
units: imperial
- number: 151
name: Weather demo
abbr: WX2
weather:
logo: placeholders/weather.png
provider: weatherapi.com
apiKey: "YOUR-API-KEY"
units: metric❗ Deprecation Notice
The basic-text engine has been deprecated and will be removed in TVS 6.0. All example usages of it have been updated to use character-generator instead.
TVS 5.9.2-beta (2026-03-16)
Update Notes - 5.9.2 (2026-03-16)
🔧 Bug Fixes
-
Fixed #115 which was a problem I traced back to a Svelte framework issue. Svelte 5.53.7 exhibited this issue but Svelte 5.53.12 has fixed it. The issue manifested itself in TVS as a problem when changing channels too quickly; we would unload a channel rapidly while it's still loading and this would cause multiple channels to be loaded at the same time despite using a
{#key}block to prevent this. The zombie channels would never unload and would stick around until we refreshed the page. -
Added a 200ms throttle on channel change operations to help prevent any future issues with changing channels too fast. If you hold down the channel up / down button we no longer change channels as fast as possible; we'll change channels about 5 channels per second instead. If you mash channel up and down buttons rapidly we'll ignore any button presses shorter than 200ms apart.
-
Fixed an issue with the YouTube playlist engine where if you use it inside a
h-splitorv-splitlayout the player would take up 100% of the screen rather than 100% of its container meaning that we were losing half the image. YouTube playlists resize to fit their container properly now.
TVS 5.9.1-beta (2026-03-15)
Update Notes - 5.9.1 (2026-03-15)
🔧 Bug Fixes
- Fixed #113; the
<marquee>tag is broken in Chrome 146, so I switched to a custom implementation. This runs at 60 FPS and behaves similarly to the real marquee tag. Currently it is only available in the1989program guide theme, but it'll be used in upcoming engines as well.
TVS 5.9.0-beta (2026-03-09)
Update Notes - 5.9.0 (2026-03-09)
✨ New Features
- Added new
sat1992OSD theme based on C-Band satellite TV from the early 90's. This theme brings with it some interesting customization options; true to the way the real receivers work, we simulate a satellite dish on a motorized base. You can optionally define a list of known satellites with positions based on motor pulses (these values can be any arbitrary number). You can then definethemeOptionsin individual channels to specify the satellite that the picture would be received from. When you go to a channel that uses a different satellite than the one that you were on previously, the simulated motor will display progress saying it's turning to the position that you specified.
osd:
theme: sat1992 # 1990's analog C-band satellite receiver theme
themeOptions:
# showChannelInterference: false # by default, we display overlays of
satellite: C1 # the default satellite for all channels to be on. If unset, only channels with a satellite option set will display one.
satellites: # you can define a list of different satellites; they'll be a letter and number combination followed by a 4-digit number representing the location in the sky
C1: 3600 # these are all arbitrary numbers
C3: 4100
C4: 4300
C5: 4550
G1: 4550
G2: 4700
G3: 5100
G4: 6200
T3: 6900
channels:
- number: 1
name: Test Channel
color: blue
themeOptions: # optional section for theme-specific metadata
satellite: C3 # you can designate a channel as being on a particular satellite; choose from the list you defined in the OSD themes
- number: 2
name: Test Channel 2
color: red
themeOptions:
satellite: G2
- number: 3
name: Test Channel 3
color: green # if a channel doesn't specify a satellite, it defaults to the one specified in the OSD options, or no satellite if one isn't specified there either- Added a new
abstract-backgroundengine, which can currently apply two different visual effects to an image of your choice;wave1andwave2.
- number: 143
name: Abstract background 1
abstract-background:
type: wave1
- number: 144
name: Abstract background 2
abstract-background:
type: wave2
- number: 145
name: Abstract background with custom image
abstract-background:
src: placeholders/example-program.webp
type: wave2
width: 400
height: 300