> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/media/audio-analysis.md).

# Análisis de audio

Lee datos de amplitud y frecuencia en tiempo real del audio que se reproduce en tu escena para impulsar visuales reactivos.

El `AudioAnalysis` componente lee datos en tiempo real de una fuente de audio que se reproduce en tu escena, para que puedas controlar elementos visuales con la música. En cada frame, informa un **amplitud** valor y **8 bandas de frecuencia** (de bajas a altas) que puedes usar para escalar, colorear o animar entidades.

Usos comunes:

* Cubos que rebotan con el bajo.
* Luces que pulsan con el ritmo.
* Visualizadores de barras al estilo ecualizador.
* Materiales reactivos o props escalados que coinciden con la música.

`AudioAnalysis` es un feed de solo lectura: tu escena solo consume los valores, el runtime los completa. Funciona en entidades que reproducen audio a través de un [AudioSource](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/sounds.md), un [AudioStream](/creator/content-creator-es/scenes-sdk7/media/audio-streaming.md), o el audio de un [VideoPlayer](/creator/content-creator-es/scenes-sdk7/media/video-playing.md).

{% hint style="warning" %}
**📔 Nota**: `AudioAnalysis` actualmente solo es compatible con la app de escritorio oficial de Decentraland. En otros clientes, los valores del componente nunca se completan, así que asegúrate de que tu escena siga funcionando aunque los datos nunca lleguen.
{% endhint %}

## Ejemplo mínimo

La siguiente escena reproduce un sonido, adjunta `AudioAnalysis` al mismo entity, y escala un cubo en cada frame usando la amplitud del audio.

```ts
import {
  engine,
  Transform,
  MeshRenderer,
  AudioSource,
  AudioAnalysis,
  AudioAnalysisView,
} from "@dcl/sdk/ecs";
import { Vector3 } from "@dcl/sdk/math";

export function main() {
  // Reproduce un sonido en una entidad
  const audioEntity = engine.addEntity();
  Transform.create(audioEntity);
  AudioSource.create(audioEntity, {
    audioClipUrl: "sounds/music.mp3",
    playing: true,
    loop: true,
  });

  // Adjunta AudioAnalysis a la misma entidad para empezar a recibir datos de análisis
  AudioAnalysis.createAudioAnalysis(audioEntity);

  // Un objeto de vista reutilizable en el que el componente escribirá en cada frame
  const analysis: AudioAnalysisView = {
    amplitude: 0,
    bands: new Array<number>(8),
  };

  // Un cubo que pulsa con la amplitud del audio
  const cube = engine.addEntity();
  MeshRenderer.setBox(cube);
  Transform.create(cube, { position: Vector3.create(8, 1, 8) });

  // En cada frame, lee los valores de análisis más recientes y escala el cubo
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
    const s = 1 + analysis.amplitude * 10;
    Transform.getMutable(cube).scale = Vector3.create(s, s, s);
  });
}
```

Las llamadas clave son:

