npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@guardvideo/player-sdk

v3.7.0

Published

GuardVideo Player SDK - Secure HLS video player with embed token authentication for React, Next.js, and vanilla JavaScript

Downloads

1,467

Readme

GuardVideo Player SDK

🎬 Secure HLS video player with embed token authentication — React, Next.js, and vanilla JavaScript

npm version License: MIT

Features

Custom Professional Player UI — No native browser controls; full custom design
Adaptive Bitrate Streaming — Automatic quality switching based on network conditions
Secure Token Authentication — API key never exposed to the browser
Multi-Quality Support — 1080p, 720p, 480p, 360p
AES-128 Encryption — Secure video segment delivery
Forensic Watermark — Viewer-identifying overlay baked into playback (default: on)
React & Next.js Support — First-class TypeScript support
Vanilla JS / CDN Support — Full custom UI without any framework
TypeScript Types — Full type safety included
Browser Support — All modern browsers + Safari/iOS native HLS


Installation

NPM / Yarn (React / Next.js)

npm install @guardvideo/player-sdk
# or
yarn add @guardvideo/player-sdk

CDN (Vanilla JavaScript)

<!-- full bundle (recommended for development) -->
<script src="https://cdn.jsdelivr.net/npm/@guardvideo/player-sdk@latest/dist/vanilla/guardvideo-player.js"></script>

<!-- minified bundle (recommended for production) -->
<script src="https://cdn.jsdelivr.net/npm/@guardvideo/player-sdk@latest/dist/vanilla/guardvideo-player.min.js"></script>

Quick Start

React / Next.js Component

import { GuardVideoPlayer } from '@guardvideo/player-sdk';

function VideoPage() {
  return (
    <GuardVideoPlayer
      videoId="your-video-id"
      embedTokenEndpoint="/api/embed-token"
      width="100%"
      height="500px"
      viewerEmail="[email protected]"
      viewerName="Jane Doe"
      forensicWatermark    // default: true
      onReady={() => console.log('Video ready!')}
      onError={(error) => console.error(error)}
      onQualityChange={(quality) => console.log('Quality:', quality)}
      onStateChange={(state) => console.log('State:', state)}
    />
  );
}

Note: The component renders a fully custom player UI with play/pause, seek bar, volume control, quality selector, playback speed menu, and fullscreen. You do not need to add the native controls attribute or wrap it in any overlay.

React Hook (build your own controls)

import { useGuardVideoPlayer } from '@guardvideo/player-sdk';

function CustomPlayer({ videoId }: { videoId: string }) {
  const {
    videoRef,
    isReady,
    isPlaying,
    currentTime,
    duration,
    qualityLevels,
    play,
    pause,
    seek,
    setVolume,
    setQuality,
  } = useGuardVideoPlayer({
    videoId,
    embedTokenEndpoint: '/api/embed-token',
    viewerEmail: '[email protected]',
  });

  const formatTime = (s: number) =>
    `${Math.floor(s / 60)}:${String(Math.floor(s % 60)).padStart(2, '0')}`;

  return (
    <div>
      <video ref={videoRef} style={{ width: '100%' }} />
      {isReady && (
        <div>
          <button onClick={isPlaying ? pause : play}>
            {isPlaying ? 'Pause' : 'Play'}
          </button>
          <input
            type="range" min={0} max={duration} value={currentTime}
            onChange={(e) => seek(Number(e.target.value))}
          />
          <span>{formatTime(currentTime)} / {formatTime(duration)}</span>
          <select onChange={(e) => setQuality(Number(e.target.value))}>
            <option value="-1">Auto</option>
            {qualityLevels.map((l) => (
              <option key={l.index} value={l.index}>{l.name}</option>
            ))}
          </select>
        </div>
      )}
    </div>
  );
}

Next.js App Router

// app/watch/[videoId]/page.tsx
'use client';

import { GuardVideoPlayer } from '@guardvideo/player-sdk';

export default function WatchPage({ params }: { params: { videoId: string } }) {
  return (
    <GuardVideoPlayer
      videoId={params.videoId}
      embedTokenEndpoint="/api/embed-token"
      width="100%"
      height="600px"
      viewerEmail="[email protected]"
      onReady={() => console.log('Ready!')}
      onError={(e) => console.error(e)}
    />
  );
}

