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

z-astro-web-audio-stream

v1.4.0

Published

Astro integration for Web Audio Stream with separated download/storage optimization and automatic worklet deployment

Readme

z-astro-z-web-audio-stream

Astro integration for Web Audio Stream with automatic worklet deployment.

🍎 What This Fixes

This integration automatically sets up iOS Safari-safe audio streaming that fixes:

  • Sample Rate Mismatches - High-pitched/fast audio playback
  • Memory Pressure - Page reloads from large audio files
  • IndexedDB Failures - Safari connection issues
  • Broken AudioContext - iOS-specific Web Audio bugs

📦 Installation

npm install z-astro-z-web-audio-stream z-web-audio-stream
# or
pnpm add z-astro-z-web-audio-stream z-web-audio-stream

🚀 Setup

Add the integration to your astro.config.mjs:

import { defineConfig } from 'astro/config';
import webAudioStream from 'z-astro-z-web-audio-stream';

export default defineConfig({
  integrations: [
    webAudioStream({
      // Optional configuration
      workletPath: '/audio-worklet-processor.js',
      publicDir: 'public',
      autoDeploy: true,
      verbose: true
    })
  ]
});

⚙️ Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | workletPath | string | '/audio-worklet-processor.js' | URL path where worklet will be served | | publicDir | string | 'public' | Public directory relative to project root | | autoDeploy | boolean | true | Automatically copy worklet during build | | verbose | boolean | true | Log deployment information |

🎵 Usage in Components

Astro Component

---
// src/components/AudioPlayer.astro
---

<div id="audio-player">
  <button id="play-btn">Play</button>
  <button id="pause-btn">Pause</button>
</div>

<script>
  import { setupWebAudio } from 'z-web-audio-stream';
  
  // Initialize with iOS-safe defaults
  const manager = await setupWebAudio({
    workletPath: '/audio-worklet-processor.js', // Automatically deployed!
    onTimeUpdate: (currentTime, duration) => {
      console.log(`Playing: ${currentTime}s / ${duration}s`);
    },
    onEnded: () => {
      console.log('Playback finished');
    }
  });
  
  // Control buttons
  document.getElementById('play-btn')?.addEventListener('click', async () => {
    await manager.loadAndPlay('/audio/song.mp3', 'song-1', 'My Song');
  });
  
  document.getElementById('pause-btn')?.addEventListener('click', async () => {
    await manager.pause();
  });
</script>

React Component (in Astro)

// src/components/ReactAudioPlayer.tsx
import { useEffect, useState } from 'react';
import { setupWebAudio, type WebAudioManager } from 'z-web-audio-stream';

export default function ReactAudioPlayer() {
  const [manager, setManager] = useState<WebAudioManager | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);

  useEffect(() => {
    setupWebAudio({
      workletPath: '/audio-worklet-processor.js', // Auto-deployed by integration
      onTimeUpdate: (time, dur) => {
        setCurrentTime(time);
        setDuration(dur);
      },
      onEnded: () => {
        setIsPlaying(false);
      }
    }).then(setManager);

    return () => {
      manager?.cleanup();
    };
  }, []);

  const handlePlay = async () => {
    if (!manager) return;
    
    await manager.loadAndPlay('/audio/song.mp3', 'song-1', 'My Song');
    setIsPlaying(true);
  };

  const handlePause = async () => {
    if (!manager) return;
    
    await manager.pause();
    setIsPlaying(false);
  };

  return (
    <div className="audio-player">
      <button onClick={isPlaying ? handlePause : handlePlay}>
        {isPlaying ? 'Pause' : 'Play'}
      </button>
      
      {duration > 0 && (
        <div className="progress">
          <div 
            className="progress-bar"
            style={{ width: `${(currentTime / duration) * 100}%` }}
          />
        </div>
      )}
      
      <span>{Math.floor(currentTime)}s / {Math.floor(duration)}s</span>
    </div>
  );
}

🏗️ Build Process

During build, the integration:

  1. Finds the iOS-safe audio worklet processor
  2. Copies it to your public directory
  3. Configures the correct path automatically
  4. Logs deployment status (if verbose enabled)

Build Output:

🎵 Web Audio Stream integration loaded
🍎 iOS Safari audio fixes will be applied automatically
✅ Audio worklet deployed to: /path/to/public/audio-worklet-processor.js
🔧 Use in your app: setupWebAudio({ workletPath: "/audio-worklet-processor.js" })

🔧 Manual Deployment

If you prefer manual control:

// astro.config.mjs
export default defineConfig({
  integrations: [
    webAudioStream({
      autoDeploy: false // Disable automatic deployment
    })
  ]
});

Then deploy manually:

npx z-web-audio-stream-cli deploy

🍎 iOS Safari Benefits

This integration ensures your Astro site works perfectly on iOS Safari:

  • ✅ No High-Pitched Audio - Sample rate monitoring and correction
  • ✅ No Page Reloads - Memory-safe 1-2MB chunks on iOS
  • ✅ Reliable Caching - IndexedDB retry logic for Safari
  • ✅ Instant Playback - Progressive loading with first chunk
  • ✅ Zero Configuration - Works out of the box

📱 Mobile-First Examples

Progressive Loading with Preloading

<script>
  import { setupWebAudio } from 'z-web-audio-stream';
  
  const manager = await setupWebAudio();
  
  // Preload next tracks for seamless transitions
  await manager.preloadAudio('/audio/song1.mp3', 'song-1', 'Song 1');
  await manager.preloadAudio('/audio/song2.mp3', 'song-2', 'Song 2'); 
  
  // Play immediately (loads from cache)
  await manager.loadAndPlay('/audio/song1.mp3', 'song-1', 'Song 1');
</script>

Playlist with iOS Optimizations

function Playlist({ songs }) {
  const [manager, setManager] = useState<WebAudioManager | null>(null);
  const [currentSong, setCurrentSong] = useState(0);

  useEffect(() => {
    setupWebAudio({
      onEnded: () => {
        // Auto-advance to next song
        setCurrentSong(prev => (prev + 1) % songs.length);
      }
    }).then(async (audioManager) => {
      setManager(audioManager);
      
      // Preload all songs for iOS-safe smooth playback
      for (const song of songs) {
        await audioManager.preloadAudio(song.url, song.id, song.name);
      }
    });
  }, [songs]);

  const playSong = async (index: number) => {
    if (!manager) return;
    
    const song = songs[index];
    await manager.loadAndPlay(song.url, song.id, song.name);
    setCurrentSong(index);
  };

  return (
    <div className="playlist">
      {songs.map((song, index) => (
        <button
          key={song.id}
          onClick={() => playSong(index)}
          className={currentSong === index ? 'active' : ''}
        >
          {song.name}
        </button>
      ))}
    </div>
  );
}

🔍 Troubleshooting

Integration not found

npm install z-astro-z-web-audio-stream

Worklet file not deployed

  • Check that autoDeploy: true (default)
  • Verify z-web-audio-stream is installed
  • Check build logs for error messages

iOS audio still has issues

  • Ensure you're using the deployed worklet path
  • Check browser console for iOS-specific logs
  • Verify the integration ran during build

📄 License

MIT License - Part of the Web Audio Stream package suite.