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

nimio-player

v1.9.0

Published

Nimio SLDP 2.0 Player — lightweight JS player built on WebCodecs

Downloads

409

Readme

SLDP ecosystem

SLDP (Softvelum Low Delay Protocol) is a part of Larix product family, which provides a complete solution for mobile contribution and low-latency playback.

  • Nimio — lightweight JavaScript SLDP player for the web built on WebCodecs.
  • Larix Player — playback including SLDP (iOS / Apple TV / Android)
  • Larix Broadcaster — mobile contribution; supports SLDP talkback (iOS / Android)

Get Larix apps

Larix Player
  

Larix Broadcaster
  

Overview

Nimio is a lightweight, flexible JavaScript player for the SLDP 2.0 protocol built on the WebCodecs API. It offers low-latency streaming, full control over audio/video pipelines, and easy integration into modern web apps.

Demo

https://nimio.pages.dev/demo - Latest

https://softvelum.com/nimio/demo/ - Stable

Player highlights

  • Ultra-low latency SLDP 2.0 over WebSockets with WebCodecs; supports H.264/H.265/AV1/VP8/VP9 plus AAC/MP3/Opus.
  • Adaptive streaming
  • Integrated player UI
  • Latency and sync control: target + tolerance, fast-forward/seek correction, audio gap smoothing, timestamp recovery.
  • Audio-only/video-only modes
  • Full screen playback
  • VU meter
  • EventBus hooks for custom UI/analytics

SLDP & WebCodecs Features

  • SLDP Protocol (Softvelum Low Delay Protocol) - WebSocket‑based streaming with sub-100ms latency, supporting H.264, H.265/HEVC, AV1, VP8, VP9, AAC, MP3, Opus, and more.
  • WebCodecs Integration - Fine‑grained control over decoding, synchronization, jitter buffering, playback speed, and debugging at each stage of the pipeline.
  • Available on all web platforms - desktop, Android and recent iOS/macOS.

Read the first beta release announcement with the list of current features.

Installation

Nimio can be used either as an npm package in a bundler-based project, or as a standalone build loaded directly in the browser.

Option A. npm package (bundler: Vite, webpack, Rollup, Parcel, etc.)

npm install nimio-player
import Nimio from "nimio-player";
import "nimio-player/style.css";

const nimio = new Nimio({
  streamUrl: "wss://example.com/stream",
  container: "#player",
});

Web Workers and the AudioWorklet processor used by Nimio are emitted as separate chunks next to the main file. Modern bundlers pick them up automatically via new Worker(new URL(...), import.meta.url) — no extra configuration is required.

Option B. Standalone build (no bundler)

Download the latest dist.tar.gz from the Releases page and host its contents on your server, or build it yourself:

git clone https://github.com/Softvelum/nimio.git
cd nimio
npm install
npm run build

The build produces versioned files in dist/: nimio-<version>.js, nimio-<version>.css and a ready-to-use demo.html.

Quick Start

<link rel="stylesheet" href="/path/to/nimio.css" />
<script type="module" src="/path/to/nimio.js"></script>

<div id="player"></div>

<script type="module">
  const nimio = new Nimio({
    streamUrl: "wss://example.com/stream",
    container: "#player",
  });
</script>

Full Configuration Example

