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

@ziplayer/client

v1.0.2

Published

Browser AudioWorklet client for ZiPlayer WebSocket Opus streams

Readme

@ziplayer/client

Small browser client for ZiPlayer's Opus-only WebSocket audio protocol. It validates the publisher configuration and binary frame headers, decodes Opus packets with opus-decoder WebAssembly into Float32 samples, and plays them through an AudioWorklet with a bounded jitter buffer.

The package is a receiving/playback client; it does not expose remote pause, stop, seek, or volume methods. To control playback volume, send a volume command through your server API to the ZiPlayer player, which applies it before audio is sent to its subscribers. Your Node.js application still needs an authenticated WebSocket gateway and a WebAudioConnection publisher. Authentication is determined by your gateway; the token connect option is optional for gateways that do not require it. Add playback controls to your own server API and bind them to the intended ZiPlayer player. The gateway example in ../examples/backend shows a complete local setup with search, publisher routing, browser playback, queue display, and multi-player controls.

Install and use

npm install @ziplayer/client

Import it from a browser bundle or serve browser/index.js as an ES module. When serving the file directly without a bundler, provide an import map for the opus-decoder package and its dependencies; the gateway example includes the required mappings and serves those modules from the installed client dependencies:

import { WebAudioClient } from "@ziplayer/client";

const client = new WebAudioClient();
client.addEventListener("config", ({ detail }) => {
	console.log(`Listening to player ${detail.sessionId}`);
});
client.addEventListener("pcm", ({ detail }) => {
	console.log(`Frame ${detail.sequence}, peak ${detail.peak.toFixed(3)}`);
});
client.addEventListener("error", ({ detail }) => {
	console.error("Audio client error:", detail.error);
});

// Call from a user gesture so the browser permits AudioContext playback.
await client.connect({
	gatewayUrl: "ws://127.0.0.1:8080",
	token: tokenFromYourApplication,
	sessionId: "my-player",
});

// Stop the browser listener and release its AudioContext.
await client.disconnect();

For a UI that starts a new player session after the click, connect first with nextPublisher: true, then ask the server to start playback:

await client.connect({
	gatewayUrl: "ws://127.0.0.1:8080",
	token: tokenFromYourApplication,
	nextPublisher: true,
});
await fetch("/play", { method: "POST", body: JSON.stringify({ query }) });

The token option is optional for gateways that do not require authentication; provide it when your server uses token-based authentication. The browser fills in client.sessionId when the next publisher sends audio:config. If a publisher is already active and you want to join that live stream, pass its sessionId instead. Call disconnect() to release browser resources.

Events

WebAudioClient is an EventTarget:

| Event | event.detail | | ------------- | -------------------------------------------------------------------------------------- | | connected | { sessionId, nextPublisher }, emitted when the WebSocket opens | | config | Validated publisher audio configuration (codec: "opus") | | pcm | { sequence, timestampMs, samples, peak, payload, sequenceGap, codec } for each frame | | statechange | { state, previousState } | | sequencegap | { expectedSequence, receivedSequence } when a frame is lost | | control | An unrecognized, versioned publisher control message | | error | { error } | | close | { code, reason } for a remote WebSocket close |

payload is the original Opus packet, excluding its 16-byte protocol header. samples is the locally decoded, interleaved stereo Float32 data normalized to [-1, 1]. The client transfers that Float32 buffer to its AudioWorklet after dispatching the event; copy the samples inside the event callback if they must be retained.

In-Browser Opus Decoding

When the gateway publisher streams Opus (codec: "opus"), the default decoder uses opus-decoder (or supply an asynchronous opusDecoderFactory returning a compatible decoder adapter):

import { WebAudioClient, OpusDecoderAdapter } from "@ziplayer/client";
import { OpusDecoder } from "opus-decoder";

const client = new WebAudioClient({
	opusDecoderFactory: async () => {
		const decoder = new OpusDecoder({ channels: 2, sampleRate: 48000 });
		await decoder.ready;
		return new OpusDecoderAdapter({ decoder, channels: 2, sampleRate: 48000 });
	},
});

Options default to a 100 ms startup buffer, a two-second maximum AudioWorklet FIFO, and a five-second WebSocket connect timeout. The AudioContext must support 48 kHz output. Browsers require HTTPS/WSS outside localhost. Because browser WebSocket clients cannot set authorization headers, the gateway URL carries the listener token in a query parameter; use short-lived credentials.

TypeScript

Declarations are included. The browser APIs require the TypeScript DOM library.