---
name: fal-ai-inferencia-ia-serverless
description: Referencia completa para integrar fal.ai en proyectos: generación de imágenes con Flux Pro/Dev/Schnell y LoRA, vídeo con AnimateDiff/Kling, transcripción con Whisper y música con MusicGen, todo via API serverless sin gestionar GPUs. Incluye patrones de colas asíncronas, webhooks, subida de archivos y procesamiento en lote.
license: Apache-2.0
metadata:
  id: faa9565a
  slug: fal-ai-inferencia-ia-serverless
  titulo: "fal.ai — Inferencia IA Serverless (Flux, Video, Audio)"
  servicio: IA-Ingenieria-MLOps
  categoria_recurso: IA-Generativa
  tipo: referencia
  nivel: intermedio
  idioma: es
  idioma_original: en
  acceso: gratis
  precio_eur: 0
  plataformas: [Node.js, Python, Browser, Next.js]
  dependencias: [@fal-ai/client, fal-client, FAL_KEY]
  licencia: { spdx: Apache-2.0, redistribuible: true, uso_comercial: true }
  fuente:
    repo: TerminalSkills/skills
    url: https://github.com/TerminalSkills/skills/tree/main/skills/fal-ai
    commit: 77fa015
    autor: TerminalSkills
    nombre_original: fal-ai
    duplicados_en: []
  seguridad: { veredicto: seguro, riesgo: bajo, escaneado: "2026-06-14", motor: "grep-estatico+auditor-llm" }
  ficha:
    que_hace: "Proporciona guía de integración lista para usar con fal.ai para ejecutar modelos de imagen, vídeo y audio mediante API serverless de pago por inferencia."
    como_lo_hace: "Documenta el SDK oficial (@fal-ai/client / fal-client) con ejemplos en TypeScript y Python para subscribe síncrono, colas asíncronas con webhooks, subida de ficheros y procesamiento en lote."
  content_hash: "faa9565a0dc519f54e62c40ef7d0fbe39f329dd27042104c7cad6d38d65afb88"
  version: 1.0.0
---

# fal.ai

## Overview

fal.ai provides instant serverless inference for AI models — no GPU provisioning, no containers, pay per inference. The API is simple: pick a model ID, pass inputs, get outputs. Supports async jobs with webhooks, real-time streaming, and file uploads. Best-in-class for Flux image generation, video generation, and audio models.

## Install

```bash
npm install @fal-ai/client    # JavaScript/TypeScript
pip install fal-client         # Python
```

## Authentication

```bash
export FAL_KEY="your-api-key"  # Get from fal.ai/dashboard
```

## Quick Start

### TypeScript

```typescript
import * as fal from "@fal-ai/client";

// Configure (reads FAL_KEY from env by default)
fal.config({ credentials: process.env.FAL_KEY });

// Generate an image with Flux Schnell (fastest)
const result = await fal.subscribe("fal-ai/flux/schnell", {
  input: {
    prompt: "A futuristic city at night, neon lights, cyberpunk style",
    image_size: "landscape_4_3",
    num_images: 1,
  },
  logs: true,
  onQueueUpdate: (update) => {
    if (update.status === "IN_PROGRESS") {
      console.log(update.logs?.map(l => l.message).join("\n"));
    }
  },
});

console.log(result.data.images[0].url);
```

### Python

```python
import fal_client

def on_queue_update(update):
    if isinstance(update, fal_client.InProgress):
        for log in update.logs:
            print(log["message"])

result = fal_client.subscribe(
    "fal-ai/flux/schnell",
    arguments={
        "prompt": "A futuristic city at night, neon lights, cyberpunk style",
        "image_size": "landscape_4_3",
        "num_images": 1,
    },
    with_logs=True,
    on_queue_update=on_queue_update,
)

print(result["images"][0]["url"])
```

## Popular Models

### Flux Image Generation

```typescript
// Flux Pro — highest quality
const pro = await fal.subscribe("fal-ai/flux-pro", {
  input: {
    prompt: "Portrait of a robot chef, photorealistic, soft lighting",
    image_size: "portrait_4_3",   // landscape_4_3, square, square_hd
    num_inference_steps: 28,
    guidance_scale: 3.5,
    num_images: 1,
    safety_tolerance: "2",        // 1-6, higher = more permissive
  }
});

// Flux Dev — high quality, faster than Pro
const dev = await fal.subscribe("fal-ai/flux/dev", {
  input: {
    prompt: "...",
    num_inference_steps: 28,
    seed: 42,  // For reproducibility
  }
});

// Flux Schnell — fastest, good quality
const schnell = await fal.subscribe("fal-ai/flux/schnell", {
  input: { prompt: "...", num_inference_steps: 4 }  // Only needs 4 steps
});

// Flux with LoRA
const lora = await fal.subscribe("fal-ai/flux-lora", {
  input: {
    prompt: "A photo of TOK wearing a tuxedo",
    loras: [
      {
        path: "https://huggingface.co/your-lora/model.safetensors",
        scale: 1.0
      }
    ],
    num_inference_steps: 28,
  }
});
```

### Image-to-Image