Vanilla JavaScript (CDN)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>GuardVideo Player</title>
  <style>
    #player-container {
      width: 100%;
      max-width: 900px;
      aspect-ratio: 16/9;
      margin: 40px auto;
    }
  </style>
</head>
<body>
  <div id="player-container"></div>

  <script src="https://cdn.jsdelivr.net/npm/@guardvideo/player-sdk@latest/dist/vanilla/guardvideo-player.min.js"></script>
  <script>
    const player = GuardVideoPlayer.create('player-container', 'your-video-id', {
      embedTokenEndpoint: '/api/embed-token',
      viewerEmail: '[email protected]',
      viewerName: 'Jane Doe',

      onReady: function () {
        console.log('Ready! Qualities:', player.getQualityLevels());
      },
      onError: function (err) {
        console.error('Player error:', err);
      },
      onQualityChange: function (quality) {
        console.log('Quality changed to:', quality);
      },
      onStateChange: function (state) {
        console.log('State:', state);
      },
    });
  </script>
</body>
</html>

The vanilla build bundles everything (hls.js included). No npm install, no bundler needed. The player renders the same full custom UI as the React component.


Backend Setup

Your backend needs to create embed tokens using your API key:

// Next.js API Route: app/api/embed-token/[videoId]/route.ts
export async function POST(
  request: Request,
  { params }: { params: { videoId: string } }
) {
  const VIDEO_API_KEY  = process.env.VIDEO_API_KEY!;
  const VIDEO_API_BASE = process.env.NEXT_PUBLIC_VIDEO_API_BASE!;

  const response = await fetch(
    `${VIDEO_API_BASE}/videos/${params.videoId}/embed-token`,
    {
      method: 'POST',
      headers: {
        'X-API-Key': VIDEO_API_KEY,   // API key stays on the server!
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        allowedDomain: request.headers.get('origin'),
        expiresInMinutes: 120,
        maxViews: null,
        viewerEmail: /* optionally forward from session */ undefined,
        forensicWatermark: true,
      }),
    }
  );

  return Response.json(await response.json());
}

Environment Variables

VIDEO_API_KEY=your-secret-api-key
NEXT_PUBLIC_VIDEO_API_BASE=http://localhost:3001

API Reference

React Component Props (GuardVideoPlayerProps)

| Prop | Type | Default | Description | |------|------|---------|-------------| | videoId | string | — | Required. Video ID to load | | embedTokenEndpoint | string | — | Required. Your backend endpoint that mints embed tokens | | width | string \| number | "100%" | Player container width | | height | string \| number | "auto" | Player container height | | apiBaseUrl | string | — | Override default API base URL | | autoplay | boolean | false | Auto-play on load | | debug | boolean | false | Enable verbose debug logging | | viewerName | string | — | Viewer name (used for forensic watermark) | | viewerEmail | string | — | Viewer email (used for forensic watermark) | | forensicWatermark | boolean | true | Show viewer-identifying watermark overlay | | branding | BrandingConfig | — | Custom accent colour and brand name | | security | SecurityConfig | — | Security hardening options | | contextMenuItems | ContextMenuItem[] | — | Extra context menu items | | hlsConfig | HlsConfig | — | HLS.js configuration overrides | | onReady | () => void | — | Called when video is ready to play | | onError | (err: PlayerError) => void | — | Called on error | | onQualityChange | (quality: string) => void | — | Called when quality changes | | onStateChange | (state: PlayerState) => void | — | Called on state transitions | | onTimeUpdate | (time: number) => void | — | Called on time updates | | onEnded | () => void | — | Called when video ends |

Vanilla JS Config (PlayerConfig)

All React props above except JSX-specific ones (className, style) are available. Extra vanilla-only props:

| Prop | Type | Default | Description | |------|------|---------|-------------| | width | string | "100%" | Player container width CSS value | | height | string | "auto" | Player container height CSS value |

Player Methods

player.play(): Promise<void>           // Start playback
player.pause(): void                   // Pause
player.seek(time: number): void        // Seek to time in seconds
player.getCurrentTime(): number        // Current playback position (seconds)
player.getDuration(): number           // Total duration (seconds)
player.getVolume(): number             // Current volume (0–1)
player.setVolume(v: number): void      // Set volume (0–1)
player.getQualityLevels(): QualityLevel[]       // Available quality levels
player.getCurrentQuality(): QualityLevel | null // Active quality
player.setQuality(index: number): void          // Set quality (-1 = auto)
player.getState(): PlayerState         // Current player state
player.getVideoElement(): HTMLVideoElement | null  // Underlying <video> element
player.destroy(): void                 // Clean up and remove player

