Player
Dependencies
- npm
- Yarn
- pnpm
- Bun
npm install @mui/material @emotion/react @emotion/styled @mui/icons-material lodash
yarn add @mui/material @emotion/react @emotion/styled @mui/icons-material lodash
pnpm add @mui/material @emotion/react @emotion/styled @mui/icons-material lodash
bun add @mui/material @emotion/react @emotion/styled @mui/icons-material lodash
Usage
import {
AudioHolder,
MiniPlayer,
PlayerContextProvider,
usePlayer,
VideoPlayer,
} from "@arclockproject/common/components/Player";
A video and audio player made of parts that share one state:
PlayerContextProviderholds the state. Put it high in the tree so playback survives page changes.VideoPlayershows the video and controls.AudioHolderplays the audio. Keep it mounted so audio keeps playing whenVideoPlayeris removed.MiniPlayeris a small player bar fixed to the bottom-right of the screen.usePlayergives your own components access to the state.
The examples below are live. Edit the code to try your own values.
Single video
Pass videoData to load an entry as soon as the player mounts.
▶ Show code (click to view and edit)
Live Editor
<PlayerContextProvider> <div style={{ width: "80%", maxWidth: "600px", }} > <VideoPlayer videoData={{ files: { video: `${REMOTE.base}/PXQZNGjZIFo.mp4`, audio: `${REMOTE.base}/PXQZNGjZIFo.m4a`, subtitles: null, thumbnail: `${REMOTE.base}/PXQZNGjZIFo.webp`, }, id: "original-2-eis3", title: "Original Piece #2 by Eis3", meta: null, }} isPlaylist={false} chapters={[]} heatmap={[]} showInlineTitle /> <AudioHolder /> </div> </PlayerContextProvider>
Result
Loading...
Mini player and playlist
Load a video, then press VideoPlayer Unload. As long as <AudioHolder /> stays mounted,
the audio keeps playing in the mini player. When the player is loaded again, it syncs back.
▶ Show code (click to view and edit)
Live Editor
function main() { function PageWithPlayer() { let exampleVideos = [ { files: { video: `${REMOTE.base}/PXQZNGjZIFo.mp4`, audio: `${REMOTE.base}/PXQZNGjZIFo.m4a`, subtitles: null, thumbnail: `${REMOTE.base}/PXQZNGjZIFo.webp`, }, id: "original-2-eis3", title: "Original Piece #2 by Eis3", meta: null, }, { files: { video: `${REMOTE.base}/jkZ53T1Pu7k.mp4`, audio: `${REMOTE.base}/jkZ53T1Pu7k.m4a`, subtitles: null, thumbnail: `${REMOTE.base}/jkZ53T1Pu7k.webp`, }, id: "original-3-eis3", title: "Original Piece #3 by Eis3", meta: null, }, ]; const player = usePlayer(); return ( <div> <div style={{ width: "80%", maxWidth: "600px", }} > <VideoPlayer isPlaylist={false} chapters={[]} heatmap={[]} showInlineTitle /> {player.internal.playerData.value !== null && ( <button onClick={() => player.internal.playlistContent.set(exampleVideos)} > Load All (playlist) </button> )} {exampleVideos.map((entry) => ( <button onClick={() => player.internal.playerData.set(entry)} key={entry.id} > {entry.title} </button> ))} </div> </div> ); } function App() { const [page, setPage] = useState(0); return ( <> <div> <button onClick={() => setPage(0)}>VideoPlayer Unload</button> <button onClick={() => setPage(1)}>VideoPlayer Load</button> </div> <div style={{ width: "80%", maxWidth: "600px" }}> {page === 0 ? <p>VideoPlayer not rendering</p> : <PageWithPlayer />} </div> </> ); } return ( <PlayerContextProvider> <div style={{ height: "400px" }}> <App /> </div> <MiniPlayer /> <AudioHolder /> </PlayerContextProvider> ); }
Result
Loading...
Sticky mobile player
With sticky: true, the video stays at the top on mobile while the page scrolls below it.
▶ Show code (click to view and edit)
Live Editor
<PlayerContextProvider settings={{ autoAudioOnly: false, autoPlay: false, videoBackgroundBloom: true, allowMiniPlayer: true, sticky: true, // changed stickySpacing: 0, // Gap above the sticky player in px (e.g. for a navbar). Hidden while scrolling down. stickyTriggerDistance: 0, // Pixels to scroll before the gap hides or comes back. 0 is immidiate }} > <div style={{ height: "500px", overflowY: "scroll" }}> <VideoPlayer videoData={{ files: { video: `${REMOTE.base}/PXQZNGjZIFo.mp4`, audio: `${REMOTE.base}/PXQZNGjZIFo.m4a`, subtitles: null, thumbnail: `${REMOTE.base}/PXQZNGjZIFo.webp`, }, id: "original-2-eis3", title: "Original Piece #2 by Eis3", meta: null, }} isPlaylist={false} chapters={[]} heatmap={[]} showInlineTitle /> <div style={{ height: "500px" }}> I am 500px tall. If you view me on mobile, you will see that the video stays there and this text will go below the video as you scroll. Try to scroll and see me disappear! <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> Still here! </div> </div> <AudioHolder /> </PlayerContextProvider>
Result
Loading...
API
See the Player API reference for every prop, method and type.