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

# 오디오 분석

씬에서 재생 중인 오디오의 실시간 진폭 및 주파수 데이터를 읽어 반응형 비주얼을 구동합니다.

이 `AudioAnalysis` 구성 요소는 장면에서 재생 중인 오디오 소스에서 실시간 데이터를 읽어와, 음악으로 비주얼을 구동할 수 있게 합니다. 각 프레임마다 전체 **진폭** 값과 **8개의 주파수 대역** (낮은 것부터 높은 것까지)를 엔티티의 크기를 조절하거나, 색을 바꾸거나, 애니메이션을 적용하는 데 사용할 수 있습니다.

일반적인 용도:

* 베이스에 맞춰 튀는 큐브.
* 비트에 맞춰 맥동하는 조명.
* 이퀄라이저 스타일의 막대 시각화.
* 음악에 반응하는 머티리얼이나 크기가 조절되는 소품.

`AudioAnalysis` 읽기 전용 피드입니다 — 장면은 값만 소비하고, 런타임이 값을 채워 넣습니다. 이는 오디오를 재생하는 엔티티에서 작동합니다. 다음을 통해 [AudioSource](/creator/content-creator-ko/sdk7/3d/sounds.md), 그리고 [AudioStream](/creator/content-creator-ko/sdk7/media/audio-streaming.md), 또는 다음의 오디오 [VideoPlayer](/creator/content-creator-ko/sdk7/media/video-playing.md).

{% hint style="warning" %}
**📔 참고**: `AudioAnalysis` 현재는 공식 Decentraland 데스크톱 앱에서만 지원됩니다. 다른 클라이언트에서는 구성 요소의 값이 채워지지 않으므로, 데이터가 끝내 도착하지 않아도 장면이 계속 동작하는지 확인하세요.
{% endhint %}

## 최소 예제

다음 장면은 사운드를 재생하고, `AudioAnalysis` 를 같은 엔티티에 연결한 다음, 오디오의 진폭을 사용해 매 프레임 큐브의 크기를 조절합니다.

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

export function main() {
  // 엔티티에서 사운드 재생
  const audioEntity = engine.addEntity();
  Transform.create(audioEntity);
  AudioSource.create(audioEntity, {
    audioClipUrl: "sounds/music.mp3",
    playing: true,
    loop: true,
  });

  // 분석 데이터를 받기 시작하려면 같은 엔티티에 AudioAnalysis를 연결합니다
  AudioAnalysis.createAudioAnalysis(audioEntity);

  // 매 프레임마다 구성 요소가 값을 기록할 재사용 가능한 뷰 객체
  const analysis: AudioAnalysisView = {
    amplitude: 0,
    bands: new Array<number>(8),
  };

  // 오디오 진폭에 맞춰 맥동하는 큐브
  const cube = engine.addEntity();
  MeshRenderer.setBox(cube);
  Transform.create(cube, { position: Vector3.create(8, 1, 8) });

  // 매 프레임마다 최신 분석 값을 읽어 큐브의 크기를 조절합니다
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
    const s = 1 + analysis.amplitude * 10;
    Transform.getMutable(cube).scale = Vector3.create(s, s, s);
  });
}
```

핵심 호출은 다음과 같습니다:

1. `AudioAnalysis.createAudioAnalysis(entity)` — 해당 `AudioSource`, `AudioStream`또는 `VideoPlayer`를 소유한 엔티티에 구성 요소를 연결합니다. 기본값은 로그 모드입니다(참조 [모드](#modes)).
2. `AudioAnalysis.readIntoView(entity, analysis)` — 최신 `진폭` 및 8개의 `대역` 값을 제공한 뷰 객체에 복사합니다.

{% hint style="warning" %}
**📔 참고**: 항상 `대역` 배열을 **8개 요소로** 미리 할당한 뒤 `readIntoView`를 호출하세요. 구성 요소가 배열 크기를 대신 조정해 주지 않습니다.
{% endhint %}

## 매 프레임 데이터 읽기

`AudioAnalysis` 는 시스템에서 프레임당 한 번 읽도록 설계되었습니다. 권장 패턴은 다음과 같습니다:

1. 하나의 `AudioAnalysisView` 객체를 한 번만 할당합니다.
2. 시스템에서 `readIntoView` 를 호출해 새로 고칩니다.
3. 값을 직접 사용하거나, 여러 시스템이 같은 뷰를 공유하도록 하세요.

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

engine.addSystem(() => {
  AudioAnalysis.readIntoView(audioEntity, analysis);
  // analysis.amplitude 및 analysis.bands[0..7]에는 이제 최신 값이 들어 있습니다
});
```

