[1]: https://www.mux.com/blog/6-years-building-video-players-9-bi...
67 karma · joined July 6, 2019
[1]: https://www.mux.com/blog/6-years-building-video-players-9-bi...
Some background: our store[1] which was inspired by Zustand[2] is created and passed down via context too. This is the central state management piece of our library and where we imagine most devs will build on for extending and customizing to their needs.
Updates are handled via simple store actions like `store.play()`, `store.setVolume(10)`, etc. Those actions are generally called in response to DOM events.
On the events side of things, rather than registering event listeners directly, in v10 you'd subscribe to the store instead. Something like `store.subscribe(callback)`, or in React you'd use our `usePlayer`[3] hook. The store is the single source of truth, so rather than listening to the underlying media element directly, you're observing state changes.
---
So far with v10 we haven't been thinking about "plugins" in the traditional sense either. If I had to guess at what it would look like, it'd be three things:
1. Custom store slices[4] so plugins can extend the store with their own state and actions
2. A middleware layer that plugs into the store's action pipeline so a plugin could intercept or react to actions before or after they're applied, similiar to Zustand middleware, or even in some ways like Video.js v8 middleware[5]
3. UI components that plugins can ship which use our core primitives for accessing the store, subscribing to state, etc.
I believe that'd cover the vast majority of what plugins needed in v8. We haven't nailed down the exact API yet but that's the direction we're leaning towards. We're still actively working on both the library and our docs so I don't have somewhere I can link to for these just yet (sadly)! We're likely targeting sooner, but GA (end of June) is the deadline.
I should also add... one thing we prototyped early on that may return: tracking end-to-end requests through the store. A DOM event triggers a store action like play, which calls `video.play()`, which then waits for the media event response (play, error, etc.). It worked really well and lines up nicely with the middleware direction.
[1]: https://github.com/videojs/v10/tree/main/packages/store
[2]: https://github.com/pmndrs/zustand
[3]: https://videojs.org/docs/framework/react/reference/use-playe...
[4]: https://zustand.docs.pmnd.rs/learn/guides/slices-pattern#sli...
Basically few kB for CSS and few kB for a thin “framework” layer for managing attr to prop mapping, simple lifecycle, context, and so on.
In the meantime, we’re hoping our custom elements will act as a good stopgap. Most frameworks including Svelte support them well, and we’re pouring love into the APIs so they feel good to use regardless of which framework.
If you’re interested in peeking under the hood, architecturally we’re taking a similar approach to TanStack and separating out a shared core from the beginning, but with one added step of splitting out the DOM as well to aid in supporting RN one day.
We’re taking a new approach to the library with a lot of new concepts, so your feedback would help us a ton during Beta as we figure out what’s working well and what isn’t.
The motivation for this started with some initial exploration of how native captions are inconcistent and extremely limited with respect to positioning + styling across browsers. In addtion, existing captions work was glued inside player libs and all open-source parsers were ancient (e.g., mozilla/vtt)!
I wanted to modernize it all with newer web APIs such as `fetch` and `ReadableStream` and extend support out to multiple captions formats. I also noticed that a lot of popular players on the web in recent years started adding caption customization options. Turns out accessible captions can be legally enforced!
Do note that accessible captions not only includes sync/timing, but also an adequate set of controls to customize the style of the captions, ensuring they're readable for everyone. You can see an example of this on YouTube when you go to the settings, captions, and click customize.
It just seemed silly that probably every single company is internally building this type of lib which is insanely hard to get right. I built this to serve our accessiblity goals at Vidstack[1] where we're working on enabling you to build a production-ready player quickly.
It took me about two weeks to build this and honestly there's still a lot of areas that need work but it's a great start. I hope you find it useful. You'll find a lot more helpful information in the repo.
I'll also leave you with this YouTube video where Dan Sparacio beautifully explains the complexities of building accessible media captions on the web at Paramount [2]. This is one of my favourite Demuxed talks. In there case, acessible enough to meet FCC guidelines. _Highly_ recommend checking it out to learn more!
> I don't entirely understand what it means to dispose of observables, is that just an internal optimization for cleanups basically? Exposing an API for this feels a bit risky, like it feels easy to misuse.
It's a cleanup function that ensures that the observable can be garbage collected by clearing references to it in the dependency sets. It also marks the observable as disposed so that it's no longer reactive and ensures no new references can be made. I think brundolf gave a really good use-case for this API but you're right people can and will definitely misuse it... ¯\_(ツ)_/¯
> I personally prefer to opt into batching only sparingly and for performance reasons.
I'll definitely look at providing an API to provide a custom scheduler. I have to be careful not to bump up size in doing so _might_ be tricky.
> A function for creating roots seems missing, I think that's important.
I don't think it's needed here because it can be created with an `$effect`. It returns a `stop` function that can be called with `true` to dispose of all inner computations. I think I should provide a `$root` function that's just sugar for the mentioned.
> "isComputed" feels like a weird function to have
Ye I agree. I'll remove it and expose `isObservable` and `isReadonly` functions.
> I've made something similar myself, also inspired by Solid and Sinuous...
`oby` is super cool. It's so feature packed that it's going to take some time to dig through all of it. I love finding libraries like these, thanks for sharing it.
[0]: https://codesandbox.io/s/maverick-js-observables-bench-cellx...
For example, if the core goal of the library is to achieve <2kB and you've predetermined a tight API scope (most likely based on existing references) then IMO it's okay to call it tiny/lightweight. It works out with libraries that are a providing a set of primitives to solve a generalized problem. I'm sure some people appreciate like I do when a library clearly indicates a core goal that was achieved (i.e. size) right in the top-level description.
For anyone curious the reasons are listed here -> https://github.com/vime-js/vime#motivation.
If you're looking for multi-provider support, plugins, custom controls and other goodies then this might be for you. It's not perfect but it feels stable enough to share. If you guys end up using it then please share your experiences so I can learn how to improve the library.
Cheers!