1. `AudioAnalysis.createAudioAnalysis(entity)` — adjunta el componente a la entidad que posee el `AudioSource`, `AudioStream`, o `VideoPlayer` . De forma predeterminada usa el modo logarítmico (consulta [Modos](#modes)).
2. `AudioAnalysis.readIntoView(entity, analysis)` — copia el último `amplitud` y 8 `bandas` valores en un objeto de vista que tú proporcionas.

{% hint style="warning" %}
**📔 Nota**: Siempre preasigna el `bandas` array con **8 elementos** antes de llamar a `readIntoView`. El componente no redimensiona el array por ti.
{% endhint %}

## Leyendo los datos en cada frame

`AudioAnalysis` está diseñado para leerse una vez por frame desde un sistema. El patrón recomendado es:

1. Asigna un único `AudioAnalysisView` objeto una vez.
2. En un sistema, llama a `readIntoView` para actualizarlo.
3. Usa los valores directamente o comparte la vista entre varios sistemas.

```ts
const analysis: AudioAnalysisView = {
  amplitude: 0,
  bands: new Array<number>(8),
};

engine.addSystem(() => {
  AudioAnalysis.readIntoView(audioEntity, analysis);
  // analysis.amplitude y analysis.bands[0..7] ahora contienen los valores más recientes
});
```

Si la entidad analizada todavía no tiene un `AudioAnalysis` componente (por ejemplo, se crea más tarde o se elimina de forma dinámica), usa `tryReadIntoView` en su lugar. Devuelve `false` cuando el componente falta, y `true` cuando se escribieron valores.

```ts
engine.addSystem(() => {
  if (!AudioAnalysis.tryReadIntoView(audioEntity, analysis)) return;
  // seguro para usar analysis aquí
});
```

{% hint style="info" %}
**💡 Consejo** : Es más barato llamar a `readIntoView` una vez y dejar que varios sistemas compartan el mismo objeto de vista que leer el componente repetidamente.
{% endhint %}

## Reacciona a bandas de frecuencia específicas

Las 8 bandas cubren el espectro audible de bajas a altas. `bands[0]` es la más baja (bajo) y `bands[7]` es la más alta (agudos). Puedes controlar distintas entidades con distintas bandas para construir un ecualizador clásico.

```ts
import {
  engine,
  Transform,
  MeshRenderer,
  Material,
  AudioSource,
  AudioAnalysis,
  AudioAnalysisView,
  Schemas,
} from "@dcl/sdk/ecs";
import { Color4, Vector3 } from "@dcl/sdk/math";

// Componente personalizado para marcar cada barra y recordar qué banda sigue
const VisualBar = engine.defineComponent("visual-bar", {
  index: Schemas.Number,
});

const BARS_HEIGHT = 12;

export function main() {
  const audioEntity = engine.addEntity();
  Transform.create(audioEntity);
  AudioSource.create(audioEntity, {
    audioClipUrl: "sounds/music.mp3",
    playing: true,
    loop: true,
  });
  AudioAnalysis.createAudioAnalysis(audioEntity);

  const analysis: AudioAnalysisView = {
    amplitude: 0,
    bands: new Array<number>(8),
  };

  // Crea 8 barras, una por banda
  for (let i = 0; i < 8; i++) {
    const bar = engine.addEntity();
    VisualBar.create(bar, { index: i });
    Transform.create(bar, { position: Vector3.create(4 + i, 0, 8) });
    MeshRenderer.setBox(bar);
    Material.setPbrMaterial(bar, { albedoColor: Color4.Yellow() });
  }

  // Leer una vez por frame
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
  });

  // Escala cada barra con su banda
  engine.addSystem(() => {
    for (const [entity] of engine.getEntitiesWith(VisualBar, Transform)) {
      const index = VisualBar.get(entity).index;
      const transform = Transform.getMutable(entity);
      transform.scale = Vector3.create(
        1,
        analysis.bands[index] * BARS_HEIGHT,
        1
      );
    }
  });
}
```

Es el mismo patrón usado en la [escena de ejemplo de visualización de audio](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/88,-10-audio-visualization), reducido a lo esencial.

## Modos

`AudioAnalysis` admite dos modos de análisis, establecidos cuando creas el componente:

* `PBAudioAnalysisMode.MODE_LOGARITHMIC` (predeterminado): los valores se escalan con una curva logarítmica, que se siente más cercana a cómo el oído humano percibe los cambios de volumen. Mejor para la reactividad visual.
* `PBAudioAnalysisMode.MODE_RAW`: la amplitud sin procesar y los valores de banda FFT. Usa esto si quieres aplicar tu propio escalado.

```ts
import { AudioAnalysis, PBAudioAnalysisMode } from "@dcl/sdk/ecs";

// Usa valores sin procesar
AudioAnalysis.createAudioAnalysis(audioEntity, PBAudioAnalysisMode.MODE_RAW);
```

### Ajuste del modo logarítmico

En modo logarítmico puedes pasar dos multiplicadores de ganancia opcionales:

* `amplitudeGain` — multiplicador aplicado a la amplitud global. Por defecto `5`.
* `bandsGain` — multiplicador aplicado a las 8 bandas. Por defecto `0.05`.

Las ganancias más altas hacen que los valores sean más reactivos; las más bajas los hacen más sutiles.

```ts
// Respuesta de amplitud más fuerte, respuesta de banda más suave
AudioAnalysis.createAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_LOGARITHMIC,
  10, // amplitudeGain
  0.03 // bandsGain
);
```

{% hint style="warning" %}
**📔 Nota**: `amplitudeGain` y `bandsGain` solo se aplican en modo logarítmico. En modo raw se ignoran.
{% endhint %}

## Reemplaza un componente existente

`createAudioAnalysis` falla si la entidad ya tiene un `AudioAnalysis` componente. Para cambiar de modo o de ganancias en tiempo de ejecución, usa `createOrReplaceAudioAnalysis`, que tiene la misma firma.

```ts
// Cambia a modo raw a mitad de la escena
AudioAnalysis.createOrReplaceAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_RAW
);
```

## Referencia del componente

### `AudioAnalysis.createAudioAnalysis(entity, mode?, amplitudeGain?, bandsGain?)`

Adjunta un `AudioAnalysis` componente en `entidad`. Falla si ya hay un componente presente.

* `entidad` (`Entity`): la entidad que posee el `AudioSource`, `AudioStream`, o `VideoPlayer` que quieres analizar.
* `modo` (`PBAudioAnalysisMode`, opcional): `MODE_LOGARITHMIC` (predeterminado) o `MODE_RAW`.
* `amplitudeGain` (`number`, opcional): multiplicador de amplitud en modo logarítmico. Por defecto `5`.
* `bandsGain` (`number`, opcional): multiplicador de bandas en modo logarítmico. Por defecto `0.05`.

### `AudioAnalysis.createOrReplaceAudioAnalysis(entity, mode?, amplitudeGain?, bandsGain?)`

Igual que arriba, pero reemplaza un `AudioAnalysis` componente existente en la entidad en lugar de fallar.

### `AudioAnalysis.readIntoView(entity, out)`

Lee los valores más recientes en `out`. Lanza un error si `entidad` no tiene un `AudioAnalysis` componente.

* `entidad` (`Entity`): la entidad con el componente.
* `out` (`AudioAnalysisView`): un objeto de vista que proporcionas. Debe tener `bandas` preasignado con 8 números.

### `AudioAnalysis.tryReadIntoView(entity, out): boolean`

Igual que `readIntoView`, pero devuelve `false` si la entidad no tiene un `AudioAnalysis` componente en lugar de lanzar un error. Devuelve `true` cuando se escriben valores.

### `AudioAnalysisView`

Un objeto simple que asignas para recibir los datos del análisis:

```ts
type AudioAnalysisView = {
  amplitude: number; // fuerza general de la señal
  bands: number[]; // 8 bandas de frecuencia, de bajas (0) a altas (7)
};
```

## Notas y limitaciones

* **8 bandas, fijas.** El número de bandas de frecuencia está fijo en 8. No hay API para pedir más o menos bandas.
* **Una fuente de audio por análisis.** Cada `AudioAnalysis` componente analiza el audio de la entidad a la que está adjunto. Para analizar varias fuentes, adjunta `AudioAnalysis` a cada una.
* **Los streams de video en vivo no se analizan.** Hay un problema conocido en el que `AudioAnalysis` no recibe datos cuando la `VideoPlayer` fuente es un stream no progresivo, como una `.m3u8` URL HLS: el audio del stream se reproduce, pero los valores de análisis se quedan en cero. Los archivos de video (como `.mp4`) se analizan correctamente.
* **El audio en pausa no reporta actualizaciones.** Cuando el audio subyacente se detiene o se pausa, los valores del componente dejan de cambiar. Los últimos valores leídos permanecen en tu objeto de vista hasta que el audio vuelva a reproducirse.
* **Barato, pero no gratis.** El análisis por frame está diseñado para ser poco costoso (menos de un milisegundo por fuente en escritorio). Evita adjuntar `AudioAnalysis` a demasiadas fuentes a la vez si no necesitas los datos. Elimina el componente cuando un visualizador no sea visible.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/media/audio-analysis.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
