/** * Audio-platform — shared types for music and TTS backends. * * This interface is the canonical contract for all MusicBackend * implementations in videoclaw. Every backend must conform to these * exact shapes; the registry enforces availability before dispatch. */ export type AudioBackendKind = 'music' | 'tts' | 'sfx'; export interface AudioBackendDescriptor { id: string; kind: AudioBackendKind; displayName: string; requiredEnv: string[]; requiresVertex?: boolean; /** * When true, availability additionally requires a Gemini API key resolvable * from the key-pool sources (GEMINI_API_KEYS / GOOGLE_API_KEYS / * GOOGLE_API_KEY). This is for API-key Gemini products that declare an empty * `requiredEnv` (no single fixed var). The registry gates on this flag rather * than the backend id, so the availability rule stays decoupled from * backend identity. */ requiresGeminiKey?: boolean; /** * When true, availability additionally requires the shared useapi.net bearer * token (USEAPI_API_TOKEN — the same token used by the dreamina/runway video * routes). This is for useapi-transport backends (e.g. FlowMusic) that declare * an empty `requiredEnv` and reuse the existing token rather than introducing a * new one. The registry gates on this flag, not the backend id. */ requiresUseApi?: boolean; summary: string; } export interface MusicGenInput { prompt: string; durationSec?: number; outputPath: string; dryRun?: boolean; fetcher?: typeof fetch; env?: NodeJS.ProcessEnv; /** * Optional path to a reference image for image-to-music conditioning. * Additive and backend-specific: the Lyria 3 (Gemini API) backend attaches it * as an inlineData part; backends that don't support it (suno, Vertex lyria) * ignore the field. */ imagePath?: string; /** * User-supplied lyrics ([Verse]/[Chorus]-tagged). Backend-specific: the * FlowMusic backend renders these as a vocal song; backends that don't support * lyrics (suno, lyria, lyria3) ignore the field. */ lyrics?: string; /** * Force an instrumental render. Backend-specific to FlowMusic (which otherwise * decides whether to sing based on the prompt); ignored by other backends. */ instrumental?: boolean; /** * Lyrics-writer version used when the MODEL writes the lyrics (FlowMusic only; * ignored when explicit lyrics are supplied, and by other backends). */ ghostwriter?: 'standard' | 'pro'; } export interface MusicGenResult { path: string; durationMs: number; backendId: string; } export interface MusicBackend extends AudioBackendDescriptor { kind: 'music'; generate(input: MusicGenInput): Promise; } export interface TtsGenInput { text: string; voice?: string; outputPath: string; dryRun?: boolean; fetcher?: typeof fetch; env?: NodeJS.ProcessEnv; } export interface TtsGenResult { path: string; durationMs: number; backendId: string; } export interface TtsBackend extends AudioBackendDescriptor { kind: 'tts'; /** * File extension (no dot) the backend writes — e.g. `'wav'` for gemini-tts * (PCM wrapped as WAV) or `'mp3'` for elevenlabs-tts. Callers that choose the * output path (e.g. `generateNarration`) use this so the extension matches the * actual bytes. Defaults to `'wav'` when absent. */ outputExtension?: string; generate(input: TtsGenInput): Promise; } export interface SfxGenInput { /** Natural-language description of the sound effect to generate. */ text: string; /** Desired duration in seconds (0.5–22). Defaults to 2s when omitted. */ durationSec?: number; /** Prompt influence (0–1, default 0.3). Controls how closely the output * follows the text vs. spontaneous model variation. */ promptInfluence?: number; /** Absolute path the downloaded mp3 is written to. */ outputPath: string; /** Skip all network + file I/O; return a synthetic result for dry runs. */ dryRun?: boolean; /** Injectable fetch for offline tests; defaults to the global `fetch`. */ fetcher?: typeof fetch; /** Override env (e.g. { ELEVENLABS_API_KEY: '...' }) for library callers * that cannot mutate process.env. */ env?: NodeJS.ProcessEnv; } export interface SfxGenResult { /** Path the audio was written to (== input.outputPath). */ path: string; /** Duration in milliseconds. */ durationMs: number; /** Backend id that produced the result. */ backendId: string; } export interface SfxBackend extends AudioBackendDescriptor { kind: 'sfx'; generate(input: SfxGenInput): Promise; }