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

@pozalabs/pori

v0.6.0

Published

Audio library for React — waveform visualization, HLS streaming, and playlist management

Downloads

180

Readme

pori

A React audio library built for fast loading and flexible UI composition.

pori gives you optimized audio fetching out of the box and a layered API: use headless hooks for full control, or compose pre-built components to ship faster.

Features

  • Optimized Audio Loading - Adaptive chunking with parallel downloads and automatic retries
  • Headless Hooks - useAudio, usePlaylist, useWaveform work independently from any UI
  • Compound Components - Pick and arrange only the sub-components you need
  • Waveform Visualization - Canvas and SVG renderers with line/bar variants and hover preview
  • HLS Streaming - Automatic detection and playback for .m3u8 sources
  • TypeScript - Full type coverage

Installation

npm install @pozalabs/pori

Requires React 18 or later.

For HLS streaming (.m3u8), install hls.js as well:

npm install hls.js

Quick Start

Compose an audio player

Wrap sub-components inside AudioPlayer.Provider to build the exact player you need.

import { AudioPlayer } from '@pozalabs/pori';

const playlist = [
  { id: '1', src: '/audio/track-01.mp3' },
  { id: '2', src: '/audio/track-02.mp3' },
];

function Player() {
  return (
    <AudioPlayer.Provider playlist={playlist}>
      <AudioPlayer.PlayPauseButton />
      <AudioPlayer.ProgressBar />
      <AudioPlayer.CurrentTime format="MM:SS" />
      <AudioPlayer.Duration format="MM:SS" />
      <AudioPlayer.VolumeProgressBar />
    </AudioPlayer.Provider>
  );
}

Go headless

Use hooks directly when you need a fully custom UI.

import { useAudio } from '@pozalabs/pori';

function CustomPlayer({ src }: { src: string }) {
  const { isPlaying, currentTime, duration, togglePlayPause } = useAudio({ src });

  return (
    <div>
      <button onClick={() => togglePlayPause()}>
        {isPlaying ? 'Pause' : 'Play'}
      </button>
      <span>{currentTime} / {duration}</span>
    </div>
  );
}

API Overview

Hooks

useAudio

Core audio playback, volume, playback rate, keyboard shortcuts. See Quick Start for usage.

usePlaylist

Extends useAudio with playlist management and repeat modes (none, one, all).

import { usePlaylist } from '@pozalabs/pori';

const playlist = [
  { id: '1', src: '/audio/track-01.mp3' },
  { id: '2', src: '/audio/track-02.mp3' },
];

function Player() {
  const { isPlaying, togglePlayPause, playNextAudio } = usePlaylist({ playlist });
  return <button onClick={() => playNextAudio()}>Next</button>;
}

useWaveform

Audio visualization with Canvas/SVG rendering and interactive controls.

import { useWaveform } from '@pozalabs/pori';

function WaveformPlayer() {
  const { waveform, isPlaying, play, pause } = useWaveform({ src: '/audio.mp3' });
  return <div ref={(el) => el && waveform && el.appendChild(waveform)} />;
}

Components

AudioPlayer

Compound component with Provider and composable sub-components. See Quick Start for usage.

  • AudioPlayer.Provider - Provides audio player state and controls
  • AudioPlayer.Playlist - Renders playlist items
  • AudioPlayer.CurrentTime - Displays current playback time
  • AudioPlayer.Duration - Displays total duration
  • AudioPlayer.ProgressBar - Playback position slider
  • AudioPlayer.VolumeProgressBar - Volume level slider
  • AudioPlayer.PlayButton - Starts playback
  • AudioPlayer.PauseButton - Pauses playback
  • AudioPlayer.PlayPauseButton - Toggles play/pause
  • AudioPlayer.StopButton - Stops and resets playback
  • AudioPlayer.ShiftForwardButton - Advances playback by time shift
  • AudioPlayer.ShiftBackwardButton - Rewinds playback by time shift
  • AudioPlayer.SkipStartButton - Restarts or skips to previous
  • AudioPlayer.SkipEndButton - Skips to next
  • AudioPlayer.RepeatButton - Cycles repeat mode
  • AudioPlayer.VolumeButton - Toggles mute

Waveform

Standalone waveform visualization component.

import { useRef } from 'react';
import { Waveform } from '@pozalabs/pori';
import type { WaveformHandles } from '@pozalabs/pori';

function Player() {
  const ref = useRef<WaveformHandles>(null);
  return <Waveform ref={ref} src="/audio.mp3" />;
}

Slider

General-purpose slider for building custom progress/volume bars.

import { useState } from 'react';
import { Slider } from '@pozalabs/pori';

function VolumeControl() {
  const [volume, setVolume] = useState(50);
  return <Slider value={volume} onChange={setVolume} />;
}

Utilities

fetchAudio

Chunked parallel download with retry.

import { fetchAudio } from '@pozalabs/pori';

const audioBuffer = await fetchAudio({ src: '/audio.mp3' });

getAudioFileInformation

Retrieves audio file metadata (type, size) via a HEAD request.

Development

bun dev            # Dev server (port 3000)
bun run build      # Build with tsup
bun run test       # Run tests
bun run lint       # Lint

License

MIT