분석 대상 엔티티에 아직 `AudioAnalysis` 구성 요소가 없을 수 있다면(예: 나중에 생성되거나 동적으로 제거되는 경우), 대신 `tryReadIntoView` 를 사용하세요. 이는 `false` 구성 요소가 없을 때는 `true` 을 반환하고, 값이 기록되었을 때는

```ts
engine.addSystem(() => {
  if (!AudioAnalysis.tryReadIntoView(audioEntity, analysis)) return;
  // 여기서 analysis를 안전하게 사용할 수 있습니다
});
```

{% hint style="info" %}
**💡 팁**: `readIntoView` 를 한 번 호출해 같은 뷰 객체를 여러 시스템이 공유하게 하는 것이, 구성 요소를 반복해서 읽는 것보다 더 저렴합니다.
{% endhint %}

## 특정 주파수 대역에 반응하기

8개 대역은 가청 스펙트럼을 낮은 것부터 높은 것까지 커버합니다. `bands[0]` 가 가장 낮은 값(베이스)이고 `bands[7]` 가 가장 높은 값(트레블)입니다. 다양한 엔티티를 서로 다른 대역으로 구동해 고전적인 이퀄라이저를 만들 수 있습니다.

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

// 각 막대를 표시하고 어떤 대역을 추적하는지 기억하는 사용자 정의 구성 요소
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),
  };

  // 대역별로 하나씩 8개의 막대를 만듭니다
  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() });
  }

  // 프레임당 한 번 읽기
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
  });

  // 각 막대를 해당 대역에 맞춰 스케일 조정
  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
      );
    }
  });
}
```

이는 [오디오 시각화 예제 씬](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/88,-10-audio-visualization)에서 사용된 것과 같은 패턴이며, 핵심만 남겼습니다.

## 모드

`AudioAnalysis` 를 생성할 때 설정하는 두 가지 분석 모드를 지원합니다:

* `PBAudioAnalysisMode.MODE_LOGARITHMIC` (기본값): 값은 로그 곡선으로 스케일되며, 이는 사람이 음량 변화를 인지하는 방식에 더 가깝습니다. 시각적 반응성에 가장 적합합니다.
* `PBAudioAnalysisMode.MODE_RAW`: 가공되지 않은 진폭과 FFT 대역 값입니다. 직접 스케일링을 적용하고 싶을 때 사용하세요.

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

// 원시 값 사용
AudioAnalysis.createAudioAnalysis(audioEntity, PBAudioAnalysisMode.MODE_RAW);
```

### 로그 모드 조정하기

로그 모드에서는 두 개의 선택적 게인 배율을 전달할 수 있습니다:

* `amplitudeGain` — 전체 진폭에 적용되는 배율입니다. 기본값은 `5`.
* `bandsGain` — 8개 대역 전체에 적용되는 배율입니다. 기본값은 `0.05`.

게인이 높을수록 값이 더 민감하게 반응하고, 낮을수록 더 미묘해집니다.

```ts
// 더 강한 진폭 반응, 더 부드러운 대역 반응
AudioAnalysis.createAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_LOGARITHMIC,
  10, // amplitudeGain
  0.03 // bandsGain
);
```

{% hint style="warning" %}
**📔 참고**: `amplitudeGain` 과 `bandsGain` 는 로그 모드에서만 적용됩니다. raw 모드에서는 무시됩니다.
{% endhint %}

## 기존 구성 요소 교체

`createAudioAnalysis` 는 엔티티에 이미 `AudioAnalysis` 구성 요소가 있으면 실패합니다. 런타임에 모드나 게인을 바꾸려면 `createOrReplaceAudioAnalysis`를 사용하세요. 시그니처는 같습니다.

```ts
// 장면 도중 raw 모드로 전환
AudioAnalysis.createOrReplaceAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_RAW
);
```

## 구성 요소 참조

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

다음을 부착합니다 `AudioAnalysis` 구성 요소의 값을 `엔티티`. 구성 요소가 이미 있으면 실패합니다.

* `엔티티` (`Entity`): 다음을 소유한 엔티티 `AudioSource`, `AudioStream`또는 `VideoPlayer` 분석하려는
* `mode` (`PBAudioAnalysisMode`, 선택 사항): `MODE_LOGARITHMIC` (기본값) 또는 `MODE_RAW`.
* `amplitudeGain` (`number`, 선택 사항): 로그 모드 진폭 배율입니다. 기본값 `5`.
* `bandsGain` (`number`, 선택 사항): 로그 모드 대역 배율입니다. 기본값 `0.05`.

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

위와 같지만, 기존 `AudioAnalysis` 구성 요소를 실패 대신 엔티티에서 교체합니다.

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

최신 값을 `out`에 읽어들입니다. 다음이면 예외를 던집니다 `엔티티` 에 `AudioAnalysis` 컴포넌트를 추가해야 합니다.

* `엔티티` (`Entity`): 구성 요소가 있는 엔티티
* `out` (`AudioAnalysisView`): 제공하는 뷰 객체입니다. 8개의 숫자로 `대역` 미리 할당되어 있어야 합니다.

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

다음과 동일하지만 `readIntoView`, `false` 엔티티에 `AudioAnalysis` 구성 요소가 없으면 예외를 던지지 않고 `true` 값이 기록되면

### `AudioAnalysisView`

분석 데이터를 받기 위해 직접 할당하는 일반 객체:

```ts
type AudioAnalysisView = {
  amplitude: number; // 전체 신호 강도
  bands: number[]; // 8개의 주파수 대역, 낮음(0)에서 높음(7)까지
};
```

## 참고 및 제한 사항

* **8개 대역, 고정.** 주파수 대역 수는 8로 고정되어 있습니다. 더 많거나 적은 대역을 요청하는 API는 없습니다.
* **분석당 오디오 소스 하나.** 각 `AudioAnalysis` 구성 요소는 연결된 엔티티의 오디오를 분석합니다. 여러 소스를 분석하려면 `AudioAnalysis` 를 각각에 연결하세요.
* **실시간 비디오 스트림은 분석되지 않습니다.** 다음과 같은 알려진 문제가 있습니다 `AudioAnalysis` 다음일 때 데이터를 받지 못합니다 `VideoPlayer` 소스가 다음과 같은 비진행형 스트림인 경우 `.m3u8` HLS URL: 스트림 오디오는 재생되지만, 분석 값은 0으로 유지됩니다. 다음과 같은 비디오 파일은 `.mp4`는 올바르게 분석됩니다.
* **일시 중지된 오디오는 업데이트를 보고하지 않습니다.** 기저 오디오가 중지되거나 일시 중지되면 구성 요소 값의 변화도 멈춥니다. 마지막으로 읽은 값은 오디오가 다시 재생될 때까지 뷰 객체에 남아 있습니다.
* **저렴하지만 공짜는 아닙니다.** 프레임별 분석은 비용이 적게 들도록 설계되었습니다(데스크톱에서는 소스당 1밀리초 미만). `AudioAnalysis` 데이터가 필요하지 않다면 한 번에 너무 많은 소스에 연결하지 마세요. 시각화 도구가 보이지 않을 때는 구성 요소를 제거하세요.


---

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