react-native-audio-waveform

repository·master·Indexed 43 days ago

https://github.com/simformsolutionspvtltd/react-native-audio-waveform

A React Native component for generating and rendering audio waveforms. Version 2.1.6 supports two modes: 'static' for visualizing and playing back pre-recorded audio files via a provided path, and 'live' for real-time waveform drawing during audio recording. It includes an imperative API via IWaveformRef for controlling playback and recording, as well as a useAudioPermission hook for managing microphone access on iOS and Android.

Tokens
11.2K
Snippets
34
Records
42
Agent score
54%

What's inside react-native-audio-waveform

  1. Configure audio recording permissions

    master

    To use the recording features, you must request microphone permissions in your native configuration files.

    iOS

    Add NSMicrophoneUsageDescription to your info.plist with a description of why the app needs access.

    Android

    Add the RECORD_AUDIO permission to your AndroidManifest.xml.

    <!-- iOS: info.plist -->
    <key>NSMicrophoneUsageDescription</key>
    <string>Needed permission to record audio</string>
    
    <!-- Android: AndroidManifest.xml -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
  2. Install @simform_solutions/react-native-audio-waveform

    master

    Install the package along with react-native-gesture-handler, which is a required dependency.

    For iOS projects, you must also run npx pod-install to install the CocoaPods.

    npm install @simform_solutions/react-native-audio-waveform react-native-gesture-handler
    
    # or
    
    yarn add @simform_solutions/react-native-audio-waveform react-native-gesture-handler
    
    # For iOS
    npx pod-install
  3. Run the react-native-audio-waveform example app

    master

    To run the official example application, you must first ensure that the audio sample files are correctly added to the iOS bundle. This is done using the npx react-native-asset command within the example directory.

    Important: If a link-assets-manifest.json file already exists, you must delete it before running the asset command to avoid conflicts.

    # 1. Prepare assets (delete link-assets-manifest.json if it exists first)
    cd example && npx react-native-asset
    
    # 2. Install dependencies
    yarn
    
    # 3. Run the app
    yarn example ios   # For iOS
    yarn example android # For Android
  4. Use static mode for pre-recorded audio waveforms

    master

    Use mode="static" when you want to visualize an existing audio file. In this mode, you must provide a path to the audio file. The component provides type-safe ref methods specifically for static playback.

    Key props:

    • mode: Set to "static".
    • path: The file path to the audio file.
    • onPlayerStateChange: Callback triggered when the player state changes.
    • onPanStateChange: Callback triggered when scrubbing/moving through the waveform.
    import { useRef } from 'react';
    import {
      Waveform,
      type IWaveformRef,
    } from '@simform_solutions/react-native-audio-waveform';
    
    const path = 'path/to/audio/file.mp3';
    const ref = useRef<IWaveformRef>(null);
    
    <Waveform
      mode="static"
      ref={ref}
      path={path}
      candleSpace={2}
      candleWidth={4}
      scrubColor="white"
      onPlayerStateChange={playerState => console.log(playerState)}
      onPanStateChange={isMoving => console.log(isMoving)}
    />;
  5. Use live mode for real-time recording waveforms

    master

    Use mode="live" to draw waveforms dynamically while audio is being recorded. The component provides type-safe ref methods specifically for live recording.

    Key props:

    • mode: Set to "live".
    • onRecorderStateChange: Callback triggered when the recorder state changes.
    import { useRef } from 'react';
    import {
      Waveform,
      type IWaveformRef,
    } from '@simform_solutions/react-native-audio-waveform';
    
    const ref = useRef<IWaveformRef>(null);
    
    <Waveform
      mode="live"
      ref={ref}
      candleSpace={2}
      candleWidth={4}
      onRecorderStateChange={recorderState => console.log(recorderState)}
    />;
  6. Use IWaveformRef methods for Static mode

    master

    When the component is in static mode, use the IWaveformRef to control audio playback. All methods return a Promise<boolean> indicating success.

    Available Methods:

    • startPlayer({ finishMode?: FinishMode }): Starts playback. Defaults to FinishMode.stop.
    • stopPlayer(): Stops playback.
    • pausePlayer(): Pauses playback.
    • resumePlayer(): Resumes paused playback.
    • stopAllPlayers(): Stops all players and frees native resources. Recommended for unmount.
    • stopAllWaveFormExtractors(): Stops waveform extractors and frees native resources. Recommended for unmount.
    • stopPlayersAndExtractors(): Combines stopping players and extractors. Recommended for unmount.
    // Example usage for static mode
    const start = await waveformRef.current.startPlayer();
    const stop = await waveformRef.current.stopPlayer();
    const pause = await waveformRef.current.pausePlayer();
    const resume = await waveformRef.current.resumePlayer();
    
    // Cleanup on unmount
    const cleanup = await waveformRef.current.stopPlayersAndExtractors();
  7. Use IWaveformRef methods for Live mode

    master

    When the component is in live mode, use the IWaveformRef to control audio recording.

    Note: On iOS, you must ensure NSMicrophoneUsageDescription permission is granted before calling startRecord.

    Available Methods:

    • startRecord({ encoder, sampleRate, bitRate, fileNameFormat, useLegacy, updateFrequency? }): Starts a new recording. Returns Promise<boolean>.
    • stopRecord(): Stops recording and returns the file path as a Promise<string>.
    • pauseRecord(): Pauses recording. Returns Promise<boolean>.
    • resumeRecord(): Resumes recording. Returns Promise<boolean>.
    // Example usage for live mode
    const started = await waveformRef.current.startRecord({
      encoder: 1,
      sampleRate: 44100,
      bitRate: 128,
      fileNameFormat: 'test',
      useLegacy: false
    });
    
    const filePath = await waveformRef.current.stopRecord();
  8. Manage microphone permissions with useAudioPermission

    master

    The useAudioPermission hook provides methods to check and request microphone permissions (NSMicrophoneUsageDescription) required for live recording.

    Methods:

    • checkHasAudioRecorderPermission(): Returns the current PermissionStatus.
    • getAudioRecorderPermission(): Requests permission from the user. Returns PermissionStatus.

    PermissionStatus Enum:

    • denied
    • undetermined
    • granted
    let hasPermission = await checkHasAudioRecorderPermission();
    
    if (hasPermission === PermissionStatus.granted) {
      startRecording();
    } else if (hasPermission === PermissionStatus.undetermined) {
      const permissionStatus = await getAudioRecorderPermission();
      if (permissionStatus === PermissionStatus.granted) {
        startRecording();
      }
    } else {
      // Permission denied, perhaps open settings
      Linking.openSettings();
    }
  9. Configure Metro for the example project monorepo structure

    master

    The metro.config.js in the example directory is configured to handle a monorepo-style setup where the library source code resides in the parent directory (..).

    Key configurations include:

    • watchFolders: Includes the project root to ensure Metro watches changes in the library source.
    • resolver.blacklistRE: Prevents Metro from loading multiple versions of peerDependencies by blocking the versions located in the root node_modules.
    • resolver.extraNodeModules: Aliases peerDependencies and the @simform_solutions/react-native-audio-waveform package to the specific versions/paths used within the example directory's node_modules or the local source path. This ensures the example app uses the local version of the library being developed.
    const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
    const path = require('path');
    const escape = require('escape-string-regexp');
    const exclusionList = require('metro-config/src/defaults/exclusionList');
    const rootPackage = require('../package.json');
    const rootModules = Object.keys({
      ...rootPackage.peerDependencies,
    });
    
    const root = path.resolve(__dirname, '..');
    
    module.exports = mergeConfig(getDefaultConfig(__dirname), {
      projectRoot: __dirname,
      watchFolders: [root],
      resolver: {
        blacklistRE: exclusionList(
          rootModules.map(
            m => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
          )
        ),
        extraNodeModules: {
          ...rootModules.reduce((acc, name) => {
            acc[name] = path.join(__dirname, 'node_modules', name);
            return acc;
          }, {}),
          '@simform_solutions/react-native-audio-waveform': path.resolve(
            __dirname,
            '..'
          ),
        },
      },
    });
  10. Reference: PlayerState, RecorderState, and UpdateFrequency enums

    master

    These enums define the possible states and configuration values for the waveform component.

    PlayerState (Static mode):

    • playing
    • paused
    • stopped

    RecorderState (Live mode):

    • recording
    • paused
    • stopped

    UpdateFrequency (Used in startRecord):

    • high: 250.0 ms
    • medium: 500.0 ms
    • low: 1000.0 ms
    enum PlayerState {
      playing = 'playing',
      paused = 'paused',
      stopped = 'stopped',
    }
    
    enum RecorderState {
      recording = 'recording',
      paused = 'paused',
      stopped = 'stopped',
    }
    
    enum UpdateFrequency {
      high = 250.0,
      medium = 500.0,
      low = 1000.0,
    }
  11. Configure the Audio Waveform component props

    master

    The waveform component accepts several props to control its appearance and behavior. It operates in two modes: static (for playing existing audio files) and live (for recording audio).

    Key Props:

    • mode*: 'live' or 'static'. Required.
    • ref*: An IWaveformRef instance. Required. Note that calling methods intended for the wrong mode will throw an error.
    • path*: The resource path of the audio file. Required for static mode.
    • playbackSpeed: Supports 1.0, 1.5, or 2.0. Values > 2.0 default to 1.0.
    • waveColor: Color of the waveform candlesticks (default: #545454).
    • scrubColor: Color of the played portion of the waveform (only in static mode).
    • onPlayerStateChange: Callback for PlayerState changes (only in static mode).
    • onRecorderStateChange: Callback for RecorderState changes (only in live mode).
    • onCurrentProgressChange: Returns currentProgress and songDuration (only in static mode).
    • candleWidth, candleSpace, candleHeightScale: Controls the visual dimensions of the waveform candlesticks.
    | **Props** | **Default** | **Static Mode** | **Live Mode** | **Type** | **Description** |
    | --- | --- | --- | --- | --- | --- |
    | mode* | - | ✅ | ✅ | 'live' or 'static' | Type of waveform. |
    | ref* | - | ✅ | ✅ | IWaveformRef | Type of ref provided. |
    | path* | - | ✅ | ❌ | string | Resource path for static mode. |
    | playbackSpeed | 1.0 | ✅ | ❌ | 1.0 / 1.5 / 2.0 | Playback speed. |
    | candleSpace | 2 | ✅ | ✅ | number | Space between candlesticks. |
    | candleWidth | 5 | ✅ | ✅ | number | Width of single candlestick. |
    | candleHeightScale | 3 | ✅ | ✅ | number | Scaling height of candlestick. |
    | maxCandlesToRender | 300 | ❌ | ✅ | number | Number of candlesticks. |
    | containerStyle | - | ✅ | ✅ | `StyleProp<ViewStyle>` | Style of the container. |
    | waveColor | #545454 | ✅ | ✅ | string | Color of candlestick. |
    | scrubColor | #7b7b7b | ✅ | ❌ | string | Color of played candlestick. |
    | onPlayerStateChange | - | ✅ | ❌ | ( playerState : PlayerState ) => void | Player state change callback. |
    | onPanStateChange | - | ✅ | ❌ | ( panMoving : boolean ) => void | Audio seeking active callback. |
    | onRecorderStateChange | - | ❌ | ✅ | ( recorderState : RecorderState ) => void | Recorder state change callback. |
    | onCurrentProgressChange | - | ✅ | ❌ | ( currentProgress : number, songDuration: number ) => void | Progress and duration callback. |
    | onChangeWaveformLoadState | - | ✅ | ❌ | ( state : boolean ) => void | Loading state callback. |
    | onError | - | ✅ | ❌ | ( error : Error ) => void | Error callback for static mode. |
    | showsHorizontalScrollIndicator | false | ❌ | ✅ | boolean | Show scroll indicator in live mode. |