nimio = new Nimio({
  streamUrl: "wss://example.com/stream", //SLDP stream URL
  container: "#player", // CSS selector or HTMLElement
  //optional parameters:
  width: 476,
  height: 268,
  latency: 600, // Target latency in ms
  startOffset: 1000, // Startup offset in ms
  pauseTimeout: 3000, // ms until auto-stop when paused
  metricsOverlay: true, // Show overlay with performance metrics
  logLevel: "warn", // Logging verbosity
  autoplay: true, // Start playback automatically
  videoOnly: false, // Video only playback
  audioOnly: false, // Audio only playback
  muted: true, // Player is muted on start
  hardwareAcceleration: false, // Request hardware decoder; falls back to software if unsupported
  adaptiveBitrate: {
    initialRendition: "480p", // Default rendition which the player will set on start
    maxRendition: "1080p", // Maximum rendition that the player will set automatically
    sizeConstrained: true, // Player won't automatically switch to renditions which dimensions exceed the actual player size more then 5%
  },
  vuMeter: {
    // a volume unit (VU) meter settings object
    api: "AudioWorklet", // audio processing interface used by VU meter ("AudioWorklet" or "ScriptProcessor")
    container: "vu-meter", // ID of the VU meter container. VU meter UI  occupies the whole container's size. Vertical orientation (container's height >= width), horizontal orientation (container's width > height)
    mode: "peak", // the way which audio level values are calculated ("peak", "avg", "rms")
    type: "input", // VU meter readings type ("input" or "output")
    rate: 6, // audio level update frequency limit (from 0.001 to 50)
    dbRange: 100, // decibel scale range which is plotted in the VU meter UI
  },
  vod: {
    // video on demand (VOD) playback settings. VOD feature provides playback of recorded live stream (DVR). VOD settings can be defined as an object, or simply with true or false values. true value has the same meaning as an empty object, false means the feature is switched off. If not defined, VOD functionality is not enabled by default. VOD feature is backed by open source HLS.js library.

    // Please refer to https://softvelum.com/2024/06/dvr-sldp-html5-player/ article for setup and usage details.

    url: "https://myserver.com:8081/live/stream/playlist_dvr.m3u8", // (optional) URL to HLS stream that provides recorded content. If not defined, SLDP Player will use default Nimble Streamer DVR path according to the live stream URL.
    startupVodFailover: true, // (optional) specifies whether the player should automatically switch to VOD on startup if live stream playback fails. Enabled by default.
    liveFailover: true, // (optional) specifies whether the player should automatically switch to Live if VOD stream playback fails. Enabled by default.
    thumbnails: true, // (optional) enables video thumbnails above the progress bar of the player while hovering or dragging it. It works only if Nimble Streamer is configured with the dvr_hls_add_program_date_time parameter enabled.
    hlsjs: {
      source: "https://cdn.jsdelivr.net/npm/hls.js@1",
    }, // (optional) HLS.js library settings. It can be either object or string. Currently 2 string values are available: 1. ‘local’ – HLS.js is already included in the web application, so Nimio doesn’t load anything. 2. ‘cdn’ – (default) Nimio will automatically load HLS.js library from the official CDN URL. If the hlsjs parameter is defined as object, it can contain the following fields (currently only one parameter is supported): ‘source‘ – a URL to HLS.js library if a specific version is required.
  },
  captions: {
    // CEA-608 closed captions settings object. Can be set to {} or true to enable captions without specific settings. Each caption track is represented by ID: capObj pair, where the ID is one of the following: ‘CC1’, ‘CC2’, ‘CC3’, ‘CC4’. The capObj is an object, that defines the following settings:
    CC1: {
      name: "First track", // (optional) track name that is shown in caption selection menu. If it’s not set, then corresponding ID will be shown instead.
      lang: "English", // (optional) track language that is shown in parentheses in caption selection menu after the track name.
      default: true, // (optional) defines whether given track should be enabled by default. If this parameter isn’t specified for any of the tracks, then captions won’t be shown on the player start.
    },
    CC2: {
      name: "Second track", // (optional) track name
      lang: "French", // (optional) track language
    },
  },
  timecodes: true, // enables handling of SEI picture timing (H264) and SEI time code (H265) messages
});

nimio.play();

Multiple players

Mosaic demo (multiple players on one page): docs/mosaic-demo.md

Cross‑Origin Isolation

Nimio tries to use SharedArrayBuffer for zero‑copy state/audio exchange, but now falls back to a message‑based path when it is unavailable.
For best latency you should still enable a fully isolated browsing context by sending both the Cross‑Origin‑Opener‑Policy and Cross‑Origin‑Embedder‑Policy headers on any page or asset that loads the player.

Add these two headers:

add_header Cross-Origin-Opener-Policy  same-origin always;
add_header Cross-Origin-Embedder-Policy require-corp always;

Example: Nginx Configuration

server {
    listen 443 ssl;
    server_name example.com;

    # Serve the Nimio demo with COOP/COEP
    location ^~ /nimio/ {
        alias /usr/share/nginx/example.com/nimio/;
        index index.html;

        # Enable cross‑origin isolation
        add_header Cross-Origin-Opener-Policy  same-origin always;
        add_header Cross-Origin-Embedder-Policy require-corp always;
    }
}

Methods

Instance Methods

