Migrating from the Legacy Player (Vulcan) to Aurora

Aurora is the current Wistia Player. It replaces the previous-generation player (Vulcan), and it's built as a Web Component. It's a native <wistia-player> HTML element rather than a JavaScript object you retrieve through a queue. If you have a custom Vulcan integration, most of what you were doing is still possible in Aurora. The shape of the calls is just different.

This page maps the patterns our team is asked about most. For the complete API, see Player Events, Player Methods, and Attributes & Properties. For the basics of grabbing a player on your page, see Interacting with Aurora on your page.

Readiness callbacks: _wq.push and bind("ready", ...)

In Vulcan, you waited for the player by pushing an onReady handler onto _wq, or by calling bind("ready", ...) on a wistiaEmbed reference:

window._wq = window._wq || [];
_wq.push({
  id: "abc123",
  onReady: function(video) {
    video.play();
  }
});

In Aurora, the equivalent is the api-ready event, dispatched on the <wistia-player> element once its API is initialized:

<script src="https://fast.wistia.com/player.js" async></script>
<wistia-player id="my-player" media-id="abc123"></wistia-player>

<script>
  const player = document.getElementById("my-player");
  player.addEventListener("api-ready", () => {
    player.play();
  });
</script>

In React, use the onApiReady prop:

import { WistiaPlayer } from "@wistia/wistia-player-react";

export default function App() {
  return (
    <WistiaPlayer
      mediaId="abc123"
      onApiReady={(event) => event.target.play()}
    />
  );
}

You don't need a _wq queue as Aurora's <wistia-player> element exists in the DOM as soon as the browser parses it, so you can attach listeners immediately.

Reading duration and other metadata

In Vulcan, your onReady callback received a video handle whose metadata methods (getAssetDuration(), videoWidth(), videoHeight()) returned values right away.

In Aurora, duration is exposed as a read-only property on the <wistia-player> element — but api-ready fires before metadata has loaded. Wait for loaded-metadata before reading it:

<script src="https://fast.wistia.com/player.js" async></script>
<wistia-player id="my-player" media-id="abc123"></wistia-player>

<script>
  const player = document.getElementById("my-player");
  player.addEventListener("loaded-metadata", () => {
    console.log(player.duration);
  });
</script>

Depending on the browser, loaded-metadata may be delayed until the viewer interacts with the video.

Reading the asset's width and height is no longer exposed on the player itself. If you need the underlying video's intrinsic dimensions, fetch them from the Data API GET /v1/medias/{hashed_id} endpoint, which returns each asset with its width and height. To reserve the right amount of layout space at render time without a fetch, set the aspect attribute on the embed.

React component event timing

<WistiaPlayer> is a thin wrapper around <wistia-player> and follows the same event lifecycle. A few patterns to watch for when porting React code:

  • onApiReady does not fire synchronously on mount. If your code calls play() or seekTo() from a useEffect that depends on the ref, gate the call on onApiReady instead.
  • Methods on the ref require the API to be ready. Calling myPlayer.current.play() before api-ready is a no-op. Use the ref pattern from Player Methods and trigger from event handlers or user actions, not directly inside render or mount effects.
  • Programmatic seeks fire seeking and seeked the same as user-initiated seeks — there is no separate "internal seek" event. If you need to distinguish them, set a flag in your code before calling currentTime = ... and clear it inside the seeked handler.

For the full React API, see Aurora React Component.