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

@nikelroot/video-player

v0.4.1

Published

Standalone React video player with HLS support.

Readme

@nikelroot/video-player

Standalone React video player with HLS support, retry/recovery behavior, fullscreen, seek controls, and overridable error messages.

Install

npm install @nikelroot/video-player

GitLab CI and automatic npm releases

The repository is hosted at https://gitlab.nikelroot.ru/home/nvideoplayer. Every push to the default branch runs validation and publishes a new public version of @nikelroot/video-player to npmjs.com. Merge requests and other branches only run validation. Tag pipelines are disabled.

The release chooses the highest stable version from package.json and npm, then increases its patch number (for example, 0.3.2 → 0.3.3) inside the CI workspace, builds the package, and publishes it directly to npm. The source repository is not modified: CI does not push commits or create Git tags. The published version is visible on npmjs.com; package.json in Git remains the starting version. Releases are serialized to avoid version collisions. The npm package records the source commit as gitHead; retrying a job for an already-published commit skips publication. If publishing failed before the version reached npm, retry the failed publish job to calculate the next available version and publish again.

One-time setup in GitLab:

  1. Configure a Docker-compatible runner capable of using node:24-bookworm.
  2. Protect the default branch (usually main).
  3. In Settings → CI/CD → Variables, add this Masked and Protected variable with variable expansion disabled:
    • NPM_TOKEN: an npm granular access token with read/write permission for @nikelroot/video-player and Bypass two-factor authentication enabled. The package publishing settings must permit token publishing. Renew the token before its expiration.
  4. Push the repository and CI configuration to GitLab. Do not add secrets to Git.

Only NPM_TOKEN is required. No GitLab push token or job-token push permission is needed.

This self-hosted GitLab uses token authentication because npm trusted publishing currently supports GitLab.com shared runners only. See the npm CI token guide and trusted publishing documentation.

Peer dependencies:

npm install react react-dom styled-components

Usage

import { useRef } from 'react';
import VideoPlayer from '@nikelroot/video-player';

export function Example() {
  const videoRef = useRef<HTMLVideoElement | null>(null);

  return (
    <VideoPlayer
      videoSrc="https://example.com/stream.m3u8"
      videoRef={videoRef}
      active={true}
      live={false}
      autoPlay={false}
      onTimeChange={(time) => console.log(time)}
    />
  );
}

Only videoSrc is required. controlsVariant defaults to "none"; set it to "full", "fullscreen-only", or "tiny" to render built-in controls.

When active is true, pressing F toggles fullscreen.

Multiple MP4 players

Use active when rendering several video players on the same page and only one of them should be ready for playback.

<VideoPlayer
  videoSrc="https://cdn.example.com/video-a.mp4"
  sourceType="native"
  active={isSelected}
  preload="metadata"
/>

This solves a switching problem where previous MP4 players can keep large browser media requests open after another player starts. In Chrome DevTools this often appears as new video requests staying in a long Pending state, even when CDN, disk, and network throughput are healthy.

For native MP4 sources:

  • active={true} allows playback and fullscreen.
  • active={false} releases playback loading so inactive players do not keep competing media requests open.
  • preload="metadata" still loads metadata for inactive native videos, so duration and basic media information can be available without starting playback loading.

By default exclusivePlayback is enabled. When a player starts playback, the previous active native MP4 player is paused and its media source is released, freeing the browser media request before the next video loads.

Public CDN requests use hlsCredentials="same-origin" and crossOrigin="anonymous" by default. For streams that require cross-origin cookies, explicitly set hlsCredentials="include" and crossOrigin="use-credentials" and configure credentialed CORS on the CDN:

<VideoPlayer
  videoSrc="https://cdn.example.com/stream.m3u8"
  hlsCredentials="include"
  crossOrigin="use-credentials"
/>

If you use hlsCredentials="include" or crossOrigin="use-credentials", the CDN must allow credentialed CORS and should not forward Cookie into the cache key for public media.

For hlsCredentials="omit", the player selects the hls.js fetch loader when the browser supports it and no custom loader or XHR setup is configured. XHR cannot suppress same-origin cookies; use a fetch-based loader when omitting all credentials is required in other configurations. Custom loaders are responsible for their own credential handling. Native HLS requests are controlled by crossOrigin and the browser.

HLS buffer targets default to 30–60 seconds ahead for VOD and 20–30 seconds for live, with 15 and 10 seconds of back buffer respectively. Segment boundaries, browser buffering and decoding also affect memory usage; these values are not hard memory limits. Override them using hlsConfig, vodHlsConfig or liveHlsConfig.

HLS downloads stop when playback is paused and resume when playback continues. Set active={false} to release HLS resources for an inactive player. Live seek controls use the browser's current seekable window; as the playlist advances, expired portions are no longer seekable.

Playback error data includes a compact diagnostic summary instead of loader objects and segment payloads.

Build before publishing:

npm run build

Separate audio and video recordings

Provide the HLS master as videoSrc, the video media playlist as videoOnlySrc, and available audio intervals in seconds on the same recording timeline:

<VideoPlayer
  videoSrc="https://cdn.example.com/record/master.m3u8"
  videoOnlySrc="https://cdn.example.com/record/video.m3u8"
  audioRanges={[{ start: 0, end: 120 }, { start: 135, end: 240 }]}
  onAudioFallbackChange={(videoOnly) => console.log({ videoOnly })}
/>

Missing audio switches playback to the video playlist while retaining position, playing or paused state, speed, volume, and mute. Playback returns to the master when the current position has at least four seconds of available audio. Audio request failures impose a 15-second retry cooldown. Update audioRanges as a live recording grows; callbacks and metadata updates do not reload the source. The player displays a nonblocking status while playing without audio. Both media playlists and their fragment timestamps must use the same timeline.