These methods are available on every Nimio player instance.

  • play()
    Start playback.

  • pause()
    Pause playback.

  • stop()
    Stop and reset the player.

  • destroy()
    Destroy the player instance and release all memory.

  • version()
    Return the current version string of the player instance.

  • seekVod(position)
    Updates current VOD playback position with the specified value. If the player is currently in the live mode, it's switched to the VOD mode.
    Return value: boolean status (true - position update is performed successfully, false - playback position update failed).
    Parameters: position - playback position in seconds from the start. Possible values are in range [0, duration]

  • seekLive(buffer)
    Updates current live playback position (buffering) with the specified value. If the player is currently in VOD mode, it will be switched to Live mode. The latency value in the player's settings is updated with the value of the buffer parameter. If the parameter is omitted, the current buffering setting is used.
    Return value: boolean status (true - position update is performed successfully, false - playback position update failed).
    Parameters: buffer - (optional) buffer size in seconds that the player pertains during live playback.

  • getCaptionTracks()
    Returns a map of the CEA-608 caption tracks currently available in the stream.
    Return value: object, containing ID: CAP_OBJ pairs, where the ID is one of the following: "CC1", "CC2", "CC3", "CC4". The CAP_OBJ is and object with the following fields:

    • title - caption track title that is shown in caption selection dialog.
    • name - (optional) caption track name defined in caption settings.
    • lang - (optional) caption track language defined in caption settings.
  • getCurrentCaptionTrack()
    Returns currently selected CEA-608 caption track.
    Return value: object, containing single ID: CAP_OBJ pair, with the ID of currently selected caption track. If no caption track is selected, then an empty object will be returned.

  • setCaptionTrack(ID)
    Sets current CEA-608 caption track with the ID specified. To turn off captions, "OFF" value should be specified as ID.
    Return value: boolean status (true - track is set successfully, false - specified track can't be set).
    Parameters:
    ID - either caption track ID value, which can be one of the following: "CC1", "CC2", "CC3", "CC4" or "OFF" to turn off captions.

  • getCurrentStreamBandwidth()
    Returns stream's bandwidth in bits per second.

  • getVodThumbnailUrl(time)
    Returns the URL to the thumbnail of the current VOD stream at the given time in seconds. More specifically, the thumbnail is the keyframe of the HLS segment that covers the given time.
    IMPORTANT: This functionality only works if Nimble Streamer is configured with the dvr_hls_add_program_date_time parameter enabled. If there is no thumbnail at the specified time or if Nimble Streamer isn't configured with the above parameter, the result is undefined.
    Return value: string with the requested thumbnail URL.
    Parameters:
    time - time of the thumbnail in seconds from 0 to the length of the DVR archive

  • getStreamEncodedFramerate()
    Returns framerate value calculated from the SPS parameters. Applicable only when the "timecodes" init parameter is enabled. If there are no relevant parameters in the SPS, the method will return undefined. The method should be run after the player started to receive video frames. E.g. it can be run on the first "nimio:sei-timecode" event emission.
    Return value: integer value of the current stream's framerate, encoded in the SPS.

Static Methods

These methods are available directly on the Nimio class.

  • Nimio.version()
    Return the current version string (identical to instance.version()).

Events

Nimio player uses events to interact with its UI. It allows to create custom UI easily.

Events sent from UI to player

These events are used to send commands and data from UI to Nimio player.

  • ui:play-pause-click
    Start/pause playback control invoked.
    Parameters:
isPlayClicked: Boolean;
mode: "live" | "vod"; // playback mode

  • ui:volume-change
    Set audio volume.
    Parameters:
volume: Number; // Current volume as integer value in the range from 0 to 100.

  • ui:mute-unmute-click
    Mute/unmute audio.
    Parameters:
mute: Boolean;

  • ui:rendition-select
    A specific rendition is selected from the list received from the nimio:rendition-list event.
    Parameters:
rend: {
  id: Number, // An integer number with unique rendition ID.
  name: String // Rendition name.
},
mode: "live" | "vod"; // playback mode

Events sent from player to UI

These events are used to send data from Nimio player to UI.

  • nimio:play
    Playback started. Parameters:
mode: "live" | "vod"; // playback mode

  • nimio:pause
    Playback paused.
    Parameters:
mode: "live" | "vod"; // playback mode

  • nimio:playback-start Playback has started and first frame is rendered.
    Parameters:
mode: "live" | "vod"; // playback mode

  • nimio:playback-end
    Playback reached the end of the media.
    Parameters:
mode: "live" | "vod"; // playback mode

  • nimio:volume-set
    Audio volume level set.
    Parameters:
volume: Number; // Current volume integer value in the range from 0 to 100.

  • nimio:muted
    Audio muted/unmuted.
    Parameters:
muted: Boolean;

  • nimio:abr
    Adaptive bitrate (ABR) mode enabled/disabled.
    Parameters:
enabled: Boolean;

  • nimio:rendition-list
    List of available renditions.
    Parameters:
  renditions: Array<{
    id: Number, // An integer number with unique rendition ID.
    name: String // Rendition name.
  }>;

  • nimio:rendition-set
    Active video/audio rendition selected manually or programmatically.
    Parameters:
  rendition: {
    id: Number, // An integer number with unique rendition ID.
    name: String // Rendition name.
  }

Playback events

  • nimio:connection-started
    Invoked when player starts connection to media server.
    Parameters:
  url - stream URL the player connects to, e.g. "wss://exampl.com/live/stream"

  • nimio:connection-established
    Emitted when connection to media server is established and a list of available streams is received. The list of renditions available for user is composed depending on those streams and browser capabilities.
    Parameters:
  streams: Array<{
    name: String, // application and stream name, e.g. 'live/stream'
    width: Number, // stream width in pixels if video is present
    height: Number, // stream height in pixels if video is present
    vcodec: String, // stream video codec if present
    video: String, // either 'supported' or 'not supported' depending on browser capabilities
    acodec: String, // stream audio codec if present
    audio: String, // either 'supported' or 'not supported' depending on browser capabilities
    bandwidth: Number, // stream bandwidth expressed in bits per second
  }>;

  • nimio:vod-progress
    Invoked when the current VOD playback state is changed. The VOD playback status change during live playback is usually related to the VOD duration change.
    Parameters:
  status: {
    position: Number, // VOD playback position in seconds from the start
    duration: Number, // total VOD duration in seconds
  }

  • nimio:live-progress
    Invoked when the current live playback state is changed.
    Parameters:
  status: {
    buffer: Number, // current buffer size in seconds
  }

Other events that can be handled by the caller

  • nimio:captions-arrived
    Emitted each time a new set of captions is ready to be displayed on the player's screen. All previous captions should be replaced by new ones. CEA-608 caption format implies that player's screen is divided into 15 rows and 32 columns. Each cell contains one symbol.
    Parameters:
  captions: Array<{
    time: Number, // caption display start time in microseconds
    x: Number, // caption block's horizontal position counted from the left. Can be in range of 0 - 31.
    y1: Number, //caption block's top line position counted from the top. Can be in range of 0 - 14.
    y2: Number, // caption block's bottom line position counted from the top. Can be in range of 0 - 14.
    regions: Array<{
      spans: Array<{
        row: Number, // row number starting from the top. Can be in range of 0 - 14.
        content: String, // caption span text string
        style: { // caption span style object
          foreground: String, // text font color
          background: String, // background color
          italics: Boolean, // text should be italic if true
          underline: Boolean, // text should be underlined if true
          flash: Boolean, // span should be blinking if true
        },
      }>
    }> // If the regions array is empty, it means that the given caption block is used to clear all previous captions from the given time onwards
  }>,
  currentTime: Number, // current player time in microseconds
  • nimio:sei-timecode
    Emitted each time a new SEI picture timing or SEI time code message is parsed by the player.
    Parameters:
  frameTs: Number, // timestamp of a frame to which the given SEI picture timing message is attached. The timestamp is defined in microseconds
  clockTs: Number, // clockTimestamp from the SEI message which is calculated according to the Rec. ITU-T H.264 document.
  stringTs: String, // timecode from the SEI message in the form "hh:mm:ss.n_frames time_offset"
  mode: String, // "live" - the timecode is retrieved from a Live stream, "vod" - the timecode is retrieved from a VOD stream;

Roadmap

The following features are planned for upcoming releases:

  • Automatic aspect ratio detection
  • Picture-in-Picture (PiP)
  • WebTransport protocol
  • Screenshot capture
  • Extended Player API
  • OffscreenCanvas rendering
  • Resume from pause in DVR mode (no auto-jump to live)

Development

Common scripts:

  • npm run dev — start the Vite dev server with the demo page.
  • npm run build — produce the standalone build in dist/ (versioned file names + demo.html).
  • npm run build:pkg — produce the npm package layout in pkg/ (stable nimio.js/nimio.css + worker chunks in pkg/assets/).
  • npm run build:all — run both builds.
  • npm run test:pkg:vite — build the npm package, install it into the Vite smoke-test app from a local npm pack tarball, and run the app production build.
  • npm run dev:pkg:vite — build and install the local package tarball, then start the Vite smoke-test app for manual browser testing.
  • npm run test:pkg:webpack — build the npm package, install it into the webpack smoke-test app from a local npm pack tarball, and run the app production build.
  • npm run dev:pkg:webpack — build and install the local package tarball, then start the webpack smoke-test app for manual browser testing.
  • npm run tar — pack dist/ into dist.tar.gz for standalone distribution.
  • npm run test / npm run test:ci — run the test suite.

npm package smoke test

The examples/vite-package and examples/webpack-package projects verify that the npm package works when consumed by real bundler apps. They import nimio-player and nimio-player/style.css from a local tarball generated with npm pack, so the tests cover the published package shape (files, exports, CSS, worker chunks, and AudioWorklet assets), not just the source tree.

Run the build smoke test from the repository root:

npm run test:pkg:vite
npm run test:pkg:webpack

For manual playback testing in a browser:

npm run dev:pkg:vite
npm run dev:pkg:webpack

Contributing

Contributions are welcome! Please open an issue for discussion or submit a pull request.

License

Nimio released under MIT License.