Skip to content

loonylabs-dev/tta-middleware

Repository files navigation

@loonylabs/tta-middleware

Provider-agnostic Text-to-Audio middleware for music and sound effect generation.

npm version License: MIT TypeScript


Table of Contents

Features

  • Multi-Provider Architecture — ElevenLabs (SFX + Music) and Google Lyria (Instrumental Music)
  • Discriminated Union Requests — Full type safety with separate request types for sound effects and music
  • Retry Logic — Exponential backoff with jitter for transient errors (429, 5xx, timeouts)
  • Dry Mode — Validate requests without making API calls (no cost)
  • Debug Logging — Markdown-based request/response logging
  • TypeScript-First — Full type definitions with discriminated unions
  • Typed Error ClassesInvalidConfigError, QuotaExceededError, CapabilityNotSupportedError, etc.
  • Lazy SDK Loading — Provider SDKs loaded only when needed

Quick Start

npm install @loonylabs/tta-middleware

# Install provider SDK(s) you need:
npm install @elevenlabs/elevenlabs-js    # For ElevenLabs
npm install @google-cloud/aiplatform     # For Google Lyria
import { TTAService, ElevenLabsTTAProvider } from '@loonylabs/tta-middleware';

const service = new TTAService();
service.registerProvider(new ElevenLabsTTAProvider({ apiKey: 'your-key' }));

// Generate a sound effect
const sfxResult = await service.generate({
  type: 'sound_effect',
  prompt: 'Thunder crash with echoes',
  durationSeconds: 5,
});

// Generate music
const musicResult = await service.generate({
  type: 'music',
  prompt: 'Smooth jazz piano trio',
  musicLengthMs: 30000,
});

// Access the audio
const audioBase64 = sfxResult.audio[0].data;
const contentType = sfxResult.audio[0].contentType; // 'audio/mpeg'

Providers & Models

Provider Model Type Looping Instrumental Only Max Duration
ElevenLabs eleven_text_to_sound_v2 Sound Effects Yes No 30s
ElevenLabs music_v1 Music No No 600s
Google Lyria lyria-002 Music No Yes 600s

API Reference

TTAService

const service = new TTAService();

// Provider management
service.registerProvider(provider);
service.getProvider(TTAProvider.ELEVENLABS);
service.getAvailableProviders();
service.setDefaultProvider(TTAProvider.GOOGLE_LYRIA);

// Generation
const result = await service.generate(request, provider?);

// Discovery
service.listAllModels();
service.findProvidersWithCapability('soundEffects');

TTARequest (Discriminated Union)

Sound Effect Request:

interface TTASoundEffectRequest {
  type: 'sound_effect';
  prompt: string;
  durationSeconds?: number;     // 0.5-30
  promptInfluence?: number;     // 0-1
  loop?: boolean;
  model?: string;
  outputFormat?: string;
  retry?: boolean | RetryOptions;
  dry?: boolean;
}

Music Request:

interface TTAMusicRequest {
  type: 'music';
  prompt: string;
  musicLengthMs?: number;       // 3000-600000
  forceInstrumental?: boolean;
  seed?: number;
  negativePrompt?: string;
  model?: string;
  outputFormat?: string;
  retry?: boolean | RetryOptions;
  dry?: boolean;
}

TTAResponse

interface TTAResponse {
  audio: TTAAudio[];       // Array of generated audio clips
  metadata: {
    provider: string;
    model: string;
    region?: string;
    duration: number;      // Request duration in ms
  };
  usage: TTAUsage;
  billing?: TTABilling;
}

Advanced Features

Dry Mode

Test without API calls:

const result = await service.generate({
  type: 'sound_effect',
  prompt: 'test',
  dry: true,  // Returns placeholder audio, no API call
});

Retry Configuration

const result = await service.generate({
  type: 'music',
  prompt: 'jazz piano',
  retry: {
    maxRetries: 5,
    delayMs: 1000,
    backoffMultiplier: 2.0,
    maxDelayMs: 30000,
    jitter: true,
    timeoutMs: 60000,
  },
});

Debug Logging

# Enable via environment variable
DEBUG_TTA_REQUESTS=true
import { TTADebugger } from '@loonylabs/tta-middleware';

TTADebugger.setEnabled(true);
TTADebugger.setLogsDir('./logs/tta/requests');

Error Handling

import {
  TTAError,
  InvalidConfigError,
  QuotaExceededError,
  CapabilityNotSupportedError,
} from '@loonylabs/tta-middleware';

try {
  await service.generate(request);
} catch (error) {
  if (error instanceof QuotaExceededError) {
    console.log('Rate limited, try again later');
  } else if (error instanceof CapabilityNotSupportedError) {
    console.log('This provider/model does not support the requested type');
  }
}

Testing

# Run all unit tests
npm test

# Watch mode
npm run test:unit:watch

# Coverage report
npm run test:unit:coverage

# Manual tests (requires API keys)
npm run test:manual:elevenlabs-sfx
npm run test:manual:elevenlabs-music
npm run test:manual:google-lyria

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Write tests for your changes
  4. Ensure npm run build && npm test passes
  5. Submit a pull request

License

MIT - see LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors