1.0.1 • Published 25 days ago

@siteed/expo-audio-stream v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
25 days ago

@siteed/expo-audio-stream

@siteed/expo-audio-stream is a comprehensive library designed to facilitate real-time audio processing and streaming across iOS, Android, and web platforms. This library leverages Expo's robust ecosystem to simplify the implementation of audio recording and streaming functionalities within React Native applications.

Features

  • Real-time audio streaming across iOS, Android, and web.
  • Configurable intervals for audio buffer receipt.
  • Automated microphone permissions setup in managed Expo projects.
  • IOS is automatically setup to handle background audio recording.
  • Listeners for audio data events with detailed event payloads.
  • Utility functions for recording control and file management.

Example Application

The project comes with a fully functional example application that demonstrates how to use the library in a real-world scenario.

Example App

To try it:

git clone https://github.com/deeeed/expo-audio-stream.git
cd expo-audio-stream
yarn
yarn example ios
yarn example android
yarn example web

Installation

To install @siteed/expo-audio-stream, add it to your project using npm or Yarn:

npm install @siteed/expo-audio-stream
# or
yarn add @siteed/expo-audio-stream

Configuring with app.json

To ensure expo-audio-stream works correctly with Expo, you must add it as a plugin in your app.json configuration file.

{
  "expo": {
    "plugins": ["@siteed/expo-audio-stream"]
  }
}

Make sure to run npx expo prebuild after adding the plugin to your app.json file.

Usage

This library provides two hooks: useAudioRecorder for standalone use and useSharedAudioRecorder for accessing shared recording state within a React context.

Standalone Recording

The example/ folder contains a fully functional React Native application demonstrating how to integrate and use useAudioRecorder from @siteed/expo-audio-stream. This includes starting and stopping recordings, handling permissions, and processing live audio data.

Standalone Usage

import {
  useAudioRecorder,
  AudioStreamResult,
} from '@siteed/expo-audio-stream';

export default function App() {
  const { startRecording, stopRecording, duration, size, isRecording } = useAudioRecorder({
    debug: true,
    onAudioStream: (audioData: Blob) => {
      console.log(`audio event`,audioData);
    }
  });

  const handleStart = async () => {
    const { granted } = await Audio.requestPermissionsAsync();
    if (granted) {
      const fileUri = await startRecording({interval: 500});
    }
  };

  const handleStop = async () => {
    const result: AudioStreamResult = await stopRecording();
  };

  const renderRecording = () => (
    <View>
      <Text>Duration: {duration} ms</Text>
      <Text>Size: {size} bytes</Text>
      <Button title="Stop Recording" onPress={handleStop} />
    </View>
  );

  const renderStopped = () => (
    <View>
      <Button title="Start Recording" onPress={handleStart} />
    </View>
  );

  return (
    <View>
      <Button title="Request Permission" onPress={() => Audio.requestPermissionsAsync()} />
      {isRecording ? renderRecording() : renderStopped()}
    </View>
  );
}

The library also exposes an addAudioEventListener function that provides an AudioEventPayload object that you can subscribe to:

import { addAudioEventListener } from '@siteed/expo-audio-stream';

  useEffect(() => {
    const subscribe = addAudioEventListener(async ({fileUri, deltaSize, totalSize, from, streamUuid, encoded, mimeType, buffer}) => {
        log(`Received audio event:`, {fileUri, deltaSize, totalSize, mimeType, from, streamUuid, encodedLength: encoded?.length, bufferLength: buffer?.length})
    });
    return () => subscribe.remove();
  }, []);

Shared Recording

To facilitate state sharing across multiple components or screens, useSharedAudioRecorder can be used. It should be wrapped in a AudioRecorderProvider context provider to ensure state is managed at a higher level and shared appropriately.

Shared Recording Usage

import { AudioRecorderProvider, useSharedAudioRecorder } from '@siteed/expo-audio-stream';

export default function ParentComponent() {
  return (
    <AudioRecorderProvider>
      <ChildComponent />
    </AudioRecorderProvider>
  );
}

function ChildComponent() {
  const {
    startRecording,
    isRecording
  } = useSharedAudioRecorder();

  return (
    <View>
      <Text>{isRecording ? "Recording..." : "Ready to record"}</Text>
      <Button title="Toggle Recording" onPress={startRecording} />
    </View>
  );
}

Add Event Listener

You can also add an event listener to receive detailed audio event payloads, which is crucial for both standalone and shared usage scenarios.

import { useEffect } from 'react';
import { addAudioEventListener } from '@siteed/expo-audio-stream';

function App() {
  useEffect(() => {
    const subscription = addAudioEventListener(event => {
      console.log("Audio event received:", event);
    });

    return () => subscription.remove();
  }, []);

  // UI code here
}

Recording configuration

  • on Android and IOS, audio is recorded in wav format, 16khz sample rate, 16 bit depth, 1 channel.
  • on web, it usually records in opus but it depends on the browser configuration.

If you want to process the audio livestream directly, I recommend having another encoding step to align the audio format across platforms.

1.0.1

25 days ago

1.0.0

25 days ago

0.7.5

29 days ago

0.7.2

29 days ago

0.7.1

29 days ago

0.7.4

29 days ago

0.7.3

29 days ago

0.7.0

29 days ago

0.6.0

29 days ago

0.4.6

1 month ago

0.5.0

1 month ago

0.5.2

1 month ago

0.5.1

1 month ago

0.4.5

1 month ago

0.4.4

1 month ago

0.4.1

1 month ago

0.3.2

1 month ago

0.4.0

1 month ago

0.3.1

1 month ago

0.4.3

1 month ago

0.3.4

1 month ago

0.4.2

1 month ago

0.3.3

1 month ago

0.3.0

1 month ago

0.2.1

1 month ago

0.2.0

1 month ago

0.2.3

1 month ago

0.2.2

1 month ago

0.2.4

1 month ago

0.1.0

1 month ago