Skip to content

Page API

approved

How a hosting page creates, controls, and observes player instances.

Mounting and unmounting

  • Creating a player takes a host element and a configuration and returns an instance handle; destroying it releases everything.
  • Updating an instance swaps the video in place: the media element is reused, which preserves playback permissions such as the audio activation grant. This operation is the primitive the shorts feed is built on.
  • Mount and update validate before applying anything. A hard-invalid configuration (the config contract's validation section defines exactly three conditions, with the legacy pre-3 body shape called out) makes the call fail with a console error naming the violation, and the instance renders the config error state; a rejected update applies no partial changes and does not continue the previous video. Soft irregularities never fail a call: they degrade to defaults with one consolidated console warning.
  • A hard-invalid initial call still mounts the configuration-error state before it reports and throws, and it returns no handle. When the supplied layout is valid, the error state uses that layout; landscape is the fallback only when the layout value is absent or invalid. The failed tree stays associated with its host internally so a later valid createPlayer call can replace and dispose it.
  • An update rejects a configuration whose layout differs from the instance's: layout is immutable per instance, in both directions, and the error says so plainly.
  • One live player owns one host. A second createPlayer call on an already-owned host throws an error naming the ownership conflict and leaves the existing instance untouched. Destroying the owner releases the host for a later player.

Instance handles

Creating a player is one call: createPlayer(host, config) takes a host element and a complete configuration and returns the instance handle. The handle is the entire surface a page ever holds; there is no other object and no engine access. It is a stable plain object whose method identities do not change.

ts
handle.update(config); // apply a complete configuration; throws on hard-invalid
handle.destroy(); // release everything

handle.getState(); // one snapshot object, see below

handle.play();
handle.pause();
handle.seek(seconds);
handle.setVolume(volume); // 0 to 1
handle.setMuted(muted);
handle.setRate(rate); // within the offered rate list
handle.setCaptions({ enabled, language });

handle.openShare(); // the external share trigger
handle.openPanel(view); // open a specific context panel view
handle.closePanel();

handle.on(event, handler); // returns an unsubscribe function

destroy() is idempotent. Once it has released the instance, mutating commands, update(), and new subscription attempts through that stale handle are silent no-ops; on() returns an inert unsubscribe function. getState() remains readable and returns the final detached snapshot. The unsubscribe returned by a live subscription is also idempotent.

State

getState() returns one snapshot, deliberately instead of many getters:

json
{
  "playback": "playing",
  "currentTime": 12.4,
  "duration": 609.9,
  "volume": 0.8,
  "muted": false,
  "rate": 1.5,
  "captions": { "enabled": true, "language": "de" },
  "pip": false,
  "layout": "portrait"
}

playback is one of idle, buffering, playing, paused, ended, error (the core player's six states; their derivation and transitions live in the core player document). The snapshot is a plain serializable object, computed at call time; it never updates itself. Pages that want continuous values subscribe to events.

Setter semantics

  • Setters express user-equivalent actions: they update the user state exactly as the player's own controls would (setRate remembers intent, setCaptions sets the preference), and the same bounds apply: a rate outside the offered list snaps to the closest offered value.
  • Setters on removed functions are silent no-ops: calling setCaptions on an instance with capabilities.captions: false does nothing, matching the removal-beats-preference rule.
  • openPanel(view) with a view whose metadata section is absent is a silent no-op (the view is dormant); openShare() without share data likewise.
  • openShare() opens the share dialog in its page placement, centered in the viewport; the player's own trigger uses the in-player placement (the share capability's Placement section defines both).
  • openPanel(view) on an instance whose layout owns no panel surface is a silent no-op, even when that view's metadata section is present.
  • The public context-panel view values are knowledge, underlyingPublication, and relatedVideos.

Events

handle.on(event, handler) subscribes; the returned function unsubscribes. Handlers receive one payload object, and every payload carries currentTime, read when the event is dispatched. Commands do not emit optimistically: an event follows the observed engine or LT-module state change, regardless of whether the trigger was the page API, player UI, lock screen, or browser. The list is deliberately small and grows in ordinary releases when a real need appears:

EventAdditional payload fieldsFires
readydurationMetadata and a first frame are available and the instance can play
playnonePlayback starts or resumes
pausenonePlayback pauses
endednonePlayback reaches the end (standalone; the feed loops instead)
seekednoneA seek completes
bufferingbuffering: booleanPublished buffering starts or recovers
errorkind: "configuration" | "startup" | "mid-playback"The corresponding error state is entered
timeUpdatenonePlayback position updates at the media element's native cadence
chapterChangechapter: PlayerChapter | nullThe current chapter changes, including the unlabeled intro
volumeChangevolume, mutedVolume or mute changes
rateChangeratePlayback rate changes
captionsChangecaptions: { enabled: boolean; language?: string }Captions toggle or the selected track changes
pipChangepip: booleanPicture-in-picture is entered or left
shareOpensource: "player" | "page"The share dialog opens; source matches the trigger
panelOpenview: "knowledge" | "underlyingPublication" | "relatedVideos"The context panel opens or switches to that view
panelClosenoneThe context panel closes
videoChangenoneA successful update is live

Every error also reaching the console is a rule from the core player document; events are for pages, the console is for developers.

Multiple players on one page

  • Multiple independent instances are supported. Cross-instance coordination exists only where a module defines it; the shorts feed's single-instance model keeps the common case trivial.