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

@vindral/publisher

v0.2.0

Published

Web SDK for publishing to Vindral LiveCloud

Readme

@vindral/publisher

Web SDK for publishing to Vindral LiveCloud

Installation

npm install @vindral/publisher

Usage

Publisher is the recommended high-level API for publishing streams.

import { Publisher } from "@vindral/publisher"

// Get media stream from camera/microphone
const stream = await navigator.mediaDevices.getUserMedia({
  video: {
    width: 1280,
    height: 720,
    frameRate: 30,
  },
  audio: {
    channelCount: 2,
    sampleRate: 48000,
  },
})

const videoTrack = stream.getVideoTracks()[0]
const audioTrack = stream.getAudioTracks()[0]

// Channel ID and auth token can be found in the Vindral portal
const publisher = new Publisher({
  url: "https://moq.global.cdn.vindral.com:7001/voq/publish",
  channelId: "your_channel_id",
  authToken: "your_signed_auth_token",
})

publisher.on("publisher state", (state) => {
  console.log("Publisher state:", state)
})

publisher.on("connection state", (state) => {
  console.log("Connection state:", state)
})

publisher.on("error", (error) => {
  console.error("Publisher error:", error)
})

publisher.addTrack({
  kind: "video",
  track: videoTrack,
  config: {
    codec: "avc1.42001f",
    width: 1280,
    height: 720,
    framerate: 30,
    bitrate: 2_000_000,
    gopSize: 60,
  },
})

publisher.addTrack({
  kind: "audio",
  track: audioTrack,
  config: {
    codec: "opus",
    numberOfChannels: 2,
    sampleRate: 48000,
    bitrate: 128_000,
  },
})

// Optional: warm up encoding before going live.
// Calling publish() without prepare() will auto-prepare.
await publisher.prepare()

// Start the actual broadcast
await publisher.publish()

// Read current state synchronously
console.log("Publisher state:", publisher.state) // "idle" | "ready" | "publishing" | "closed"
console.log("Connection state:", publisher.connectionState) // "disconnected" | "connecting" | "connected" | "reconnecting"

// Read current publisher statistics (encoding, connection, and session info)
console.log("Publisher stats:", publisher.stats())

// Later (when ending the stream):
// Stop network publishing but keep encoding active
await publisher.unpublish()

// Fully close and release resources
await publisher.close()

const publisherError = await publisher.closed()
if (publisherError) {
  console.error("Publisher closed with error:", publisherError)
}

Lifecycle monitoring

Use either publisher.closed() for terminal monitoring, or the "publisher state" event for reactive state handling.

// Option 1: start terminal monitoring immediately
const closedPromise = publisher.closed()

// ... publish / unpublish as needed ...

// Later: close publisher intentionally
await publisher.close()

// Resolve terminal result (also works for unexpected fatal close)
const closedError = await closedPromise
if (closedError) {
  console.error("Publisher terminated with error:", closedError)
}
// Option 2: subscribe to state changes and react when state becomes "closed"
publisher.on("publisher state", (state) => {
  if (state === "closed") {
    console.log("Publisher is closed")
  }
})

Configuration

The Publisher constructor accepts the following options:

const publisher = new Publisher({
  // Required
  url: "https://moq.global.cdn.vindral.com:7001/voq/publish",
  channelId: "your_channel_id",
  authToken: "your_signed_auth_token",

  // Optional
  logLevel: "debug",            // "debug" | "info" | "warn" | "error"
  telemetryEnabled: true,      // Enable telemetry reporting
  encodeQueueSize: 5,  // Encode queue size for flow control

  // Custom reconnect logic (return true to allow reconnect, false to stop)
  reconnectHandler: (state) => {
    console.log(`Reconnect attempt ${state.attempt}`)
    return true
  },
})

You can update connection parameters at runtime:

publisher.setAuthToken("new_token") // e.g. before token expiry
publisher.setUrl("new_url")         // takes effect on next connection
publisher.setChannelId("new_id")    // only while disconnected

Low-level APIs

For advanced custom integrations, the Producer and Client classes are also exported. Producer manages encoding independently of any network connection, while Client handles the connection lifecycle and transport. Most users should use Publisher, which orchestrates both.

import { Producer, Client, createNamespace } from "@vindral/publisher"

Browser compatibility

The Publisher SDK requires WebCodecs (VideoEncoder / AudioEncoder). Modern Chromium-based browsers (Chrome, Edge) are fully supported. Firefox and Safari have partial or experimental support.

Documentation

For full API reference including publisher states, error codes, and configuration details, visit https://docs.vindral.com/web-sdk/api/publisher/.

License and support

Vindral is a commercial product and requires an active, paid license to access and use. To obtain such a license, or in case you have any questions, do not hesitate to get in touch!

Copyright RealSprint AB