Architecture
Core Dependencies
-
Shaka Player: Our foundational player engine used across all components. We selected Shaka Player as our streaming engine after extensive evaluationâread more about this decision.
-
Zustand: Our state management solution for the player. Despite Zustand's minimal footprint (only 1.2kb), we initially aimed to avoid opinionated state management systems. However, after thorough research and testing, Zustand emerged as the optimal choice for our needs.
State Management Implementation
We integrate Zustand with React Context to create proper isolation between Media Player instances. This approach addresses several architectural challenges:
-
Singleton Pattern: Zustand uses a singleton store where states are shared across components, unlike React Hooks which maintain separate state in each component.
-
Multiple Player Support: To support multiple Media Player instances on the same page, we implemented an isolation layer using React Context, ensuring each player maintains its own state.
-
Modular Design: Zustand's slice pattern enables efficient component distribution and organization, allowing us to separate concerns within our state management.
-
Component Hierarchy
-
MediaProvider
component sets the isolated store of React Context and Zustand. In case you don't want the isolation of player you can update the reference ofuseMediaStore
in the code fromuseMediaStoreWithContext
=>useMediaStoreWithoutContext
. -
Layout.RootContainer
component sets an accessible element layer which describes the Media Player. This layer essentially is responsible to add a skin on top of media element to control the state of player controls like toggling the hidden state. -
Layout.PlayerContainer
component is a shim for media element,aspect-ratio
is primarily configured here. -
Layout.ControlsContainer
component provides you with a spaced area to add control sections like Top Controls, Middle Controls, Bottom Controls. -
MediaElement
component is the native media element -
PlayerHooks
component is the central memoized component to mount hooks optimising the performance. Since limeplay hooks are mostly singleton and calling them everytime during a re-render would cause an additional overhead.