Player States

enum PlayerState {
  IDLE      = 'idle',       // Not yet initialized
  LOADING   = 'loading',    // Loading video
  READY     = 'ready',      // Ready to play
  PLAYING   = 'playing',    // Currently playing
  PAUSED    = 'paused',     // Paused
  BUFFERING = 'buffering',  // Re-buffering mid-play
  ERROR     = 'error',      // Unrecoverable error
}

BrandingConfig

interface BrandingConfig {
  accentColor?: string;   // Hex color, default: '#44c09b'
  name?: string;          // Brand name shown in secure badge, default: 'GuardVideo'
  logoUrl?: string;       // Logo URL (used in context menu)
  websiteUrl?: string;    // Website URL (used in context menu)
}

SecurityConfig

interface SecurityConfig {
  disableContextMenu?: boolean;    // Block right-click (default: true)
  disableDevTools?: boolean;       // Detect/block DevTools (default: false)
  disablePiP?: boolean;            // Block Picture-in-Picture (default: false)
  disableDragDrop?: boolean;       // Block drag-and-drop (default: true)
  disableScreenshot?: boolean;     // Attempt screenshot blocking (default: false)
}

Keyboard Shortcuts

When the player has focus:

| Key | Action | |-----|--------| | Space / K | Play / Pause | | | Seek back 5 s | | | Seek forward 5 s | | | Volume +10% | | | Volume −10% | | M | Toggle mute | | F | Toggle fullscreen |


Using Ref for Imperative Control (React)

import { useRef } from 'react';
import { GuardVideoPlayer, GuardVideoPlayerRef } from '@guardvideo/player-sdk';

function VideoWithRef() {
  const playerRef = useRef<GuardVideoPlayerRef>(null);

  return (
    <div>
      <GuardVideoPlayer
        ref={playerRef}
        videoId="your-video-id"
        embedTokenEndpoint="/api/embed-token"
      />
      <button onClick={() => playerRef.current?.seek(playerRef.current.getCurrentTime() + 10)}>
        +10 s
      </button>
    </div>
  );
}

TypeScript Support

import type {
  PlayerConfig,
  PlayerInstance,
  PlayerState,
  PlayerError,
  QualityLevel,
  BrandingConfig,
  SecurityConfig,
} from '@guardvideo/player-sdk';

Browser Support

| Browser | Minimum version | |---------|----------------| | Chrome | 90+ | | Firefox | 88+ | | Safari | 14+ (native HLS) | | Edge | 90+ | | iOS Safari | 14+ | | Android Chrome | 90+ |


License

MIT © GuardVideo


Support


Using Ref for Imperative Control (React)

import { useRef } from 'react';
import { GuardVideoPlayer, GuardVideoPlayerRef } from '@guardvideo/player-sdk';

function VideoWithRef() {
  const playerRef = useRef<GuardVideoPlayerRef>(null);

  return (
    <div>
      <GuardVideoPlayer
        ref={playerRef}
        videoId="your-video-id"
        embedTokenEndpoint="/api/embed-token"
      />
      <button onClick={() => playerRef.current?.seek(playerRef.current.getCurrentTime() + 10)}>
        +10 s
      </button>
    </div>
  );
}

TypeScript Support

import type {
  PlayerConfig,
  PlayerInstance,
  PlayerState,
  PlayerError,
  QualityLevel,
  BrandingConfig,
  SecurityConfig,
} from '@guardvideo/player-sdk';

Browser Support

| Browser | Minimum version | |---------|----------------| | Chrome | 90+ | | Firefox | 88+ | | Safari | 14+ (native HLS) | | Edge | 90+ | | iOS Safari | 14+ | | Android Chrome | 90+ |


License

MIT © GuardVideo


Support

| Safari | 14+ (native HLS) | | Edge | 90+ | | iOS Safari | 14+ | | Android Chrome | 90+ |


License

MIT (C) GuardVideo


Support

  • GitHub Issues: https://github.com/guardvideo/player-sdk
  • Documentation: https://docs.guardvideo.com