> 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-pt/scenes-sdk7/media/audio-analysis.md).

# Análise de Áudio

Leia dados de amplitude e frequência em tempo real do áudio reproduzido na sua scene para acionar visuais reativos.

O `AudioAnalysis` component lê dados em tempo real de uma fonte de áudio a tocar na tua scene, para que possas conduzir os visuais a partir da música. Em cada frame, reporta um valor global de **amplitude** e **8 bandas de frequência** (de baixo para alto) que podes usar para escalar, colorir ou animar entities.

Usos comuns:

* Cubos que saltam ao ritmo do baixo.
* Luzes que pulsam com a batida.
* Visualizadores de barras ao estilo de um equalizador.
* Materiais reativos ou props dimensionados que acompanham a música.

`AudioAnalysis` é um fluxo só de leitura — a tua scene apenas consome os valores, e o runtime preenche-os. Funciona em entities que reproduzem áudio através de um [AudioSource](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/sounds.md), um [AudioStream](/creator/content-creator-pt/scenes-sdk7/media/audio-streaming.md), ou o áudio de um [VideoPlayer](/creator/content-creator-pt/scenes-sdk7/media/video-playing.md).

{% hint style="warning" %}
**📔 Observação**: `AudioAnalysis` é atualmente suportado apenas pela app desktop oficial da Decentraland. Noutros clients os valores do component nunca são preenchidos, por isso certifica-te de que a tua scene continua a funcionar se os dados nunca chegarem.
{% endhint %}

## Exemplo mínimo

A scene seguinte reproduz um som, anexa `AudioAnalysis` ao mesmo entity e escala um cubo em cada frame usando a amplitude do áudio.

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

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

  // Anexa AudioAnalysis ao mesmo entity para começar a receber dados de análise
  AudioAnalysis.createAudioAnalysis(audioEntity);

  // Um objeto de view reutilizável para o qual o component escreverá em cada frame
  const analysis: AudioAnalysisView = {
    amplitude: 0,
    bands: new Array<number>(8),
  };

  // Um cubo que pulsa com a amplitude do áudio
  const cube = engine.addEntity();
  MeshRenderer.setBox(cube);
  Transform.create(cube, { position: Vector3.create(8, 1, 8) });

  // Em cada frame, lê os valores de análise mais recentes e escala o cubo
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
    const s = 1 + analysis.amplitude * 10;
    Transform.getMutable(cube).scale = Vector3.create(s, s, s);
  });
}
```

As chamadas principais são:

1. `AudioAnalysis.createAudioAnalysis(entity)` — anexa o component ao entity que possui o `AudioSource`, `AudioStream`, ou `VideoPlayer`. O valor predefinido é o modo logarítmico (ver [Modos](#modes)).
2. `AudioAnalysis.readIntoView(entity, analysis)` — copia os valores mais recentes de `amplitude` e 8 `bandas` para um objeto de view que forneces.

{% hint style="warning" %}
**📔 Observação**: Prealoca sempre o `bandas` array com **8 elementos** antes de chamares `readIntoView`. O component não redimensiona o array por ti.
{% endhint %}

## Ler os dados em cada frame

`AudioAnalysis` foi concebido para ser lido uma vez por frame a partir de um system. O padrão recomendado é:

1. Aloca um único `AudioAnalysisView` objeto uma vez.
2. Num system, chama `readIntoView` para o atualizar.
3. Usa os valores diretamente ou partilha a view entre vários systems.

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

engine.addSystem(() => {
  AudioAnalysis.readIntoView(audioEntity, analysis);
  // analysis.amplitude e analysis.bands[0..7] contêm agora os valores mais recentes
});
```

Se o entity analisado ainda não tiver um `AudioAnalysis` component (por exemplo, é criado mais tarde ou removido dinamicamente), usa `tryReadIntoView` em vez disso. Devolve `false` quando o component estiver em falta, e `true` quando os valores foram escritos.

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

{% hint style="info" %}
**💡 Dica**: É mais barato chamar `readIntoView` uma vez e deixar que vários systems partilhem o mesmo objeto de view do que ler o component repetidamente.
{% endhint %}

## Reage a bandas de frequência específicas

As 8 bandas cobrem o espetro audível de baixo para alto. `bands[0]` é a mais baixa (bass) e `bands[7]` é a mais alta (treble). Podes controlar diferentes entities com diferentes bands para construir um equalizador clássico.

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

