@vioraio/player
v2.7.4
Published
Viora Player — HLS video player for education (VOD & live classrooms)
Maintainers
Readme
Viora Player
@vioraio/player — HLS video player for education platforms (schools, universities, online classrooms).
Part of the Viora family by vioraio:
| Product | Role | | --- | --- | | Viora Player | HLS playback (this package) | | Viora Stream | VOD / streaming (coming) | | Viora Live | Online classroom (coming) |
Install
pnpm add @vioraio/playerPeer deps: react, react-dom, hls.js, framer-motion, clsx, moment.
Styles (Tailwind v4 hosts — recommended)
Do not import @vioraio/player/styles.css inside apps that already run Tailwind
(HeroUI / Next.js). That file ships a second theme layer and breaks host styles.
Scan the package from your global CSS instead:
@import "tailwindcss";
@source "../node_modules/@vioraio/player/dist/**/*.{js,cjs,mjs}";Styles (no Tailwind)
import "@vioraio/player/styles.css";Usage
Public / embed
import { VioraPlayer } from "@vioraio/player";
<VioraPlayer
id={1}
title="..."
poster="..."
data={{ type: "hls", src: "https://.../master.m3u8" }}
/>With playlist
<VioraPlayer
id={active.id}
title={active.title}
data={{ type: "hls", src: active.src }}
playerName="شهریار پلیر"
playlist={items}
activePlaylistId={active.id}
playlistTitle="تیزرها"
autoPlayNext
showAutoPlayNext
loopPlaylist
autoOpenPlaylistOnEnded
onPlaylistItemSelect={(item, index) => setActiveIndex(index)}
onAutoPlayNextChange={(enabled) => console.log(enabled)}
/>Theme & controls
<VioraPlayer
id={1}
data={{ type: "hls", src }}
theme={{
colors: {
primary: "#006FEE",
secondary: "#17C964",
danger: "#F31260",
surface: "rgba(0,0,0,0.82)",
foreground: "#ffffff",
overlay: "rgba(0,0,0,0.55)",
},
}}
controls={{
download: false,
speed: true,
quality: true,
}}
/>On phone, enabled speed + quality + download fold into one تنظیمات control.
With watch-session persistence
import { VioraPlayer, type WatchSessionFlushPayload } from "@vioraio/player";
<VioraPlayer
id={videoId}
videoSubjectId={subjectId}
studentId={studentId}
watchedDuration={watched}
data={{ type: "hls", src }}
onSaveWatchSession={async (payload: WatchSessionFlushPayload) => {
await api.post(`/course/video/watch/session/${videoId}`, payload);
}}
/>Props
Source & session
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| id | number | — | Video id (also used for localStorage keys) |
| title | string | — | Cover / top-bar title |
| poster | string \| null | — | Cover image |
| posterFallback | string \| null | — | Fallback cover |
| data | { type: "hls"; src: string } | — | Stream source |
| prepareState | "loading" \| "error" \| "ready" | "ready" | Host-driven ready state |
| watchedDuration | number | — | Resume position (seconds) |
| videoSubjectId | number | — | Required when flushing watch sessions |
| studentId | number \| null | null | Scopes localStorage settings |
| onSaveWatchSession | (payload) => Promise<void> | — | Optional server flush |
Branding & chrome
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| playerName | string | ویورا پلیر | Info panel brand name |
| showTitle | boolean | true | Show title in the playing top bar |
| theme | VioraPlayerTheme | defaults | 6 color tokens |
| controls | VioraPlayerControlsConfig | all true | Toggle play, seek, skip, mute, fullscreen, speed, quality, download, info, playlist |
Playback
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| playbackRate | number | from settings / 1 | Rate 0.5–3 (0.5 steps) |
| defaultQuality | number \| "auto" | from settings / "auto" | Initial quality |
| onEnded | () => void | — | Fired when the current video ends |
| pauseWhenOutOfView | boolean | true | Pause when scrolled fully out of view; resume when visible again |
Playlist
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| playlist | VioraPlaylistItem[] | — | Items (id, title, data, optional poster / duration) |
| activePlaylistId | number | — | Controlled active item |
| defaultActivePlaylistId | number | first item | Uncontrolled initial item |
| onPlaylistItemSelect | (item, index) => void | — | Selection / skip / auto-next |
| playlistTitle | string | لیست پخش | Drawer header title |
| showPlaylistButton | boolean | true if playlist | Show playlist chrome button |
| playlistOpen | boolean | — | Controlled drawer open |
| defaultPlaylistOpen | boolean | false | Uncontrolled initial open |
| onPlaylistOpenChange | (open) => void | — | Drawer open changes |
| autoPlayNext | boolean | false | Auto-play next after countdown |
| showAutoPlayNext | boolean | true if playlist | Show the in-drawer toggle (hide = fixed by autoPlayNext) |
| onAutoPlayNextChange | (enabled) => void | — | Viewer toggled auto-next |
| loopPlaylist | boolean | false | Wrap last → first |
| autoOpenPlaylistOnEnded | boolean | true if playlist | Open drawer when a video ends |
Develop
pnpm install
pnpm build
pnpm typecheckRelease
Push to main publishes @vioraio/player to npm automatically.
- If the current
package.jsonversion is already on npm, CI bumps the patch version, commits it ([skip ci]), then publishes. - Requires repo secret
NPM_TOKEN(Granular Access Token with publish for@vioraio, bypass 2FA).
License
MIT