```typescript
const result = await fal.subscribe("fal-ai/flux/dev/image-to-image", {
  input: {
    prompt: "Transform into oil painting style",
    image_url: "https://example.com/photo.jpg",
    strength: 0.85,  // 0-1, how much to transform (1 = ignore original)
    num_inference_steps: 28,
  }
});
```

### Video Generation

```typescript
// AnimateDiff — animate a still image
const video = await fal.subscribe("fal-ai/animatediff-v2v", {
  input: {
    image_url: "https://example.com/frame.jpg",
    prompt: "Gentle breeze moving through the trees",
    num_frames: 16,
    fps: 8,
  }
});
console.log(video.data.video.url);  // .mp4 URL

// Runway-style video gen
const runway = await fal.subscribe("fal-ai/kling-video/v1/standard/image-to-video", {
  input: {
    image_url: "https://example.com/start.jpg",
    prompt: "Camera slowly pans right",
    duration: "5",
  }
});
```

### Audio — Whisper Transcription

```typescript
// Upload audio file first
const audioUrl = await fal.storage.upload(fs.readFileSync("audio.mp3"), "audio.mp3");

const transcript = await fal.subscribe("fal-ai/whisper", {
  input: {
    audio_url: audioUrl,
    task: "transcribe",  // or "translate" (to English)
    language: "en",      // Optional, auto-detected if omitted
    chunk_level: "segment",
    version: "3",
  }
});

console.log(transcript.data.text);
```

### MusicGen

```python
result = fal_client.subscribe(
    "fal-ai/musicgen",
    arguments={
        "prompt": "Upbeat electronic music for a tech product demo, 120 BPM",
        "duration": 30,   # seconds
        "top_k": 250,
        "top_p": 0.0,
        "temperature": 1.0,
    }
)
print(result["audio"]["url"])
```

## Async Jobs with Webhooks

For long-running jobs, use submit → poll instead of subscribe:

```typescript
// Submit job (returns immediately)
const { request_id } = await fal.queue.submit("fal-ai/flux-pro", {
  input: { prompt: "..." },
  webhookUrl: "https://your-app.com/webhooks/fal",  // Optional
});

// Poll for result
const checkStatus = async () => {
  const status = await fal.queue.status("fal-ai/flux-pro", {
    requestId: request_id,
    logs: true,
  });

  if (status.status === "COMPLETED") {
    const result = await fal.queue.result("fal-ai/flux-pro", {
      requestId: request_id,
    });
    return result.data;
  }

  if (status.status === "FAILED") {
    throw new Error(`Job failed: ${status.error}`);
  }

  // Still in queue, check again in 2s
  await new Promise(r => setTimeout(r, 2000));
  return checkStatus();
};

const result = await checkStatus();
```

### Webhook Handler (Next.js)

```typescript
// app/api/webhooks/fal/route.ts
export async function POST(req: Request) {
  const payload = await req.json();

  if (payload.status === "OK") {
    const imageUrl = payload.payload.images[0].url;
    await db.update({ requestId: payload.request_id, imageUrl, status: "done" });
  } else {
    await db.update({ requestId: payload.request_id, status: "failed" });
  }

  return Response.json({ ok: true });
}
```

## File Uploads

```typescript
import * as fal from "@fal-ai/client";
import * as fs from "fs";

// Upload a file to fal.ai storage
const fileBuffer = fs.readFileSync("my-image.jpg");
const url = await fal.storage.upload(fileBuffer, "image.jpg");
// Returns: "https://fal.run/files/..."

// Use uploaded URL as model input
const result = await fal.subscribe("fal-ai/flux/dev/image-to-image", {
  input: { image_url: url, prompt: "..." }
});
```

```python
# Python file upload
import fal_client

url = fal_client.upload_file("./photo.png")
print(url)  # https://fal.run/files/...
```

## Batch Processing

```typescript
async function generateBatch(prompts: string[]): Promise<string[]> {
  // Submit all jobs in parallel
  const jobs = await Promise.all(
    prompts.map(prompt =>
      fal.queue.submit("fal-ai/flux/schnell", {
        input: { prompt, num_images: 1 }
      })
    )
  );

  // Poll all results
  const results = await Promise.all(
    jobs.map(({ request_id }) =>
      fal.queue.result("fal-ai/flux/schnell", { requestId: request_id })
    )
  );

  return results.map(r => r.data.images[0].url);
}

const urls = await generateBatch([
  "A red sports car",
  "A blue mountain lake",
  "A golden sunset over the ocean",
]);
```

## Guidelines

- Use `fal.subscribe()` for synchronous workflows (waits for completion, handles polling internally)
- Use `fal.queue.submit()` + webhooks for production async pipelines
- Flux Schnell is fastest (4 steps, ~2s); use for prototyping and bulk generation
- Flux Pro gives highest quality; use for final production images
- Always handle `onQueueUpdate` for user-facing apps to show progress
- Uploaded files are stored temporarily — download and persist to your own storage if needed
- Rate limits apply per API key; for high volume use the queue API to avoid timeouts
- Check `fal.ai/models` for the full list of available models (100+)