// Component personalizado para marcar cada barra e recordar qual banda ela segue
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),
  };

  // Cria 8 barras, uma 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() });
  }

  // Lê uma vez por frame
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
  });

  // Dimensiona cada barra com a sua 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
      );
    }
  });
}
```

Este é o mesmo padrão usado na [scene de exemplo de visualização de áudio](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/88,-10-audio-visualization), reduzida ao essencial.

## Modos

`AudioAnalysis` suporta dois modos de análise, definidos quando crias o component:

* `PBAudioAnalysisMode.MODE_LOGARITHMIC` (predefinição): os valores são escalados com uma curva logarítmica, que se aproxima mais da forma como a audição humana percebe alterações de volume. Ideal para reatividade visual.
* `PBAudioAnalysisMode.MODE_RAW`: a amplitude não processada e os valores das bandas FFT. Usa isto se quiseres aplicar a tua própria escala.

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

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

### Ajustar o modo logarítmico

No modo logarítmico podes passar dois multiplicadores de ganho opcionais:

* `amplitudeGain` — multiplicador aplicado à amplitude global. O valor predefinido é `5`.
* `bandsGain` — multiplicador aplicado a todas as 8 bandas. O valor predefinido é `0.05`.

Ganhos mais altos tornam os valores mais reativos; ganhos mais baixos tornam-nos mais subtis.

```ts
// Reação mais forte da amplitude, reação mais suave das bandas
AudioAnalysis.createAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_LOGARITHMIC,
  10, // amplitudeGain
  0.03 // bandsGain
);
```

{% hint style="warning" %}
**📔 Observação**: `amplitudeGain` e `bandsGain` só se aplicam no modo logarítmico. No modo raw são ignorados.
{% endhint %}

## Substituir um component existente

`createAudioAnalysis` falha se o entity já tiver um `AudioAnalysis` component. Para trocar modos ou ganhos em tempo de execução, usa `createOrReplaceAudioAnalysis`, que tem a mesma assinatura.

```ts
// Muda para o modo raw a meio da scene
AudioAnalysis.createOrReplaceAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_RAW
);
```

## Referência do component

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

Anexa um `AudioAnalysis` component para `entity`. Falha se já existir um component.

* `entity` (`Entity`): o entity que possui o `AudioSource`, `AudioStream`, ou `VideoPlayer` que queres analisar.
* `mode` (`PBAudioAnalysisMode`, opcional): `MODE_LOGARITHMIC` (predefinição) ou `MODE_RAW`.
* `amplitudeGain` (`number`, opcional): multiplicador de amplitude do modo logarítmico. Predefinição `5`.
* `bandsGain` (`number`, opcional): multiplicador de bandas do modo logarítmico. Predefinição `0.05`.

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

Igual ao anterior, mas substitui um `AudioAnalysis` component no entity em vez de falhar.

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

Lê os valores mais recentes para `out`. Lança erro se `entity` não tiver um `AudioAnalysis` component.

* `entity` (`Entity`): o entity com o component.
* `out` (`AudioAnalysisView`): um objeto de view que forneces. Deve ter `bandas` pré-alocado com 8 números.

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

Igual a `readIntoView`, mas devolve `false` se o entity não tiver um `AudioAnalysis` component em vez de lançar erro. Devolve `true` quando os valores são escritos.

### `AudioAnalysisView`

Um objeto simples que alocas para receber os dados de análise:

```ts
type AudioAnalysisView = {
  amplitude: number; // força global do sinal
  bands: number[]; // 8 bandas de frequência, de baixo (0) a alto (7)
};
```

## Notas e limitações

* **8 bands, fixas.** O número de bandas de frequência é fixo em 8. Não existe API para pedir mais ou menos bands.
* **Uma fonte de áudio por análise.** Cada `AudioAnalysis` component analisa o áudio do entity ao qual está anexado. Para analisar várias fontes, anexa `AudioAnalysis` a cada uma.
* **Streams de vídeo em direto não são analisados.** Existe um problema conhecido em que `AudioAnalysis` não recebe dados quando a `VideoPlayer` fonte é um stream não progressivo, como um `.m3u8` URL HLS: o áudio do stream é reproduzido, mas os valores de análise mantêm-se em zero. Ficheiros de vídeo (como `.mp4`) são analisados corretamente.
* **Áudio em pausa não reporta atualizações.** Quando o áudio subjacente é parado ou colocado em pausa, os valores do component deixam de mudar. Os últimos valores lidos permanecem no teu objeto de view até o áudio voltar a tocar.
* **Barato, mas não gratuito.** A análise por frame foi concebida para ser barata (sub-milisegundo por fonte no desktop). Evita anexar `AudioAnalysis` a demasiadas fontes ao mesmo tempo se não precisares dos dados. Remove o component quando um visualizador não estiver visível.


---

# 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-pt/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.
