npm package: @movementinfra/expo-shazam-audio
Description: Expo module for Shazam music detection on audio/video files
Latest version: 1.0.8

# expo-shazam-audio

An Expo module for recognizing music from audio and video files using Apple's ShazamKit.

## Features

- Recognize music from audio files (MP3, M4A, AAC, WAV, AIFF, CAF)
- Extract and recognize music from video files (MP4, MOV, M4V)
- Full ShazamKit metadata including title, artist, album, artwork, and Apple Music links
- Simple Promise-based API
- Cancellation support for long-running recognition

## Requirements

- iOS 16.0 or later
- Expo SDK 50+
- Apple Developer account with ShazamKit entitlement

## Installation

```bash
npx expo install expo-shazam-audio
```

## Configuration

### App Config

Add the ShazamKit entitlement to your `app.json` or `app.config.js`:

```json
{
  "expo": {
    "ios": {
      "entitlements": {
        "com.apple.developer.shazamkit": true
      }
    }
  }
}
```

### Info.plist (Optional)

If you plan to use Apple Music features, add the music usage description to your `app.json`:

```json
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSAppleMusicUsageDescription": "This app uses Apple Music to play recognized songs."
      }
    }
  }
}
```

## Usage

### Basic Recognition

```typescript
import { recognize } from 'expo-shazam-audio';

async function identifySong() {
  try {
    const match = await recognize('file:///path/to/audio.mp3');

    if (match) {
      console.log(`Found: ${match.title} by ${match.artist}`);
      console.log(`Album: ${match.album}`);
      console.log(`Apple Music: ${match.appleMusicURL}`);
    } else {
      console.log('No match found');
    }
  } catch (error) {
    console.error('Recognition failed:', error.message);
  }
}
```

### With Cancellation

```typescript
import { recognize, cancel } from 'expo-shazam-audio';

// Start recognition
const recognitionPromise = recognize('file:///path/to/video.mp4');

// Cancel after 10 seconds if still running
const timeout = setTimeout(() => {
  cancel();
}, 10000);

try {
  const match = await recognitionPromise;
  clearTimeout(timeout);
  // Handle result
} catch (error) {
  if (error.message.includes('cancelled')) {
    console.log('Recognition was cancelled');
  }
}
```

### Using with Expo FileSystem

```typescript
import * as FileSystem from 'expo-file-system';
import { recognize } from 'expo-shazam-audio';

async function recognizeDownloadedFile() {
  // Download a file
  const downloadResult = await FileSystem.downloadAsync(
    'https://example.com/song.mp3',
    FileSystem.documentDirectory + 'song.mp3'
  );

  // Recognize the downloaded file
  const match = await recognize(downloadResult.uri);
  return match;
}
```

## API Reference

### `recognize(fileUri: string): Promise<ShazamMatch | null>`

Recognizes music from an audio or video file.

**Parameters:**
- `fileUri` - File URI (file://) pointing to an audio or video file

**Returns:**
- `Promise<ShazamMatch | null>` - Match result if found, null if no match

**Throws:**
- Error if file doesn't exist, format is unsupported, or recognition fails

### `cancel(): void`

Cancels any ongoing recognition operation. Safe to call even if no recognition is in progress.

### `ShazamMatch`

```typescript
interface ShazamMatch {
  // Core metadata
  title: string | null;
  artist: string | null;
  album: string | null;

  // Identifiers
  isrc: string | null;          // International Standard Recording Code
  appleMusicID: string | null;  // Apple Music track ID
  shazamID: string | null;      // Shazam internal ID

  // URLs
  appleMusicURL: string | null; // Link to Apple Music
  artworkURL: string | null;    // Album/track artwork
  videoURL: string | null;      // Music video URL (if available)
  webURL: string | null;        // Shazam web page

  // Additional metadata
  genres: string[];             // Array of genre names
  subtitle: string | null;      // Additional artist/track info
  explicitContent: boolean;     // Explicit content flag

  // Match info
  matchOffset: number;          // Seconds into audio where match found
}
```

## Supported File Formats

### Audio
- MP3
- M4A
- AAC
- WAV
- AIFF
- CAF

### Video (extracts audio track)
- MP4
- MOV
- M4V

## Error Handling

The module throws descriptive errors for common failure cases:

| Error | Description |
|-------|-------------|
| File not found | The specified file path doesn't exist |
| Invalid file format | File format is not supported |
| No audio track | Video file contains no audio |
| Recognition cancelled | `cancel()` was called during recognition |
| Shazam session failed | ShazamKit encountered an error |

## Troubleshooting

### "No such module 'ShazamKit'"

Ensure your iOS deployment target is iOS 16.0 or later. ShazamKit requires iOS 15+, but this module targets iOS 16+ for best compatibility.

### Recognition always returns null

- Ensure the audio contains recognizable music (not just speech or ambient noise)
- Check that the audio quality is sufficient (not heavily compressed or distorted)
- Verify the file is not corrupted by playing it in another app

### "Shazam session failed"

- Verify ShazamKit entitlement is properly configured
- Check network connectivity (ShazamKit may need network for full metadata)
- Ensure you have a valid Apple Developer account

## Development & Packaging

### Initial Setup

```bash
# Install dependencies
npm install

# Build TypeScript
npm run build
```

### Local Development

To test the module locally in an Expo app:

1. **Link the module locally:**
   ```bash
   # In your Expo app's package.json, add:
   # "expo-shazam-audio": "file:../path/to/expo-shazam-audio"

   # Then install
   npm install
   ```

2. **Rebuild the native project:**
   ```bash
   npx expo prebuild --clean
   npx expo run:ios
   ```

### Building for Distribution

```bash
# Clean previous builds
npm run clean

# Build TypeScript to JavaScript
npm run build

# Verify the build output
ls build/
# Should contain: index.js, index.d.ts, ExpoShazamAudio.types.js, etc.
```

### Publishing to npm

1. **Update version in package.json**

2. **Ensure you're logged into npm:**
   ```bash
   npm login
   ```

3. **Publish:**
   ```bash
   # For first publish
   npm publish --access public

   # For updates
   npm publish
   ```

### Package Contents

When published, the package includes:

| Directory/File | Purpose |
|---------------|---------|
| `build/` | Compiled JavaScript and TypeScript declarations |
| `ios/` | Swift source files (compiled by Expo during prebuild) |
| `expo-module.config.json` | Expo module configuration |
| `package.json` | Package metadata |
| `README.md` | Documentation |

### Testing in a New Expo Project

```bash
# Create a test project
npx create-expo-app test-shazam-app
cd test-shazam-app

# Install the module (from npm or local path)
npx expo install expo-shazam-audio

# Add iOS entitlement in app.json (see Configuration section)

# Build and run
npx expo prebuild --clean
npx expo run:ios
```

## License

MIT