0.1.1 • Published 9 months ago

@foxycorps/mic-drop v0.1.1

Weekly downloads
-
License
ISC
Repository
-
Last release
9 months ago

🎤 mic-drop

NPM Version License: ISC TypeScript Bundle Size

A straightforward library for capturing microphone audio in web apps

Working with microphone input in the browser can be a real headache. This library simplifies that, giving you an easy way to capture and process audio data without all the Web Audio API complexity.

What is this?

mic-drop helps you:

  • Capture audio from the user's microphone
  • Process real-time audio data
  • Build visualizations, voice features, or recording apps
  • Work around browser quirks (especially Safari and iOS)

All without having to become a Web Audio API expert.

Install

# Pick your favorite package manager
npm install mic-drop
pnpm add mic-drop
yarn add mic-drop

Quick Example

Here's how to get started with basic recording:

import MicrophoneStream from 'mic-drop';

async function startRecording() {
  try {
    // Get access to the microphone
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    
    // Create a new instance
    const mic = new MicrophoneStream({ stream });
    
    // Listen for audio data
    mic.addEventListener('data', (event) => {
      const audioData = event.detail; // This is a Float32Array
      
      // Do something with the audio data:
      // - Visualize it
      // - Analyze it
      // - Send it to a server
      // - Save it locally
    });
    
    return mic; // Keep a reference to stop it later
  } catch (err) {
    console.error('Could not access microphone:', err);
  }
}

// To stop recording
function stopRecording(mic) {
  if (mic) {
    mic.stop();
  }
}

Working with iOS/Safari

iOS is notoriously picky about audio. Here's a pattern that works well:

// Create the instance BEFORE any user interaction
const mic = new MicrophoneStream();

// Then in response to a button click:
recordButton.addEventListener('click', async () => {
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  await mic.setStream(stream); // Now we're recording!
});

Avoid Deprecated APIs

Use the allowScriptProcessorFallback option to prevent falling back to deprecated APIs:

// Modern browsers only - safer for the future
const mic = new MicrophoneStream({
  allowScriptProcessorFallback: false
});

// Will throw an error rather than use deprecated APIs

Building a Simple Visualizer

Here's a practical example of how to create a waveform visualizer:

const mic = new MicrophoneStream({ stream });
const canvas = document.getElementById('visualizer');
const ctx = canvas.getContext('2d');

mic.addEventListener('data', (event) => {
  const audioData = event.detail;
  
  // Clear canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  // Draw waveform
  ctx.beginPath();
  ctx.strokeStyle = '#0077ff';
  ctx.lineWidth = 2;
  
  const sliceWidth = canvas.width / audioData.length;
  let x = 0;
  
  for (let i = 0; i < audioData.length; i++) {
    // Convert audio data to y-position (0 to canvas height)
    const y = (audioData[i] * 0.5 + 0.5) * canvas.height;
    
    i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
    x += sliceWidth;
  }
  
  ctx.stroke();
});

API Overview

Creating an instance

// Basic usage
const mic = new MicrophoneStream();

// With options
const mic = new MicrophoneStream({
  stream: mediaStream,       // MediaStream from getUserMedia
  objectMode: false,         // true for AudioBuffer, false for Float32Array
  bufferSize: 4096,          // Buffer size (256 to 16384, power of 2)
  context: audioContext,     // Custom AudioContext (optional)
  allowScriptProcessorFallback: true // Set to false for modern browsers only
});

Methods

  • setStream(stream): Connect to a microphone stream
  • pauseRecording(): Pause data collection temporarily
  • resumeRecording(): Resume after pausing
  • stop(): Stop recording but keep the instance for later use
  • destroy(): Completely clean up resources when done

Events

// Audio data event
mic.addEventListener('data', (event) => {
  const audioData = event.detail; // Float32Array or AudioBuffer
});

// Format information
mic.addEventListener('format', (event) => {
  const format = event.detail;
  console.log(`Sample rate: ${format.sampleRate}Hz`);
});

// Error handling
mic.addEventListener('error', (event) => {
  console.error('Microphone error:', event.error);
});

Tips for Better Performance

  • Buffer Size: Smaller = lower latency but higher CPU usage. Default 4096 works well for most cases
  • Audio Processing: Do heavy processing in a Web Worker if possible
  • Memory Usage: Remove event listeners when done to prevent memory leaks
  • Mobile Devices: Be mindful of battery usage with long-running audio processing

Browser Support

Works in all modern browsers:

  • Chrome 55+
  • Firefox 52+
  • Safari 14.1+
  • Edge 79+
  • iOS Safari 14.5+

Troubleshooting Common Issues

  • No audio data? Check that your microphone permissions are granted
  • Browser errors? Try using allowScriptProcessorFallback: false and handle errors
  • iOS not working? Make sure you create the instance before user interaction
  • High CPU usage? Try increasing the buffer size

Contributing

Found a bug or want to help? Contributions are welcome!

  1. Fork the repo
  2. Create your branch (git checkout -b fix/awesome-fix)
  3. Make your changes
  4. Test your changes
  5. Submit a pull request

License

ISC License - go wild, just keep the attribution.

Credit Where It's Due

Built on the shoulders of the Web Audio API and inspired by earlier microphone libraries.

0.1.1

9 months ago

0.1.0

9 months ago