Skip to content

Changelog

All notable, user-facing changes to @hopecloud/jetstream-player are documented here. The format follows Keep a Changelog, and the project adheres to Semantic Versioning.

Unreleased

[1.4.1] - 2026-07-07

Fixed

  • The generated iframe's allow attribute now grants each feature to the embed origins explicitly (the src origin plus its known redirect target) instead of relying on the default src-origin delegation. Browsers dropped that default grant after the jstre.am 302 redirect to the real embed host, which broke picture-in-picture and autoplay delegation and logged a "Permissions policy violation: picture-in-picture" error in the host page's console. No grant ever falls back to *; hosts passing a custom embedOrigin that redirects to an unknown host should pass the final origin to retain the grants.

[1.4.0] - 2026-07-06

Added

  • getCurrentTime() – the new name for reading the current playback position. Works for video and audio alike.
  • Typed event payloads (TypeScript) – event handlers now know what they receive: timeupdate and volumechange handlers get a number, ended gets a boolean, and unknown event names are rejected at compile time. Runtime behavior is unchanged. The new PlayerEventMap type is exported.
  • embedOrigin option – the new name for pointing the player at a specific embed host (for example, a staging environment).
  • decodeCommand() - parses an inbound postMessage payload into a PlayerCommand, or null if it is not one. Exported for the embed (iframe) side of the protocol; host pages do not need it.

Deprecated

  • getVideoCurrentTime() – use getCurrentTime() instead. The old name keeps working as an alias.
  • The origin option – use embedOrigin instead. The old name keeps working as an alias; when both are set, embedOrigin wins.

Changed

  • The generated iframe's CSS class is now jetstream-player-iframe (was jet-stream-iframe-player). Update your stylesheet if you target it.
  • The wire protocol is now consistently kebab-case: getCurrentTime() asks the player with the get-current-time command (was get-video-current-time) and seekTo() sends seek-to (was seekTo). Requires an embed that understands the new names - the embed keeps answering the old ones, so older SDK versions are unaffected.

[1.3.0] - 2026-06-17

Added

  • on() and off() methods - subscribe to player events after the instance is created, the dynamic counterpart to the events constructor option. Multiple listeners per event are supported; on() returns an unsubscribe function, and off(event) (no handler) clears every listener for that event:

    ts
    const off = player.on('timeupdate', (seconds) => console.log(seconds));
    off(); // or: player.off('timeupdate')

[1.2.0] - 2026-06-17

Breaking

  • Removed the internal wire-codec exports normalizeEventData, denormalizeEventData, and isValidEventData. They were never meant to be public; the package now exports only JetstreamPlayer and the player types.
  • Replaced the IFrameBuilderSrcOpt and IFrameBuilderOpt types with a single EmbedFrameOptions.

Added

  • origin option - point the iframe at a specific embed host (a staging host, or the production host directly) to skip the redirect:

    ts
    new JetstreamPlayer('#player', {
      mediaId: 'jsv:xxxxxxxxxx',
      origin: 'https://embed.jetstream.studio',
    });
  • Optional playerId and relaxed ids - playerId may be omitted, and id formats are no longer enforced, so live stream (jsl:) ids and custom player ids work.

Fixed

  • Commands and events no longer silently fail after a redirect. The embed URL 302-redirects to its real host; the SDK now learns that host from the iframe's own messages instead of trusting the pre-redirect origin, so play(), events, and getters keep working.
  • Getters no longer hang forever. isMuted(), isPaused(), getVideoCurrentTime(), and getDuration() reject after 5 seconds if the player never replies.