@vizor-vr/player
v0.4.0
Published
VR video player for the modern web — 360°, VR, live streaming, virtual tours
Maintainers
Readme
@vizor-vr/player
High-performance VR and 360° video player for the web, built on Web Components and Three.js. Embed immersive content with a single HTML tag — no framework required.
<script
type="module"
src="https://cdn.jsdelivr.net/npm/@vizor-vr/[email protected]/dist/vizor.js"
></script>
<vz-video src="video.mp4" format="MONO_360" autoplay></vz-video>For production embeds, pin an exact version (as above) and add an integrity="sha384-..." attribute with the hash of that pinned file so a CDN compromise cannot alter the script (SRI).
Install
npm install @vizor-vr/player// Registers all <vz-*> custom elements as a side effect
import '@vizor-vr/player/register';The /register entry is safe to import under SSR — registration no-ops when there is no DOM. The bare @vizor-vr/player entry exports classes and types without registering anything.
Elements
| Element | Purpose |
| --------------- | --------------------------------------------- |
| <vz-video> | 360°/VR video playback |
| <vz-img> | 360°/VR image display |
| <vz-tour> | Multi-scene virtual tours |
| <vz-cinema> | Flat video in a 3D environment |
| <vz-live> | Live streaming (HLS / DASH) |
| <vz-playlist> | Sequential content playback |
| <vz-hub> | Content lobby: pick from multiple items in 3D |
Data-holder child elements (no UI of their own — parsed by their parent):
| Element | Parent | Purpose |
| ------------------ | --------------------- | --------------------------------------------- |
| <vz-annotation> | vz-video / vz-img | Interactive 3D marker with HTML popup content |
| <vz-chapter> | vz-video | Seek-bar chapter marker |
| <vz-tour-img> | vz-tour | One panoramic scene ("probe") in a tour |
| <vz-tour-portal> | vz-tour-img | Navigation hotspot to another probe |
| <vz-hub-item> | vz-hub | One selectable content entry in a hub |
Attributes
All media elements (vz-video, vz-img, vz-tour, vz-cinema, vz-live) share a common attribute set. Boolean attributes follow HTML semantics: presence means true.
Content and playback
| Attribute | Type | Default | Description |
| ------------------------------------- | ------- | ---------- | --------------------------------------------------------------------------------- |
| src | string | — | Direct media URL (alternative to <source> children) |
| format | string | MONO_360 | Projection format, e.g. MONO_360, STEREO_360_TB, STEREO_180_LR, MONO_FLAT |
| title | string | — | Title shown in the controls bar |
| author / author-href | string | — | Author credit and link |
| poster | string | — | Poster image URL shown before playback |
| preview | string | — | Preview image URL |
| autoplay | boolean | false | Start playback automatically (muted-autoplay policies apply) |
| loop | boolean | false | Loop playback |
| muted | boolean | false | Start muted |
| preload | string | metadata | auto, metadata, or none |
| seekable | boolean | false | Allow seeking on live/limited streams |
| fps | number | 30 | Content frame rate hint |
| crossorigin | string | — | CORS mode for media requests |
| cors-fallback-url | string | — | Fallback page when CORS blocks playback |
| cors-fallback-redirect-confirmation | boolean | true | Confirm before redirecting to the fallback URL |
| audio-format | string | — | Spatial audio layout (ambisonic content) |
Camera and projection
| Attribute | Type | Default | Description |
| --------------------------------------- | ------ | ------------ | ----------------------------------------------------------------- |
| start-lat / start-lon | number | 0 / 0 | Initial camera orientation in degrees |
| focal-length | number | 75 | Initial focal length (zoom) |
| min-focal-length / max-focal-length | number | 30 / 120 | Zoom limits |
| lens-angle | number | 180 | Capture-lens angle in degrees for fisheye/VR180 content (120–250) |
| display-mode | string | inline | Display mode |
| width / height / aspect | string | — | Explicit sizing (CSS sizing on the host element also works) |
Licensing, analytics, and delivery
| Attribute | Type | Description |
| -------------- | ------ | -------------------------------------------- |
| api-key | string | SaaS API key for license validation |
| license-key | string | Standalone (offline) license key |
| license-mode | string | License validation mode |
| api-endpoint | string | Override the license/analytics API endpoint |
| content-id | string | Content ID for hosted delivery and analytics |
Collaborative viewing
| Attribute | Type | Description |
| ---------------------------------------- | ------ | -------------------- |
| collab-server | string | WebSocket server URL |
| collab-room | string | Room name |
| collab-role | string | host or viewer |
| collab-user-id / collab-display-name | string | Participant identity |
| collab-password | string | Room password |
Branding and UI
| Attribute | Type | Default | Description |
| ----------------------------------------------------------------------------------------------------------------------- | ------- | ---------- | ----------------------------------------------------------- |
| primary-color | string | #f43f5e | Accent color for controls |
| secondary-color | string | #1a1a2e | Secondary/background color |
| brand-name / brand-logo / brand-url | string | — | Custom branding (licensed tiers) |
| controls-behavior | string | autohide | autohide, always, or minimal |
| hide-controls | boolean | false | Hide the controls bar entirely |
| hide-compass, hide-vr-button, hide-settings, hide-fullscreen, hide-title, hide-brand-logo | boolean | false | Hide individual UI pieces |
Element-specific attributes
| Element | Attributes |
| ------------------ | ------------------------------------------------------------------------------------------------ |
| <vz-cinema> | room-src, room-format, screen-width, screen-height, screen-distance, screen-offset-y |
| <vz-playlist> | autoplay (auto-advance), loop-playlist, panel (none / expandable) |
| <vz-annotation> | lat, lon, time-start, time-end, title, icon, sort-order |
| <vz-chapter> | start, title, sort-order, chapter-id |
| <vz-tour-img> | probe-id, format, src, src-left, src-right, title, rotation-y |
| <vz-tour-portal> | to, lat, lon, title, distance |
| <vz-hub-item> | src, poster, title, format, content-id |
Events
Elements re-dispatch the standard HTML5 media events (play, pause, playing, ended, timeupdate, seeking, seeked, durationchange, volumechange, canplay, waiting, error, …) from the underlying <video> on the custom element itself, plus typed vz-* CustomEvents (all bubble and cross the shadow boundary):
| Event | detail | Emitted when |
| -------------------------------------------- | --------------------------------- | ------------------------------------- |
| vz-ready | — | Player is initialized and ready |
| vz-error | { code, message } | An error occurred (load, DRM, XR, …) |
| vz-quality-change | { quality, auto } | Adaptive/manual quality level changed |
| vz-fullscreen-enter / vz-fullscreen-exit | — | Fullscreen toggled |
| vz-xr-enter / vz-xr-exit | — | WebXR immersive session started/ended |
| vz-license | { valid, tier, message? } | License validation resolved |
| vz-chapter-change | { chapterId, title, startTime } | Playback crossed into a chapter |
| vz-tour-navigate | { fromProbeId, toProbeId } | Tour navigated between scenes |
| vz-hub-select | { id, src, title, index } | A hub item was selected |
| vz-playlist-change | { index, title, total } | Playlist advanced to another item |
| vz-playlist-end | — | Playlist finished (non-looping) |
const player = document.querySelector('vz-video');
player.addEventListener('vz-ready', () => console.log('ready'));
player.addEventListener('vz-error', (e) => console.error(e.detail.code, e.detail.message));Methods
Available on the video-based elements (vz-video, vz-cinema, vz-live):
player.play(); // Start or resume (returns a Promise)
player.pause();
player.seek(30); // Seek to 30 seconds
player.toggleFullscreen();<vz-playlist> adds next(), previous(), and goTo(index).
Features
- Multiple projection formats (equirectangular 360/180, cubemap/EAC, fisheye, flat) with mono and stereo variants
- WebXR immersive sessions (via Three.js)
- Adaptive streaming through optional
hls.js/dashjspeer dependencies - Ambisonic spatial audio via the optional
omnitonepeer dependency - Progressive enhancement — degrades gracefully without WebXR
Optional peer dependencies
Install only what you use:
npm install hls.js dashjs omnitone @noble/ed25519hls.js— HLS adaptive streamingdashjs— MPEG-DASH adaptive streamingomnitone— ambisonic spatial audio@noble/ed25519— required for standalone (offline) license keys. Without it, standalone license verification fails closed and the player runs in the free tier with a watermark. SaaS (api-key) licensing does not need it.
Framework wrappers
- React —
@vizor-vr/react - Vue 3 —
@vizor-vr/vue - Svelte 5 —
@vizor-vr/svelte - Laravel —
vizor-vr/laravel-vizor
Documentation
Full guides, format reference, and API docs: docs.vizor-vr.com. Source lives in the vizor-vr monorepo on GitHub.
Security
See the monorepo security policy for how to report vulnerabilities ([email protected]).
License
MIT — see LICENSE.
