Plugins and Adapters
The player core is small on purpose. It plays a queue, keeps time, and fires events, and that’s about it. Everything else you build on top of it happens through one of two mechanisms, and almost every “how do I add X” question really comes down to picking the right one of the two.
Plugins add new behavior
A plugin is something the player does that it didn’t before: an equalizer, a controls overlay, subtitle rendering, a skip-intro button, casting to a TV. A plugin watches events, reacts to them, and brings its own state and UI along. You opt into each one with addPlugin, and your bundler drops the ones you never added, so you only ship what you actually use.
If you catch yourself wanting the player to do a new thing, you want a plugin. See the Plugin System Overview for the full picture.
Adapters swap how something already works
An adapter replaces a piece of behavior the player already has with your own version. We call each swappable piece a port. The player always saves settings somewhere, always talks to the network somehow, always reads a clock. Each of those is a port with a sensible default already in it. You swap the default when it doesn’t fit you, like saving state to your own server instead of the browser. Everything else keeps working, because the player only ever talks to the port, never to your implementation directly.
If you catch yourself wanting an existing job done differently, you want an adapter. See Adapters for every port and how to wire them.
When to use which
One question sorts almost every case: are you adding something new, or changing something that’s already there?
- Adding something the player didn’t do before, that’s a plugin.
- Changing how an existing job gets done, that’s an adapter.
An equalizer is new behavior, so it’s a plugin. Saving to your server instead of the browser is the same job done differently, so it’s an adapter. And the two team up all the time: a plugin can read from a storage port you swapped, where the plugin brings the behavior and the adapter decides where the data actually lives.
For how all of this maps onto the player’s layers, from the generic core up to your own app code, read Architecture.