Viewix
BACK TO ALL DISPATCHES
EngineeringSLUG // keeping-playlists-in-sync-across-screens
DISPATCH // ENGINEERING8 MIN READ

Keeping playlists in sync across every screen

How a paired screen decides what to show next, why the schedule is evaluated on the device, and what happens when the network drops in the middle of a publish.

Viewix TeamProduct & engineering

Sample post — written for layout review, not a published article

Keeping playlists in sync across every screen
Stock photograph — illustration only, not a product screenshot

A screen is only as good as the last instruction it actually applied. This is how a paired screen stays in step with its workspace: what it checks, what it keeps locally, and what it keeps playing when nobody can reach it.

01

Polling, and why it is not enough

The simplest sync design is a timer: every few seconds, ask the server for the current schedule and compare it with what is on screen. That works, and it is roughly where this started. It also means every screen asks the same question on its own clock, and a workspace with a few hundred screens spends most of its traffic learning that nothing has changed.

The fix is not a faster timer. It is making the common answer — nothing has changed — cheap and unambiguous, and reserving real payloads for real changes.

A screen can never be wrong about what it is showing. If the network is the only thing that knows the truth, one dropped connection is enough to make the screen lie.

Illustrative quotation — sample post
02

One version number per workspace

A workspace keeps a single manifest version, bumped whenever something a screen can see changes: a playlist, a schedule, the media behind a playlist item, or a screen's group assignment. Every screen remembers the version it last applied and asks only for anything newer.

When nothing is newer, the answer is a short "unchanged" acknowledgement — no schedule tree, no media manifest, no queue of work for the device to reconcile. When something is newer, the screen gets the schedule it should be running and the list of media that goes with it, then reports the applied version back as soon as it has it.

sync-manifest.ts
// The one call each paired screen makes. `sinceVersion` is the manifest
// version this screen last applied.
export async function fetchManifest(
  apiKey: string,
  sinceVersion: number,
): Promise<{ applied: boolean; manifestVersion: number }> {
  const response = await deviceApi.fetchSync(apiKey, sinceVersion);

  if (response.unchanged) {
    return { applied: false, manifestVersion: sinceVersion };
  }

  // Switch playback first: the new schedule goes live now, even while its
  // media is still downloading.
  usePlaybackStore.getState().applyManifest({
    manifestVersion: response.manifestVersion,
    schedule: response.schedule,
    contentManifest: response.contentManifest,
  });

  // Downloads run in the background, prioritising what is on screen now.
  contentCache.reconcile(response.contentManifest).catch(log.error);

  return { applied: true, manifestVersion: response.manifestVersion };
}
03

Clocks and time zones

Schedules are authored in the workspace's time zone, and a kiosk box is not a trustworthy clock: it can be months off after a power cut, or set to a time zone nobody in the workspace works in.

So every sync response carries the server's time and the workspace's UTC offset. The player keeps the offset and applies it wherever it evaluates a schedule, which means a daypart resolves the same way for the operator who configured it and for the screen that has to run it.

  • Schedules are evaluated against corrected time, not the box's own clock
  • Dayparts are interpreted in the workspace time zone, so a publish means the same hour everywhere
  • A screen that has been offline keeps evaluating its cached schedule with the last offset it was given
04

When the network drops

A lost connection must not change what is on screen. A screen that loses its network keeps running its cached schedule: the same dayparts, the same playlists, and the same media already verified on disk.

Anything that has not finished downloading yet is streamed from its original location rather than blocking playback, so a publish that lands during an outage shows a gap in the new content — not a gap on the screen. When the connection comes back, the screen reports the version it is running and picks up whatever it missed.

TAGS:EngineeringVIEWIX CLOUDSYSTEMS